diff --git a/CustomKeyboard/CustomKeyboard.entitlements b/CustomKeyboard/CustomKeyboard.entitlements new file mode 100644 index 0000000..89f84e3 --- /dev/null +++ b/CustomKeyboard/CustomKeyboard.entitlements @@ -0,0 +1,11 @@ + + + + + keychain-access-groups + + $(AppIdentifierPrefix)com.keyBoardst.shared + + + + diff --git a/CustomKeyboard/KeyboardViewController.m b/CustomKeyboard/KeyboardViewController.m index a55d484..320d2bf 100644 --- a/CustomKeyboard/KeyboardViewController.m +++ b/CustomKeyboard/KeyboardViewController.m @@ -6,74 +6,215 @@ // #import "KeyboardViewController.h" +#import "KBKeyBoardMainView.h" -static CGFloat KEYBOARDHEIGHT = 256; +#import "KBKey.h" +#import "KBFunctionView.h" +#import "KBSettingView.h" +#import "Masonry.h" +#import "KBAuthManager.h" +#import "KBFullAccessManager.h" -@interface KeyboardViewController () -@property (nonatomic, strong) UIButton *nextKeyboardButton; +static CGFloat KEYBOARDHEIGHT = 256 + 20; + +@interface KeyboardViewController () +@property (nonatomic, strong) UIButton *nextKeyboardButton; // 系统“下一个键盘”按钮(可选) +@property (nonatomic, strong) KBKeyBoardMainView *keyBoardMainView; // 功能面板视图(点击工具栏第0个时显示) +@property (nonatomic, strong) KBFunctionView *functionView; // 功能面板视图(点击工具栏第0个时显示) +@property (nonatomic, strong) KBSettingView *settingView; // 设置页 @end @implementation KeyboardViewController -- (void)updateViewConstraints { - [super updateViewConstraints]; - - // Add custom view sizing constraints here +{ + BOOL _kb_didTriggerLoginDeepLinkOnce; } - (void)viewDidLoad { [super viewDidLoad]; -// -// // Perform custom UI setup here -// self.nextKeyboardButton = [UIButton buttonWithType:UIButtonTypeSystem]; -// -// [self.nextKeyboardButton setTitle:NSLocalizedString(@"Next Keyboard", @"Title for 'Next Keyboard' button") forState:UIControlStateNormal]; -// [self.nextKeyboardButton sizeToFit]; -// self.nextKeyboardButton.translatesAutoresizingMaskIntoConstraints = NO; -// -// [self.nextKeyboardButton addTarget:self action:@selector(handleInputModeListFromView:withEvent:) forControlEvents:UIControlEventAllTouchEvents]; -// -// [self.view addSubview:self.nextKeyboardButton]; -// -// [self.nextKeyboardButton.leftAnchor constraintEqualToAnchor:self.view.leftAnchor].active = YES; -// [self.nextKeyboardButton.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor].active = YES; - [self setupUI]; + // 指定 HUD 的承载视图(扩展里无法取到 App 的 KeyWindow) + [KBHUD setContainerView:self.view]; + // 绑定完全访问管理器,便于统一感知和联动网络开关 + [[KBFullAccessManager shared] bindInputController:self]; + __unused id token = [[NSNotificationCenter defaultCenter] addObserverForName:KBFullAccessChangedNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(__unused NSNotification * _Nonnull note) { + // 如需,可在此刷新与完全访问相关的 UI + }]; } - (void)setupUI { - CGFloat toolBarHeight = 40; - CGFloat bottom = 5; - CGFloat buttonSpace = 8; - CGFloat eachButtonHeight = (KEYBOARDHEIGHT - toolBarHeight - 10 - 8 * 3 - bottom) / 4; + // 固定键盘整体高度 + [self.view.heightAnchor constraintEqualToConstant:KEYBOARDHEIGHT].active = YES; + // 预置功能面板(默认隐藏),与键盘区域共享相同布局 + self.functionView.hidden = YES; + [self.view addSubview:self.functionView]; + [self.functionView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.equalTo(self.view); + make.top.equalTo(self.view).offset(4); + make.bottom.equalTo(self.view.mas_bottom).offset(-4); + }]; - UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, 30)]; - view.backgroundColor = [UIColor redColor]; - [self.view addSubview:view]; + [self.view addSubview:self.keyBoardMainView]; + [self.keyBoardMainView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.equalTo(self.view); + make.top.equalTo(self.view).offset(4); + make.bottom.equalTo(self.view.mas_bottom).offset(-4); + }]; } -- (void)viewWillLayoutSubviews -{ - self.nextKeyboardButton.hidden = !self.needsInputModeSwitchKey; - [super viewWillLayoutSubviews]; -} -- (void)textWillChange:(id)textInput { - // The app is about to change the document's contents. Perform any preparation here. -} +#pragma mark - Private -- (void)textDidChange:(id)textInput { - // The app has just changed the document's contents, the document context has been updated. +/// 切换显示功能面板/键盘主视图 +- (void)showFunctionPanel:(BOOL)show { + // 简单显隐切换,复用相同的布局区域 + self.functionView.hidden = !show; + self.keyBoardMainView.hidden = show; - UIColor *textColor = nil; - if (self.textDocumentProxy.keyboardAppearance == UIKeyboardAppearanceDark) { - textColor = [UIColor whiteColor]; + // 可选:把当前显示的视图置顶,避免层级遮挡 + if (show) { + [self.view bringSubviewToFront:self.functionView]; } else { - textColor = [UIColor blackColor]; + [self.view bringSubviewToFront:self.keyBoardMainView]; } - [self.nextKeyboardButton setTitleColor:textColor forState:UIControlStateNormal]; } +/// 显示/隐藏设置页(高度与 keyBoardMainView 一致),右侧滑入/滑出 +- (void)showSettingView:(BOOL)show { + if (show) { + // if (!self.settingView) { + self.settingView = [[KBSettingView alloc] init]; + self.settingView.hidden = YES; + [self.view addSubview:self.settingView]; + [self.settingView mas_makeConstraints:^(MASConstraintMaker *make) { + // 与键盘主视图完全等同的区域,保证高度、宽度一致 + make.edges.equalTo(self.keyBoardMainView); + }]; + [self.settingView.backButton addTarget:self action:@selector(onTapSettingsBack) forControlEvents:UIControlEventTouchUpInside]; + // } + [self.view bringSubviewToFront:self.settingView]; + // 以 keyBoardMainView 的实际宽度为准,避免首次添加时 self.view 宽度尚未计算 + [self.view layoutIfNeeded]; + CGFloat w = CGRectGetWidth(self.keyBoardMainView.bounds); + if (w <= 0) { w = CGRectGetWidth(self.view.bounds); } + if (w <= 0) { w = [UIScreen mainScreen].bounds.size.width; } + self.settingView.transform = CGAffineTransformMakeTranslation(w, 0); + self.settingView.hidden = NO; + [UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{ + self.settingView.transform = CGAffineTransformIdentity; + } completion:nil]; + } else { + if (!self.settingView || self.settingView.hidden) return; + CGFloat w = CGRectGetWidth(self.keyBoardMainView.bounds); + if (w <= 0) { w = CGRectGetWidth(self.view.bounds); } + if (w <= 0) { w = [UIScreen mainScreen].bounds.size.width; } + [UIView animateWithDuration:0.22 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{ + self.settingView.transform = CGAffineTransformMakeTranslation(w, 0); + } completion:^(BOOL finished) { + self.settingView.hidden = YES; + }]; + } +} + + + +// MARK: - KBKeyBoardMainViewDelegate +- (void)keyBoardMainView:(KBKeyBoardMainView *)keyBoardMainView didTapKey:(KBKey *)key { + switch (key.type) { + case KBKeyTypeCharacter: + [self.textDocumentProxy insertText:key.output ?: key.title ?: @""]; break; + case KBKeyTypeBackspace: + [self.textDocumentProxy deleteBackward]; break; + case KBKeyTypeSpace: + [self.textDocumentProxy insertText:@" "]; break; + case KBKeyTypeReturn: + [self.textDocumentProxy insertText:@"\n"]; break; + case KBKeyTypeGlobe: + [self advanceToNextInputMode]; break; + case KBKeyTypeCustom: + // 点击自定义键(如“AI”)切换到功能面板 + [self showFunctionPanel:YES]; + break; + case KBKeyTypeModeChange: + case KBKeyTypeShift: + // 这些已在 KBKeyBoardMainView/KBKeyboardView 内部处理 + break; + } +} + +- (void)keyBoardMainView:(KBKeyBoardMainView *)keyBoardMainView didTapToolActionAtIndex:(NSInteger)index { + if (index == 0) { + [self showFunctionPanel:YES]; + } else { + [self showFunctionPanel:NO]; + } +} + +- (void)keyBoardMainViewDidTapSettings:(KBKeyBoardMainView *)keyBoardMainView { + [self showSettingView:YES]; +} + +// MARK: - KBFunctionViewDelegate +- (void)functionView:(KBFunctionView *)functionView didTapToolActionAtIndex:(NSInteger)index { + // 需求:当 index == 0 时,切回键盘主视图 + if (index == 0) { + [self showFunctionPanel:NO]; + } +} + +#pragma mark - lazy +- (KBKeyBoardMainView *)keyBoardMainView{ + if (!_keyBoardMainView) { + _keyBoardMainView = [[KBKeyBoardMainView alloc] init]; + _keyBoardMainView.delegate = self; + } + return _keyBoardMainView; +} + +- (KBFunctionView *)functionView{ + if (!_functionView) { + _functionView = [[KBFunctionView alloc] init]; + _functionView.delegate = self; // 监听功能面板顶部Bar点击 + } + return _functionView; +} + +- (KBSettingView *)settingView { + if (!_settingView) { + _settingView = [[KBSettingView alloc] init]; + } + return _settingView; +} + + +#pragma mark - Actions + +- (void)onTapSettingsBack { + [self showSettingView:NO]; +} + + +// 当键盘第一次显示时,尝试唤起主 App 以提示登录(由主 App 决定是否真的弹登录)。 +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + if (!_kb_didTriggerLoginDeepLinkOnce) { + _kb_didTriggerLoginDeepLinkOnce = YES; + // 仅在未登录时尝试拉起主App登录 + if (!KBAuthManager.shared.isLoggedIn) { + [self kb_tryOpenContainerForLoginIfNeeded]; + } + } +} + +- (void)kb_tryOpenContainerForLoginIfNeeded { + NSURL *url = [NSURL URLWithString:@"kbkeyboard://login?src=keyboard"]; + if (!url) return; + __weak typeof(self) weakSelf = self; + [self.extensionContext openURL:url completionHandler:^(__unused BOOL success) { + // 即使失败也不重复尝试;避免打扰。 + __unused typeof(weakSelf) selfStrong = weakSelf; + }]; +} @end diff --git a/CustomKeyboard/Manager/KBFullAccessManager.h b/CustomKeyboard/Manager/KBFullAccessManager.h new file mode 100644 index 0000000..14b1441 --- /dev/null +++ b/CustomKeyboard/Manager/KBFullAccessManager.h @@ -0,0 +1,43 @@ +// +// KBFullAccessManager.h +// 统一封装:检测并管理键盘扩展的“允许完全访问”状态 +// + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSInteger, KBFullAccessState) { + KBFullAccessStateUnknown = 0, // 无法确定(降级处理为未开启) + KBFullAccessStateDenied, // 未开启完全访问 + KBFullAccessStateGranted // 已开启完全访问 +}; + +/// 状态变更通知(仅扩展进程内广播) +extern NSNotificationName const KBFullAccessChangedNotification; + +/// 键盘扩展“完全访问”状态管理 +@interface KBFullAccessManager : NSObject + ++ (instancetype)shared; + +/// 绑定当前的 UIInputViewController(用于调用系统私有选择器 hasFullAccess;按字符串反射,避免编译期引用) +- (void)bindInputController:(UIInputViewController *)ivc; + +/// 当前状态(内部做缓存;如需强制刷新,调用 refresh) +- (KBFullAccessState)currentState; + +/// 便捷判断 +- (BOOL)hasFullAccess; + +/// 立即刷新一次状态(若状态有变化会发送 KBFullAccessChangedNotification) +- (void)refresh; + +/// 若未开启,则在传入视图上展示引导弹层(使用现有的 KBFullAccessGuideView);返回是否已开启 +- (BOOL)ensureFullAccessOrGuideInView:(UIView *)parent; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/CustomKeyboard/Manager/KBFullAccessManager.m b/CustomKeyboard/Manager/KBFullAccessManager.m new file mode 100644 index 0000000..ed788ad --- /dev/null +++ b/CustomKeyboard/Manager/KBFullAccessManager.m @@ -0,0 +1,100 @@ +// +// KBFullAccessManager.m +// +// 统一封装“允许完全访问”检测: +// 1) 首选:反射调用 UIInputViewController 的 hasFullAccess(避免直接引用私有 API 标识) +// 2) 兜底:无法判断时返回 Unknown(上层可按需降级为 Denied 并提示) +// + +#import "KBFullAccessManager.h" +#import +#if __has_include("KBNetworkManager.h") +#import "KBNetworkManager.h" +#endif +#if __has_include("KBKeyboardPermissionManager.h") +#import "KBKeyboardPermissionManager.h" +#endif + +NSNotificationName const KBFullAccessChangedNotification = @"KBFullAccessChangedNotification"; + +@interface KBFullAccessManager () +@property (nonatomic, weak) UIInputViewController *ivc; +@property (nonatomic, assign) KBFullAccessState state; +@end + +@implementation KBFullAccessManager + ++ (instancetype)shared { + static KBFullAccessManager *m; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ m = [KBFullAccessManager new]; }); + return m; +} + +- (instancetype)init { + if (self = [super init]) { + _state = KBFullAccessStateUnknown; + } + return self; +} + +- (void)bindInputController:(UIInputViewController *)ivc { + self.ivc = ivc; + [self refresh]; +} + +- (KBFullAccessState)currentState { return _state; } + +- (BOOL)hasFullAccess { return self.state == KBFullAccessStateGranted; } + +- (void)refresh { + KBFullAccessState newState = [self p_detectFullAccessState]; + if (newState != self.state) { + self.state = newState; + [[NSNotificationCenter defaultCenter] postNotificationName:KBFullAccessChangedNotification object:nil]; + [self p_applySideEffects]; + } +} + +- (BOOL)ensureFullAccessOrGuideInView:(UIView *)parent { + [self refresh]; + if (self.state == KBFullAccessStateGranted) return YES; +#if __has_include("KBFullAccessGuideView.h") + // 动态引入,避免主 App 编译引用 + Class guideCls = NSClassFromString(@"KBFullAccessGuideView"); + if (guideCls && [guideCls respondsToSelector:NSSelectorFromString(@"showInView:")]) { + SEL sel = NSSelectorFromString(@"showInView:"); + ((void (*)(id, SEL, UIView *))objc_msgSend)(guideCls, sel, parent); + } +#endif + return NO; +} + +#pragma mark - Detect + +// 通过反射调用 hasFullAccess(若系统提供),否则返回 Unknown +- (KBFullAccessState)p_detectFullAccessState { + UIInputViewController *ivc = self.ivc; + if (!ivc) return KBFullAccessStateUnknown; + + SEL sel = NSSelectorFromString(@"hasFullAccess"); + if ([ivc respondsToSelector:sel]) { + BOOL granted = ((BOOL (*)(id, SEL))objc_msgSend)(ivc, sel); + return granted ? KBFullAccessStateGranted : KBFullAccessStateDenied; + } + // 无法判断时标记 Unknown(上层可按需处理为未开启) + return KBFullAccessStateUnknown; +} + +#pragma mark - Side Effects + +- (void)p_applySideEffects { +#if __has_include("KBNetworkManager.h") + // 根据完全访问状态切换网络总开关 + [KBNetworkManager shared].enabled = (self.state == KBFullAccessStateGranted); +#endif +#if __has_include("KBKeyboardPermissionManager.h") + // 上报给主 App:记录最近一次“完全访问”状态(App 将据此决定是否展示引导页) + [[KBKeyboardPermissionManager shared] reportFullAccessFromExtension:(self.state == KBFullAccessStateGranted)]; +#endif +} + +@end diff --git a/CustomKeyboard/Masonry/Masonry/MASCompositeConstraint.h b/CustomKeyboard/Masonry/Masonry/MASCompositeConstraint.h deleted file mode 100755 index 934c6f1..0000000 --- a/CustomKeyboard/Masonry/Masonry/MASCompositeConstraint.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// MASCompositeConstraint.h -// Masonry -// -// Created by Jonas Budelmann on 21/07/13. -// Copyright (c) 2013 cloudling. All rights reserved. -// - -#import "MASConstraint.h" -#import "MASUtilities.h" - -/** - * A group of MASConstraint objects - */ -@interface MASCompositeConstraint : MASConstraint - -/** - * Creates a composite with a predefined array of children - * - * @param children child MASConstraints - * - * @return a composite constraint - */ -- (id)initWithChildren:(NSArray *)children; - -@end diff --git a/CustomKeyboard/Masonry/Masonry/MASCompositeConstraint.m b/CustomKeyboard/Masonry/Masonry/MASCompositeConstraint.m deleted file mode 100755 index 2002a40..0000000 --- a/CustomKeyboard/Masonry/Masonry/MASCompositeConstraint.m +++ /dev/null @@ -1,183 +0,0 @@ -// -// MASCompositeConstraint.m -// Masonry -// -// Created by Jonas Budelmann on 21/07/13. -// Copyright (c) 2013 cloudling. All rights reserved. -// - -#import "MASCompositeConstraint.h" -#import "MASConstraint+Private.h" - -@interface MASCompositeConstraint () - -@property (nonatomic, strong) id mas_key; -@property (nonatomic, strong) NSMutableArray *childConstraints; - -@end - -@implementation MASCompositeConstraint - -- (id)initWithChildren:(NSArray *)children { - self = [super init]; - if (!self) return nil; - - _childConstraints = [children mutableCopy]; - for (MASConstraint *constraint in _childConstraints) { - constraint.delegate = self; - } - - return self; -} - -#pragma mark - MASConstraintDelegate - -- (void)constraint:(MASConstraint *)constraint shouldBeReplacedWithConstraint:(MASConstraint *)replacementConstraint { - NSUInteger index = [self.childConstraints indexOfObject:constraint]; - NSAssert(index != NSNotFound, @"Could not find constraint %@", constraint); - [self.childConstraints replaceObjectAtIndex:index withObject:replacementConstraint]; -} - -- (MASConstraint *)constraint:(MASConstraint __unused *)constraint addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute { - id strongDelegate = self.delegate; - MASConstraint *newConstraint = [strongDelegate constraint:self addConstraintWithLayoutAttribute:layoutAttribute]; - newConstraint.delegate = self; - [self.childConstraints addObject:newConstraint]; - return newConstraint; -} - -#pragma mark - NSLayoutConstraint multiplier proxies - -- (MASConstraint * (^)(CGFloat))multipliedBy { - return ^id(CGFloat multiplier) { - for (MASConstraint *constraint in self.childConstraints) { - constraint.multipliedBy(multiplier); - } - return self; - }; -} - -- (MASConstraint * (^)(CGFloat))dividedBy { - return ^id(CGFloat divider) { - for (MASConstraint *constraint in self.childConstraints) { - constraint.dividedBy(divider); - } - return self; - }; -} - -#pragma mark - MASLayoutPriority proxy - -- (MASConstraint * (^)(MASLayoutPriority))priority { - return ^id(MASLayoutPriority priority) { - for (MASConstraint *constraint in self.childConstraints) { - constraint.priority(priority); - } - return self; - }; -} - -#pragma mark - NSLayoutRelation proxy - -- (MASConstraint * (^)(id, NSLayoutRelation))equalToWithRelation { - return ^id(id attr, NSLayoutRelation relation) { - for (MASConstraint *constraint in self.childConstraints.copy) { - constraint.equalToWithRelation(attr, relation); - } - return self; - }; -} - -#pragma mark - attribute chaining - -- (MASConstraint *)addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute { - [self constraint:self addConstraintWithLayoutAttribute:layoutAttribute]; - return self; -} - -#pragma mark - Animator proxy - -#if TARGET_OS_MAC && !(TARGET_OS_IPHONE || TARGET_OS_TV) - -- (MASConstraint *)animator { - for (MASConstraint *constraint in self.childConstraints) { - [constraint animator]; - } - return self; -} - -#endif - -#pragma mark - debug helpers - -- (MASConstraint * (^)(id))key { - return ^id(id key) { - self.mas_key = key; - int i = 0; - for (MASConstraint *constraint in self.childConstraints) { - constraint.key([NSString stringWithFormat:@"%@[%d]", key, i++]); - } - return self; - }; -} - -#pragma mark - NSLayoutConstraint constant setters - -- (void)setInsets:(MASEdgeInsets)insets { - for (MASConstraint *constraint in self.childConstraints) { - constraint.insets = insets; - } -} - -- (void)setInset:(CGFloat)inset { - for (MASConstraint *constraint in self.childConstraints) { - constraint.inset = inset; - } -} - -- (void)setOffset:(CGFloat)offset { - for (MASConstraint *constraint in self.childConstraints) { - constraint.offset = offset; - } -} - -- (void)setSizeOffset:(CGSize)sizeOffset { - for (MASConstraint *constraint in self.childConstraints) { - constraint.sizeOffset = sizeOffset; - } -} - -- (void)setCenterOffset:(CGPoint)centerOffset { - for (MASConstraint *constraint in self.childConstraints) { - constraint.centerOffset = centerOffset; - } -} - -#pragma mark - MASConstraint - -- (void)activate { - for (MASConstraint *constraint in self.childConstraints) { - [constraint activate]; - } -} - -- (void)deactivate { - for (MASConstraint *constraint in self.childConstraints) { - [constraint deactivate]; - } -} - -- (void)install { - for (MASConstraint *constraint in self.childConstraints) { - constraint.updateExisting = self.updateExisting; - [constraint install]; - } -} - -- (void)uninstall { - for (MASConstraint *constraint in self.childConstraints) { - [constraint uninstall]; - } -} - -@end diff --git a/CustomKeyboard/Masonry/Masonry/MASConstraint+Private.h b/CustomKeyboard/Masonry/Masonry/MASConstraint+Private.h deleted file mode 100755 index ee0fd96..0000000 --- a/CustomKeyboard/Masonry/Masonry/MASConstraint+Private.h +++ /dev/null @@ -1,66 +0,0 @@ -// -// MASConstraint+Private.h -// Masonry -// -// Created by Nick Tymchenko on 29/04/14. -// Copyright (c) 2014 cloudling. All rights reserved. -// - -#import "MASConstraint.h" - -@protocol MASConstraintDelegate; - - -@interface MASConstraint () - -/** - * Whether or not to check for an existing constraint instead of adding constraint - */ -@property (nonatomic, assign) BOOL updateExisting; - -/** - * Usually MASConstraintMaker but could be a parent MASConstraint - */ -@property (nonatomic, weak) id delegate; - -/** - * Based on a provided value type, is equal to calling: - * NSNumber - setOffset: - * NSValue with CGPoint - setPointOffset: - * NSValue with CGSize - setSizeOffset: - * NSValue with MASEdgeInsets - setInsets: - */ -- (void)setLayoutConstantWithValue:(NSValue *)value; - -@end - - -@interface MASConstraint (Abstract) - -/** - * Sets the constraint relation to given NSLayoutRelation - * returns a block which accepts one of the following: - * MASViewAttribute, UIView, NSValue, NSArray - * see readme for more details. - */ -- (MASConstraint * (^)(id, NSLayoutRelation))equalToWithRelation; - -/** - * Override to set a custom chaining behaviour - */ -- (MASConstraint *)addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute; - -@end - - -@protocol MASConstraintDelegate - -/** - * Notifies the delegate when the constraint needs to be replaced with another constraint. For example - * A MASViewConstraint may turn into a MASCompositeConstraint when an array is passed to one of the equality blocks - */ -- (void)constraint:(MASConstraint *)constraint shouldBeReplacedWithConstraint:(MASConstraint *)replacementConstraint; - -- (MASConstraint *)constraint:(MASConstraint *)constraint addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute; - -@end diff --git a/CustomKeyboard/Masonry/Masonry/MASConstraint.h b/CustomKeyboard/Masonry/Masonry/MASConstraint.h deleted file mode 100755 index 3eaa8a1..0000000 --- a/CustomKeyboard/Masonry/Masonry/MASConstraint.h +++ /dev/null @@ -1,272 +0,0 @@ -// -// MASConstraint.h -// Masonry -// -// Created by Jonas Budelmann on 22/07/13. -// Copyright (c) 2013 cloudling. All rights reserved. -// - -#import "MASUtilities.h" - -/** - * Enables Constraints to be created with chainable syntax - * Constraint can represent single NSLayoutConstraint (MASViewConstraint) - * or a group of NSLayoutConstraints (MASComposisteConstraint) - */ -@interface MASConstraint : NSObject - -// Chaining Support - -/** - * Modifies the NSLayoutConstraint constant, - * only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following - * NSLayoutAttributeTop, NSLayoutAttributeLeft, NSLayoutAttributeBottom, NSLayoutAttributeRight - */ -- (MASConstraint * (^)(MASEdgeInsets insets))insets; - -/** - * Modifies the NSLayoutConstraint constant, - * only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following - * NSLayoutAttributeTop, NSLayoutAttributeLeft, NSLayoutAttributeBottom, NSLayoutAttributeRight - */ -- (MASConstraint * (^)(CGFloat inset))inset; - -/** - * Modifies the NSLayoutConstraint constant, - * only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following - * NSLayoutAttributeWidth, NSLayoutAttributeHeight - */ -- (MASConstraint * (^)(CGSize offset))sizeOffset; - -/** - * Modifies the NSLayoutConstraint constant, - * only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following - * NSLayoutAttributeCenterX, NSLayoutAttributeCenterY - */ -- (MASConstraint * (^)(CGPoint offset))centerOffset; - -/** - * Modifies the NSLayoutConstraint constant - */ -- (MASConstraint * (^)(CGFloat offset))offset; - -/** - * Modifies the NSLayoutConstraint constant based on a value type - */ -- (MASConstraint * (^)(NSValue *value))valueOffset; - -/** - * Sets the NSLayoutConstraint multiplier property - */ -- (MASConstraint * (^)(CGFloat multiplier))multipliedBy; - -/** - * Sets the NSLayoutConstraint multiplier to 1.0/dividedBy - */ -- (MASConstraint * (^)(CGFloat divider))dividedBy; - -/** - * Sets the NSLayoutConstraint priority to a float or MASLayoutPriority - */ -- (MASConstraint * (^)(MASLayoutPriority priority))priority; - -/** - * Sets the NSLayoutConstraint priority to MASLayoutPriorityLow - */ -- (MASConstraint * (^)(void))priorityLow; - -/** - * Sets the NSLayoutConstraint priority to MASLayoutPriorityMedium - */ -- (MASConstraint * (^)(void))priorityMedium; - -/** - * Sets the NSLayoutConstraint priority to MASLayoutPriorityHigh - */ -- (MASConstraint * (^)(void))priorityHigh; - -/** - * Sets the constraint relation to NSLayoutRelationEqual - * returns a block which accepts one of the following: - * MASViewAttribute, UIView, NSValue, NSArray - * see readme for more details. - */ -- (MASConstraint * (^)(id attr))equalTo; - -/** - * Sets the constraint relation to NSLayoutRelationGreaterThanOrEqual - * returns a block which accepts one of the following: - * MASViewAttribute, UIView, NSValue, NSArray - * see readme for more details. - */ -- (MASConstraint * (^)(id attr))greaterThanOrEqualTo; - -/** - * Sets the constraint relation to NSLayoutRelationLessThanOrEqual - * returns a block which accepts one of the following: - * MASViewAttribute, UIView, NSValue, NSArray - * see readme for more details. - */ -- (MASConstraint * (^)(id attr))lessThanOrEqualTo; - -/** - * Optional semantic property which has no effect but improves the readability of constraint - */ -- (MASConstraint *)with; - -/** - * Optional semantic property which has no effect but improves the readability of constraint - */ -- (MASConstraint *)and; - -/** - * Creates a new MASCompositeConstraint with the called attribute and reciever - */ -- (MASConstraint *)left; -- (MASConstraint *)top; -- (MASConstraint *)right; -- (MASConstraint *)bottom; -- (MASConstraint *)leading; -- (MASConstraint *)trailing; -- (MASConstraint *)width; -- (MASConstraint *)height; -- (MASConstraint *)centerX; -- (MASConstraint *)centerY; -- (MASConstraint *)baseline; - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) - -- (MASConstraint *)firstBaseline; -- (MASConstraint *)lastBaseline; - -#endif - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) - -- (MASConstraint *)leftMargin; -- (MASConstraint *)rightMargin; -- (MASConstraint *)topMargin; -- (MASConstraint *)bottomMargin; -- (MASConstraint *)leadingMargin; -- (MASConstraint *)trailingMargin; -- (MASConstraint *)centerXWithinMargins; -- (MASConstraint *)centerYWithinMargins; - -#endif - - -/** - * Sets the constraint debug name - */ -- (MASConstraint * (^)(id key))key; - -// NSLayoutConstraint constant Setters -// for use outside of mas_updateConstraints/mas_makeConstraints blocks - -/** - * Modifies the NSLayoutConstraint constant, - * only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following - * NSLayoutAttributeTop, NSLayoutAttributeLeft, NSLayoutAttributeBottom, NSLayoutAttributeRight - */ -- (void)setInsets:(MASEdgeInsets)insets; - -/** - * Modifies the NSLayoutConstraint constant, - * only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following - * NSLayoutAttributeTop, NSLayoutAttributeLeft, NSLayoutAttributeBottom, NSLayoutAttributeRight - */ -- (void)setInset:(CGFloat)inset; - -/** - * Modifies the NSLayoutConstraint constant, - * only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following - * NSLayoutAttributeWidth, NSLayoutAttributeHeight - */ -- (void)setSizeOffset:(CGSize)sizeOffset; - -/** - * Modifies the NSLayoutConstraint constant, - * only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following - * NSLayoutAttributeCenterX, NSLayoutAttributeCenterY - */ -- (void)setCenterOffset:(CGPoint)centerOffset; - -/** - * Modifies the NSLayoutConstraint constant - */ -- (void)setOffset:(CGFloat)offset; - - -// NSLayoutConstraint Installation support - -#if TARGET_OS_MAC && !(TARGET_OS_IPHONE || TARGET_OS_TV) -/** - * Whether or not to go through the animator proxy when modifying the constraint - */ -@property (nonatomic, copy, readonly) MASConstraint *animator; -#endif - -/** - * Activates an NSLayoutConstraint if it's supported by an OS. - * Invokes install otherwise. - */ -- (void)activate; - -/** - * Deactivates previously installed/activated NSLayoutConstraint. - */ -- (void)deactivate; - -/** - * Creates a NSLayoutConstraint and adds it to the appropriate view. - */ -- (void)install; - -/** - * Removes previously installed NSLayoutConstraint - */ -- (void)uninstall; - -@end - - -/** - * Convenience auto-boxing macros for MASConstraint methods. - * - * Defining MAS_SHORTHAND_GLOBALS will turn on auto-boxing for default syntax. - * A potential drawback of this is that the unprefixed macros will appear in global scope. - */ -#define mas_equalTo(...) equalTo(MASBoxValue((__VA_ARGS__))) -#define mas_greaterThanOrEqualTo(...) greaterThanOrEqualTo(MASBoxValue((__VA_ARGS__))) -#define mas_lessThanOrEqualTo(...) lessThanOrEqualTo(MASBoxValue((__VA_ARGS__))) - -#define mas_offset(...) valueOffset(MASBoxValue((__VA_ARGS__))) - - -#ifdef MAS_SHORTHAND_GLOBALS - -#define equalTo(...) mas_equalTo(__VA_ARGS__) -#define greaterThanOrEqualTo(...) mas_greaterThanOrEqualTo(__VA_ARGS__) -#define lessThanOrEqualTo(...) mas_lessThanOrEqualTo(__VA_ARGS__) - -#define offset(...) mas_offset(__VA_ARGS__) - -#endif - - -@interface MASConstraint (AutoboxingSupport) - -/** - * Aliases to corresponding relation methods (for shorthand macros) - * Also needed to aid autocompletion - */ -- (MASConstraint * (^)(id attr))mas_equalTo; -- (MASConstraint * (^)(id attr))mas_greaterThanOrEqualTo; -- (MASConstraint * (^)(id attr))mas_lessThanOrEqualTo; - -/** - * A dummy method to aid autocompletion - */ -- (MASConstraint * (^)(id offset))mas_offset; - -@end diff --git a/CustomKeyboard/Masonry/Masonry/MASConstraint.m b/CustomKeyboard/Masonry/Masonry/MASConstraint.m deleted file mode 100755 index 52de590..0000000 --- a/CustomKeyboard/Masonry/Masonry/MASConstraint.m +++ /dev/null @@ -1,301 +0,0 @@ -// -// MASConstraint.m -// Masonry -// -// Created by Nick Tymchenko on 1/20/14. -// - -#import "MASConstraint.h" -#import "MASConstraint+Private.h" - -#define MASMethodNotImplemented() \ - @throw [NSException exceptionWithName:NSInternalInconsistencyException \ - reason:[NSString stringWithFormat:@"You must override %@ in a subclass.", NSStringFromSelector(_cmd)] \ - userInfo:nil] - -@implementation MASConstraint - -#pragma mark - Init - -- (id)init { - NSAssert(![self isMemberOfClass:[MASConstraint class]], @"MASConstraint is an abstract class, you should not instantiate it directly."); - return [super init]; -} - -#pragma mark - NSLayoutRelation proxies - -- (MASConstraint * (^)(id))equalTo { - return ^id(id attribute) { - return self.equalToWithRelation(attribute, NSLayoutRelationEqual); - }; -} - -- (MASConstraint * (^)(id))mas_equalTo { - return ^id(id attribute) { - return self.equalToWithRelation(attribute, NSLayoutRelationEqual); - }; -} - -- (MASConstraint * (^)(id))greaterThanOrEqualTo { - return ^id(id attribute) { - return self.equalToWithRelation(attribute, NSLayoutRelationGreaterThanOrEqual); - }; -} - -- (MASConstraint * (^)(id))mas_greaterThanOrEqualTo { - return ^id(id attribute) { - return self.equalToWithRelation(attribute, NSLayoutRelationGreaterThanOrEqual); - }; -} - -- (MASConstraint * (^)(id))lessThanOrEqualTo { - return ^id(id attribute) { - return self.equalToWithRelation(attribute, NSLayoutRelationLessThanOrEqual); - }; -} - -- (MASConstraint * (^)(id))mas_lessThanOrEqualTo { - return ^id(id attribute) { - return self.equalToWithRelation(attribute, NSLayoutRelationLessThanOrEqual); - }; -} - -#pragma mark - MASLayoutPriority proxies - -- (MASConstraint * (^)(void))priorityLow { - return ^id{ - self.priority(MASLayoutPriorityDefaultLow); - return self; - }; -} - -- (MASConstraint * (^)(void))priorityMedium { - return ^id{ - self.priority(MASLayoutPriorityDefaultMedium); - return self; - }; -} - -- (MASConstraint * (^)(void))priorityHigh { - return ^id{ - self.priority(MASLayoutPriorityDefaultHigh); - return self; - }; -} - -#pragma mark - NSLayoutConstraint constant proxies - -- (MASConstraint * (^)(MASEdgeInsets))insets { - return ^id(MASEdgeInsets insets){ - self.insets = insets; - return self; - }; -} - -- (MASConstraint * (^)(CGFloat))inset { - return ^id(CGFloat inset){ - self.inset = inset; - return self; - }; -} - -- (MASConstraint * (^)(CGSize))sizeOffset { - return ^id(CGSize offset) { - self.sizeOffset = offset; - return self; - }; -} - -- (MASConstraint * (^)(CGPoint))centerOffset { - return ^id(CGPoint offset) { - self.centerOffset = offset; - return self; - }; -} - -- (MASConstraint * (^)(CGFloat))offset { - return ^id(CGFloat offset){ - self.offset = offset; - return self; - }; -} - -- (MASConstraint * (^)(NSValue *value))valueOffset { - return ^id(NSValue *offset) { - NSAssert([offset isKindOfClass:NSValue.class], @"expected an NSValue offset, got: %@", offset); - [self setLayoutConstantWithValue:offset]; - return self; - }; -} - -- (MASConstraint * (^)(id offset))mas_offset { - // Will never be called due to macro - return nil; -} - -#pragma mark - NSLayoutConstraint constant setter - -- (void)setLayoutConstantWithValue:(NSValue *)value { - if ([value isKindOfClass:NSNumber.class]) { - self.offset = [(NSNumber *)value doubleValue]; - } else if (strcmp(value.objCType, @encode(CGPoint)) == 0) { - CGPoint point; - [value getValue:&point]; - self.centerOffset = point; - } else if (strcmp(value.objCType, @encode(CGSize)) == 0) { - CGSize size; - [value getValue:&size]; - self.sizeOffset = size; - } else if (strcmp(value.objCType, @encode(MASEdgeInsets)) == 0) { - MASEdgeInsets insets; - [value getValue:&insets]; - self.insets = insets; - } else { - NSAssert(NO, @"attempting to set layout constant with unsupported value: %@", value); - } -} - -#pragma mark - Semantic properties - -- (MASConstraint *)with { - return self; -} - -- (MASConstraint *)and { - return self; -} - -#pragma mark - Chaining - -- (MASConstraint *)addConstraintWithLayoutAttribute:(NSLayoutAttribute __unused)layoutAttribute { - MASMethodNotImplemented(); -} - -- (MASConstraint *)left { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeft]; -} - -- (MASConstraint *)top { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTop]; -} - -- (MASConstraint *)right { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeRight]; -} - -- (MASConstraint *)bottom { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeBottom]; -} - -- (MASConstraint *)leading { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeading]; -} - -- (MASConstraint *)trailing { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTrailing]; -} - -- (MASConstraint *)width { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeWidth]; -} - -- (MASConstraint *)height { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeHeight]; -} - -- (MASConstraint *)centerX { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterX]; -} - -- (MASConstraint *)centerY { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterY]; -} - -- (MASConstraint *)baseline { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeBaseline]; -} - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) - -- (MASConstraint *)firstBaseline { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeFirstBaseline]; -} -- (MASConstraint *)lastBaseline { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLastBaseline]; -} - -#endif - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) - -- (MASConstraint *)leftMargin { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeftMargin]; -} - -- (MASConstraint *)rightMargin { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeRightMargin]; -} - -- (MASConstraint *)topMargin { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTopMargin]; -} - -- (MASConstraint *)bottomMargin { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeBottomMargin]; -} - -- (MASConstraint *)leadingMargin { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeadingMargin]; -} - -- (MASConstraint *)trailingMargin { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTrailingMargin]; -} - -- (MASConstraint *)centerXWithinMargins { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterXWithinMargins]; -} - -- (MASConstraint *)centerYWithinMargins { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterYWithinMargins]; -} - -#endif - -#pragma mark - Abstract - -- (MASConstraint * (^)(CGFloat multiplier))multipliedBy { MASMethodNotImplemented(); } - -- (MASConstraint * (^)(CGFloat divider))dividedBy { MASMethodNotImplemented(); } - -- (MASConstraint * (^)(MASLayoutPriority priority))priority { MASMethodNotImplemented(); } - -- (MASConstraint * (^)(id, NSLayoutRelation))equalToWithRelation { MASMethodNotImplemented(); } - -- (MASConstraint * (^)(id key))key { MASMethodNotImplemented(); } - -- (void)setInsets:(MASEdgeInsets __unused)insets { MASMethodNotImplemented(); } - -- (void)setInset:(CGFloat __unused)inset { MASMethodNotImplemented(); } - -- (void)setSizeOffset:(CGSize __unused)sizeOffset { MASMethodNotImplemented(); } - -- (void)setCenterOffset:(CGPoint __unused)centerOffset { MASMethodNotImplemented(); } - -- (void)setOffset:(CGFloat __unused)offset { MASMethodNotImplemented(); } - -#if TARGET_OS_MAC && !(TARGET_OS_IPHONE || TARGET_OS_TV) - -- (MASConstraint *)animator { MASMethodNotImplemented(); } - -#endif - -- (void)activate { MASMethodNotImplemented(); } - -- (void)deactivate { MASMethodNotImplemented(); } - -- (void)install { MASMethodNotImplemented(); } - -- (void)uninstall { MASMethodNotImplemented(); } - -@end diff --git a/CustomKeyboard/Masonry/Masonry/MASConstraintMaker.h b/CustomKeyboard/Masonry/Masonry/MASConstraintMaker.h deleted file mode 100755 index d9b58f4..0000000 --- a/CustomKeyboard/Masonry/Masonry/MASConstraintMaker.h +++ /dev/null @@ -1,146 +0,0 @@ -// -// MASConstraintMaker.h -// Masonry -// -// Created by Jonas Budelmann on 20/07/13. -// Copyright (c) 2013 cloudling. All rights reserved. -// - -#import "MASConstraint.h" -#import "MASUtilities.h" - -typedef NS_OPTIONS(NSInteger, MASAttribute) { - MASAttributeLeft = 1 << NSLayoutAttributeLeft, - MASAttributeRight = 1 << NSLayoutAttributeRight, - MASAttributeTop = 1 << NSLayoutAttributeTop, - MASAttributeBottom = 1 << NSLayoutAttributeBottom, - MASAttributeLeading = 1 << NSLayoutAttributeLeading, - MASAttributeTrailing = 1 << NSLayoutAttributeTrailing, - MASAttributeWidth = 1 << NSLayoutAttributeWidth, - MASAttributeHeight = 1 << NSLayoutAttributeHeight, - MASAttributeCenterX = 1 << NSLayoutAttributeCenterX, - MASAttributeCenterY = 1 << NSLayoutAttributeCenterY, - MASAttributeBaseline = 1 << NSLayoutAttributeBaseline, - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) - - MASAttributeFirstBaseline = 1 << NSLayoutAttributeFirstBaseline, - MASAttributeLastBaseline = 1 << NSLayoutAttributeLastBaseline, - -#endif - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) - - MASAttributeLeftMargin = 1 << NSLayoutAttributeLeftMargin, - MASAttributeRightMargin = 1 << NSLayoutAttributeRightMargin, - MASAttributeTopMargin = 1 << NSLayoutAttributeTopMargin, - MASAttributeBottomMargin = 1 << NSLayoutAttributeBottomMargin, - MASAttributeLeadingMargin = 1 << NSLayoutAttributeLeadingMargin, - MASAttributeTrailingMargin = 1 << NSLayoutAttributeTrailingMargin, - MASAttributeCenterXWithinMargins = 1 << NSLayoutAttributeCenterXWithinMargins, - MASAttributeCenterYWithinMargins = 1 << NSLayoutAttributeCenterYWithinMargins, - -#endif - -}; - -/** - * Provides factory methods for creating MASConstraints. - * Constraints are collected until they are ready to be installed - * - */ -@interface MASConstraintMaker : NSObject - -/** - * The following properties return a new MASViewConstraint - * with the first item set to the makers associated view and the appropriate MASViewAttribute - */ -@property (nonatomic, strong, readonly) MASConstraint *left; -@property (nonatomic, strong, readonly) MASConstraint *top; -@property (nonatomic, strong, readonly) MASConstraint *right; -@property (nonatomic, strong, readonly) MASConstraint *bottom; -@property (nonatomic, strong, readonly) MASConstraint *leading; -@property (nonatomic, strong, readonly) MASConstraint *trailing; -@property (nonatomic, strong, readonly) MASConstraint *width; -@property (nonatomic, strong, readonly) MASConstraint *height; -@property (nonatomic, strong, readonly) MASConstraint *centerX; -@property (nonatomic, strong, readonly) MASConstraint *centerY; -@property (nonatomic, strong, readonly) MASConstraint *baseline; - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) - -@property (nonatomic, strong, readonly) MASConstraint *firstBaseline; -@property (nonatomic, strong, readonly) MASConstraint *lastBaseline; - -#endif - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) - -@property (nonatomic, strong, readonly) MASConstraint *leftMargin; -@property (nonatomic, strong, readonly) MASConstraint *rightMargin; -@property (nonatomic, strong, readonly) MASConstraint *topMargin; -@property (nonatomic, strong, readonly) MASConstraint *bottomMargin; -@property (nonatomic, strong, readonly) MASConstraint *leadingMargin; -@property (nonatomic, strong, readonly) MASConstraint *trailingMargin; -@property (nonatomic, strong, readonly) MASConstraint *centerXWithinMargins; -@property (nonatomic, strong, readonly) MASConstraint *centerYWithinMargins; - -#endif - -/** - * Returns a block which creates a new MASCompositeConstraint with the first item set - * to the makers associated view and children corresponding to the set bits in the - * MASAttribute parameter. Combine multiple attributes via binary-or. - */ -@property (nonatomic, strong, readonly) MASConstraint *(^attributes)(MASAttribute attrs); - -/** - * Creates a MASCompositeConstraint with type MASCompositeConstraintTypeEdges - * which generates the appropriate MASViewConstraint children (top, left, bottom, right) - * with the first item set to the makers associated view - */ -@property (nonatomic, strong, readonly) MASConstraint *edges; - -/** - * Creates a MASCompositeConstraint with type MASCompositeConstraintTypeSize - * which generates the appropriate MASViewConstraint children (width, height) - * with the first item set to the makers associated view - */ -@property (nonatomic, strong, readonly) MASConstraint *size; - -/** - * Creates a MASCompositeConstraint with type MASCompositeConstraintTypeCenter - * which generates the appropriate MASViewConstraint children (centerX, centerY) - * with the first item set to the makers associated view - */ -@property (nonatomic, strong, readonly) MASConstraint *center; - -/** - * Whether or not to check for an existing constraint instead of adding constraint - */ -@property (nonatomic, assign) BOOL updateExisting; - -/** - * Whether or not to remove existing constraints prior to installing - */ -@property (nonatomic, assign) BOOL removeExisting; - -/** - * initialises the maker with a default view - * - * @param view any MASConstraint are created with this view as the first item - * - * @return a new MASConstraintMaker - */ -- (id)initWithView:(MAS_VIEW *)view; - -/** - * Calls install method on any MASConstraints which have been created by this maker - * - * @return an array of all the installed MASConstraints - */ -- (NSArray *)install; - -- (MASConstraint * (^)(dispatch_block_t))group; - -@end diff --git a/CustomKeyboard/Masonry/Masonry/MASConstraintMaker.m b/CustomKeyboard/Masonry/Masonry/MASConstraintMaker.m deleted file mode 100755 index f11492a..0000000 --- a/CustomKeyboard/Masonry/Masonry/MASConstraintMaker.m +++ /dev/null @@ -1,273 +0,0 @@ -// -// MASConstraintMaker.m -// Masonry -// -// Created by Jonas Budelmann on 20/07/13. -// Copyright (c) 2013 cloudling. All rights reserved. -// - -#import "MASConstraintMaker.h" -#import "MASViewConstraint.h" -#import "MASCompositeConstraint.h" -#import "MASConstraint+Private.h" -#import "MASViewAttribute.h" -#import "View+MASAdditions.h" - -@interface MASConstraintMaker () - -@property (nonatomic, weak) MAS_VIEW *view; -@property (nonatomic, strong) NSMutableArray *constraints; - -@end - -@implementation MASConstraintMaker - -- (id)initWithView:(MAS_VIEW *)view { - self = [super init]; - if (!self) return nil; - - self.view = view; - self.constraints = NSMutableArray.new; - - return self; -} - -- (NSArray *)install { - if (self.removeExisting) { - NSArray *installedConstraints = [MASViewConstraint installedConstraintsForView:self.view]; - for (MASConstraint *constraint in installedConstraints) { - [constraint uninstall]; - } - } - NSArray *constraints = self.constraints.copy; - for (MASConstraint *constraint in constraints) { - constraint.updateExisting = self.updateExisting; - [constraint install]; - } - [self.constraints removeAllObjects]; - return constraints; -} - -#pragma mark - MASConstraintDelegate - -- (void)constraint:(MASConstraint *)constraint shouldBeReplacedWithConstraint:(MASConstraint *)replacementConstraint { - NSUInteger index = [self.constraints indexOfObject:constraint]; - NSAssert(index != NSNotFound, @"Could not find constraint %@", constraint); - [self.constraints replaceObjectAtIndex:index withObject:replacementConstraint]; -} - -- (MASConstraint *)constraint:(MASConstraint *)constraint addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute { - MASViewAttribute *viewAttribute = [[MASViewAttribute alloc] initWithView:self.view layoutAttribute:layoutAttribute]; - MASViewConstraint *newConstraint = [[MASViewConstraint alloc] initWithFirstViewAttribute:viewAttribute]; - if ([constraint isKindOfClass:MASViewConstraint.class]) { - //replace with composite constraint - NSArray *children = @[constraint, newConstraint]; - MASCompositeConstraint *compositeConstraint = [[MASCompositeConstraint alloc] initWithChildren:children]; - compositeConstraint.delegate = self; - [self constraint:constraint shouldBeReplacedWithConstraint:compositeConstraint]; - return compositeConstraint; - } - if (!constraint) { - newConstraint.delegate = self; - [self.constraints addObject:newConstraint]; - } - return newConstraint; -} - -- (MASConstraint *)addConstraintWithAttributes:(MASAttribute)attrs { - __unused MASAttribute anyAttribute = (MASAttributeLeft | MASAttributeRight | MASAttributeTop | MASAttributeBottom | MASAttributeLeading - | MASAttributeTrailing | MASAttributeWidth | MASAttributeHeight | MASAttributeCenterX - | MASAttributeCenterY | MASAttributeBaseline -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) - | MASAttributeFirstBaseline | MASAttributeLastBaseline -#endif -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) - | MASAttributeLeftMargin | MASAttributeRightMargin | MASAttributeTopMargin | MASAttributeBottomMargin - | MASAttributeLeadingMargin | MASAttributeTrailingMargin | MASAttributeCenterXWithinMargins - | MASAttributeCenterYWithinMargins -#endif - ); - - NSAssert((attrs & anyAttribute) != 0, @"You didn't pass any attribute to make.attributes(...)"); - - NSMutableArray *attributes = [NSMutableArray array]; - - if (attrs & MASAttributeLeft) [attributes addObject:self.view.mas_left]; - if (attrs & MASAttributeRight) [attributes addObject:self.view.mas_right]; - if (attrs & MASAttributeTop) [attributes addObject:self.view.mas_top]; - if (attrs & MASAttributeBottom) [attributes addObject:self.view.mas_bottom]; - if (attrs & MASAttributeLeading) [attributes addObject:self.view.mas_leading]; - if (attrs & MASAttributeTrailing) [attributes addObject:self.view.mas_trailing]; - if (attrs & MASAttributeWidth) [attributes addObject:self.view.mas_width]; - if (attrs & MASAttributeHeight) [attributes addObject:self.view.mas_height]; - if (attrs & MASAttributeCenterX) [attributes addObject:self.view.mas_centerX]; - if (attrs & MASAttributeCenterY) [attributes addObject:self.view.mas_centerY]; - if (attrs & MASAttributeBaseline) [attributes addObject:self.view.mas_baseline]; - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) - - if (attrs & MASAttributeFirstBaseline) [attributes addObject:self.view.mas_firstBaseline]; - if (attrs & MASAttributeLastBaseline) [attributes addObject:self.view.mas_lastBaseline]; - -#endif - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) - - if (attrs & MASAttributeLeftMargin) [attributes addObject:self.view.mas_leftMargin]; - if (attrs & MASAttributeRightMargin) [attributes addObject:self.view.mas_rightMargin]; - if (attrs & MASAttributeTopMargin) [attributes addObject:self.view.mas_topMargin]; - if (attrs & MASAttributeBottomMargin) [attributes addObject:self.view.mas_bottomMargin]; - if (attrs & MASAttributeLeadingMargin) [attributes addObject:self.view.mas_leadingMargin]; - if (attrs & MASAttributeTrailingMargin) [attributes addObject:self.view.mas_trailingMargin]; - if (attrs & MASAttributeCenterXWithinMargins) [attributes addObject:self.view.mas_centerXWithinMargins]; - if (attrs & MASAttributeCenterYWithinMargins) [attributes addObject:self.view.mas_centerYWithinMargins]; - -#endif - - NSMutableArray *children = [NSMutableArray arrayWithCapacity:attributes.count]; - - for (MASViewAttribute *a in attributes) { - [children addObject:[[MASViewConstraint alloc] initWithFirstViewAttribute:a]]; - } - - MASCompositeConstraint *constraint = [[MASCompositeConstraint alloc] initWithChildren:children]; - constraint.delegate = self; - [self.constraints addObject:constraint]; - return constraint; -} - -#pragma mark - standard Attributes - -- (MASConstraint *)addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute { - return [self constraint:nil addConstraintWithLayoutAttribute:layoutAttribute]; -} - -- (MASConstraint *)left { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeft]; -} - -- (MASConstraint *)top { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTop]; -} - -- (MASConstraint *)right { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeRight]; -} - -- (MASConstraint *)bottom { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeBottom]; -} - -- (MASConstraint *)leading { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeading]; -} - -- (MASConstraint *)trailing { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTrailing]; -} - -- (MASConstraint *)width { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeWidth]; -} - -- (MASConstraint *)height { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeHeight]; -} - -- (MASConstraint *)centerX { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterX]; -} - -- (MASConstraint *)centerY { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterY]; -} - -- (MASConstraint *)baseline { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeBaseline]; -} - -- (MASConstraint *(^)(MASAttribute))attributes { - return ^(MASAttribute attrs){ - return [self addConstraintWithAttributes:attrs]; - }; -} - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) - -- (MASConstraint *)firstBaseline { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeFirstBaseline]; -} - -- (MASConstraint *)lastBaseline { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLastBaseline]; -} - -#endif - - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) - -- (MASConstraint *)leftMargin { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeftMargin]; -} - -- (MASConstraint *)rightMargin { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeRightMargin]; -} - -- (MASConstraint *)topMargin { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTopMargin]; -} - -- (MASConstraint *)bottomMargin { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeBottomMargin]; -} - -- (MASConstraint *)leadingMargin { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeadingMargin]; -} - -- (MASConstraint *)trailingMargin { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTrailingMargin]; -} - -- (MASConstraint *)centerXWithinMargins { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterXWithinMargins]; -} - -- (MASConstraint *)centerYWithinMargins { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterYWithinMargins]; -} - -#endif - - -#pragma mark - composite Attributes - -- (MASConstraint *)edges { - return [self addConstraintWithAttributes:MASAttributeTop | MASAttributeLeft | MASAttributeRight | MASAttributeBottom]; -} - -- (MASConstraint *)size { - return [self addConstraintWithAttributes:MASAttributeWidth | MASAttributeHeight]; -} - -- (MASConstraint *)center { - return [self addConstraintWithAttributes:MASAttributeCenterX | MASAttributeCenterY]; -} - -#pragma mark - grouping - -- (MASConstraint *(^)(dispatch_block_t group))group { - return ^id(dispatch_block_t group) { - NSInteger previousCount = self.constraints.count; - group(); - - NSArray *children = [self.constraints subarrayWithRange:NSMakeRange(previousCount, self.constraints.count - previousCount)]; - MASCompositeConstraint *constraint = [[MASCompositeConstraint alloc] initWithChildren:children]; - constraint.delegate = self; - return constraint; - }; -} - -@end diff --git a/CustomKeyboard/Masonry/Masonry/MASLayoutConstraint.h b/CustomKeyboard/Masonry/Masonry/MASLayoutConstraint.h deleted file mode 100755 index 699041c..0000000 --- a/CustomKeyboard/Masonry/Masonry/MASLayoutConstraint.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// MASLayoutConstraint.h -// Masonry -// -// Created by Jonas Budelmann on 3/08/13. -// Copyright (c) 2013 Jonas Budelmann. All rights reserved. -// - -#import "MASUtilities.h" - -/** - * When you are debugging or printing the constraints attached to a view this subclass - * makes it easier to identify which constraints have been created via Masonry - */ -@interface MASLayoutConstraint : NSLayoutConstraint - -/** - * a key to associate with this constraint - */ -@property (nonatomic, strong) id mas_key; - -@end diff --git a/CustomKeyboard/Masonry/Masonry/MASLayoutConstraint.m b/CustomKeyboard/Masonry/Masonry/MASLayoutConstraint.m deleted file mode 100755 index 3483f02..0000000 --- a/CustomKeyboard/Masonry/Masonry/MASLayoutConstraint.m +++ /dev/null @@ -1,13 +0,0 @@ -// -// MASLayoutConstraint.m -// Masonry -// -// Created by Jonas Budelmann on 3/08/13. -// Copyright (c) 2013 Jonas Budelmann. All rights reserved. -// - -#import "MASLayoutConstraint.h" - -@implementation MASLayoutConstraint - -@end diff --git a/CustomKeyboard/Masonry/Masonry/MASUtilities.h b/CustomKeyboard/Masonry/Masonry/MASUtilities.h deleted file mode 100755 index 1dbfd93..0000000 --- a/CustomKeyboard/Masonry/Masonry/MASUtilities.h +++ /dev/null @@ -1,136 +0,0 @@ -// -// MASUtilities.h -// Masonry -// -// Created by Jonas Budelmann on 19/08/13. -// Copyright (c) 2013 Jonas Budelmann. All rights reserved. -// - -#import - - - -#if TARGET_OS_IPHONE || TARGET_OS_TV - - #import - #define MAS_VIEW UIView - #define MAS_VIEW_CONTROLLER UIViewController - #define MASEdgeInsets UIEdgeInsets - - typedef UILayoutPriority MASLayoutPriority; - static const MASLayoutPriority MASLayoutPriorityRequired = UILayoutPriorityRequired; - static const MASLayoutPriority MASLayoutPriorityDefaultHigh = UILayoutPriorityDefaultHigh; - static const MASLayoutPriority MASLayoutPriorityDefaultMedium = 500; - static const MASLayoutPriority MASLayoutPriorityDefaultLow = UILayoutPriorityDefaultLow; - static const MASLayoutPriority MASLayoutPriorityFittingSizeLevel = UILayoutPriorityFittingSizeLevel; - -#elif TARGET_OS_MAC - - #import - #define MAS_VIEW NSView - #define MASEdgeInsets NSEdgeInsets - - typedef NSLayoutPriority MASLayoutPriority; - static const MASLayoutPriority MASLayoutPriorityRequired = NSLayoutPriorityRequired; - static const MASLayoutPriority MASLayoutPriorityDefaultHigh = NSLayoutPriorityDefaultHigh; - static const MASLayoutPriority MASLayoutPriorityDragThatCanResizeWindow = NSLayoutPriorityDragThatCanResizeWindow; - static const MASLayoutPriority MASLayoutPriorityDefaultMedium = 501; - static const MASLayoutPriority MASLayoutPriorityWindowSizeStayPut = NSLayoutPriorityWindowSizeStayPut; - static const MASLayoutPriority MASLayoutPriorityDragThatCannotResizeWindow = NSLayoutPriorityDragThatCannotResizeWindow; - static const MASLayoutPriority MASLayoutPriorityDefaultLow = NSLayoutPriorityDefaultLow; - static const MASLayoutPriority MASLayoutPriorityFittingSizeCompression = NSLayoutPriorityFittingSizeCompression; - -#endif - -/** - * Allows you to attach keys to objects matching the variable names passed. - * - * view1.mas_key = @"view1", view2.mas_key = @"view2"; - * - * is equivalent to: - * - * MASAttachKeys(view1, view2); - */ -#define MASAttachKeys(...) \ - { \ - NSDictionary *keyPairs = NSDictionaryOfVariableBindings(__VA_ARGS__); \ - for (id key in keyPairs.allKeys) { \ - id obj = keyPairs[key]; \ - NSAssert([obj respondsToSelector:@selector(setMas_key:)], \ - @"Cannot attach mas_key to %@", obj); \ - [obj setMas_key:key]; \ - } \ - } - -/** - * Used to create object hashes - * Based on http://www.mikeash.com/pyblog/friday-qa-2010-06-18-implementing-equality-and-hashing.html - */ -#define MAS_NSUINT_BIT (CHAR_BIT * sizeof(NSUInteger)) -#define MAS_NSUINTROTATE(val, howmuch) ((((NSUInteger)val) << howmuch) | (((NSUInteger)val) >> (MAS_NSUINT_BIT - howmuch))) - -/** - * Given a scalar or struct value, wraps it in NSValue - * Based on EXPObjectify: https://github.com/specta/expecta - */ -static inline id _MASBoxValue(const char *type, ...) { - va_list v; - va_start(v, type); - id obj = nil; - if (strcmp(type, @encode(id)) == 0) { - id actual = va_arg(v, id); - obj = actual; - } else if (strcmp(type, @encode(CGPoint)) == 0) { - CGPoint actual = (CGPoint)va_arg(v, CGPoint); - obj = [NSValue value:&actual withObjCType:type]; - } else if (strcmp(type, @encode(CGSize)) == 0) { - CGSize actual = (CGSize)va_arg(v, CGSize); - obj = [NSValue value:&actual withObjCType:type]; - } else if (strcmp(type, @encode(MASEdgeInsets)) == 0) { - MASEdgeInsets actual = (MASEdgeInsets)va_arg(v, MASEdgeInsets); - obj = [NSValue value:&actual withObjCType:type]; - } else if (strcmp(type, @encode(double)) == 0) { - double actual = (double)va_arg(v, double); - obj = [NSNumber numberWithDouble:actual]; - } else if (strcmp(type, @encode(float)) == 0) { - float actual = (float)va_arg(v, double); - obj = [NSNumber numberWithFloat:actual]; - } else if (strcmp(type, @encode(int)) == 0) { - int actual = (int)va_arg(v, int); - obj = [NSNumber numberWithInt:actual]; - } else if (strcmp(type, @encode(long)) == 0) { - long actual = (long)va_arg(v, long); - obj = [NSNumber numberWithLong:actual]; - } else if (strcmp(type, @encode(long long)) == 0) { - long long actual = (long long)va_arg(v, long long); - obj = [NSNumber numberWithLongLong:actual]; - } else if (strcmp(type, @encode(short)) == 0) { - short actual = (short)va_arg(v, int); - obj = [NSNumber numberWithShort:actual]; - } else if (strcmp(type, @encode(char)) == 0) { - char actual = (char)va_arg(v, int); - obj = [NSNumber numberWithChar:actual]; - } else if (strcmp(type, @encode(bool)) == 0) { - bool actual = (bool)va_arg(v, int); - obj = [NSNumber numberWithBool:actual]; - } else if (strcmp(type, @encode(unsigned char)) == 0) { - unsigned char actual = (unsigned char)va_arg(v, unsigned int); - obj = [NSNumber numberWithUnsignedChar:actual]; - } else if (strcmp(type, @encode(unsigned int)) == 0) { - unsigned int actual = (unsigned int)va_arg(v, unsigned int); - obj = [NSNumber numberWithUnsignedInt:actual]; - } else if (strcmp(type, @encode(unsigned long)) == 0) { - unsigned long actual = (unsigned long)va_arg(v, unsigned long); - obj = [NSNumber numberWithUnsignedLong:actual]; - } else if (strcmp(type, @encode(unsigned long long)) == 0) { - unsigned long long actual = (unsigned long long)va_arg(v, unsigned long long); - obj = [NSNumber numberWithUnsignedLongLong:actual]; - } else if (strcmp(type, @encode(unsigned short)) == 0) { - unsigned short actual = (unsigned short)va_arg(v, unsigned int); - obj = [NSNumber numberWithUnsignedShort:actual]; - } - va_end(v); - return obj; -} - -#define MASBoxValue(value) _MASBoxValue(@encode(__typeof__((value))), (value)) diff --git a/CustomKeyboard/Masonry/Masonry/MASViewAttribute.h b/CustomKeyboard/Masonry/Masonry/MASViewAttribute.h deleted file mode 100755 index 601c25d..0000000 --- a/CustomKeyboard/Masonry/Masonry/MASViewAttribute.h +++ /dev/null @@ -1,49 +0,0 @@ -// -// MASViewAttribute.h -// Masonry -// -// Created by Jonas Budelmann on 21/07/13. -// Copyright (c) 2013 cloudling. All rights reserved. -// - -#import "MASUtilities.h" - -/** - * An immutable tuple which stores the view and the related NSLayoutAttribute. - * Describes part of either the left or right hand side of a constraint equation - */ -@interface MASViewAttribute : NSObject - -/** - * The view which the reciever relates to. Can be nil if item is not a view. - */ -@property (nonatomic, weak, readonly) MAS_VIEW *view; - -/** - * The item which the reciever relates to. - */ -@property (nonatomic, weak, readonly) id item; - -/** - * The attribute which the reciever relates to - */ -@property (nonatomic, assign, readonly) NSLayoutAttribute layoutAttribute; - -/** - * Convenience initializer. - */ -- (id)initWithView:(MAS_VIEW *)view layoutAttribute:(NSLayoutAttribute)layoutAttribute; - -/** - * The designated initializer. - */ -- (id)initWithView:(MAS_VIEW *)view item:(id)item layoutAttribute:(NSLayoutAttribute)layoutAttribute; - -/** - * Determine whether the layoutAttribute is a size attribute - * - * @return YES if layoutAttribute is equal to NSLayoutAttributeWidth or NSLayoutAttributeHeight - */ -- (BOOL)isSizeAttribute; - -@end diff --git a/CustomKeyboard/Masonry/Masonry/MASViewAttribute.m b/CustomKeyboard/Masonry/Masonry/MASViewAttribute.m deleted file mode 100755 index e573e8b..0000000 --- a/CustomKeyboard/Masonry/Masonry/MASViewAttribute.m +++ /dev/null @@ -1,46 +0,0 @@ -// -// MASViewAttribute.m -// Masonry -// -// Created by Jonas Budelmann on 21/07/13. -// Copyright (c) 2013 cloudling. All rights reserved. -// - -#import "MASViewAttribute.h" - -@implementation MASViewAttribute - -- (id)initWithView:(MAS_VIEW *)view layoutAttribute:(NSLayoutAttribute)layoutAttribute { - self = [self initWithView:view item:view layoutAttribute:layoutAttribute]; - return self; -} - -- (id)initWithView:(MAS_VIEW *)view item:(id)item layoutAttribute:(NSLayoutAttribute)layoutAttribute { - self = [super init]; - if (!self) return nil; - - _view = view; - _item = item; - _layoutAttribute = layoutAttribute; - - return self; -} - -- (BOOL)isSizeAttribute { - return self.layoutAttribute == NSLayoutAttributeWidth - || self.layoutAttribute == NSLayoutAttributeHeight; -} - -- (BOOL)isEqual:(MASViewAttribute *)viewAttribute { - if ([viewAttribute isKindOfClass:self.class]) { - return self.view == viewAttribute.view - && self.layoutAttribute == viewAttribute.layoutAttribute; - } - return [super isEqual:viewAttribute]; -} - -- (NSUInteger)hash { - return MAS_NSUINTROTATE([self.view hash], MAS_NSUINT_BIT / 2) ^ self.layoutAttribute; -} - -@end diff --git a/CustomKeyboard/Masonry/Masonry/MASViewConstraint.h b/CustomKeyboard/Masonry/Masonry/MASViewConstraint.h deleted file mode 100755 index ec390d1..0000000 --- a/CustomKeyboard/Masonry/Masonry/MASViewConstraint.h +++ /dev/null @@ -1,48 +0,0 @@ -// -// MASViewConstraint.h -// Masonry -// -// Created by Jonas Budelmann on 20/07/13. -// Copyright (c) 2013 cloudling. All rights reserved. -// - -#import "MASViewAttribute.h" -#import "MASConstraint.h" -#import "MASLayoutConstraint.h" -#import "MASUtilities.h" - -/** - * A single constraint. - * Contains the attributes neccessary for creating a NSLayoutConstraint and adding it to the appropriate view - */ -@interface MASViewConstraint : MASConstraint - -/** - * First item/view and first attribute of the NSLayoutConstraint - */ -@property (nonatomic, strong, readonly) MASViewAttribute *firstViewAttribute; - -/** - * Second item/view and second attribute of the NSLayoutConstraint - */ -@property (nonatomic, strong, readonly) MASViewAttribute *secondViewAttribute; - -/** - * initialises the MASViewConstraint with the first part of the equation - * - * @param firstViewAttribute view.mas_left, view.mas_width etc. - * - * @return a new view constraint - */ -- (id)initWithFirstViewAttribute:(MASViewAttribute *)firstViewAttribute; - -/** - * Returns all MASViewConstraints installed with this view as a first item. - * - * @param view A view to retrieve constraints for. - * - * @return An array of MASViewConstraints. - */ -+ (NSArray *)installedConstraintsForView:(MAS_VIEW *)view; - -@end diff --git a/CustomKeyboard/Masonry/Masonry/MASViewConstraint.m b/CustomKeyboard/Masonry/Masonry/MASViewConstraint.m deleted file mode 100755 index 173eec1..0000000 --- a/CustomKeyboard/Masonry/Masonry/MASViewConstraint.m +++ /dev/null @@ -1,401 +0,0 @@ -// -// MASViewConstraint.m -// Masonry -// -// Created by Jonas Budelmann on 20/07/13. -// Copyright (c) 2013 cloudling. All rights reserved. -// - -#import "MASViewConstraint.h" -#import "MASConstraint+Private.h" -#import "MASCompositeConstraint.h" -#import "MASLayoutConstraint.h" -#import "View+MASAdditions.h" -#import - -@interface MAS_VIEW (MASConstraints) - -@property (nonatomic, readonly) NSMutableSet *mas_installedConstraints; - -@end - -@implementation MAS_VIEW (MASConstraints) - -static char kInstalledConstraintsKey; - -- (NSMutableSet *)mas_installedConstraints { - NSMutableSet *constraints = objc_getAssociatedObject(self, &kInstalledConstraintsKey); - if (!constraints) { - constraints = [NSMutableSet set]; - objc_setAssociatedObject(self, &kInstalledConstraintsKey, constraints, OBJC_ASSOCIATION_RETAIN_NONATOMIC); - } - return constraints; -} - -@end - - -@interface MASViewConstraint () - -@property (nonatomic, strong, readwrite) MASViewAttribute *secondViewAttribute; -@property (nonatomic, weak) MAS_VIEW *installedView; -@property (nonatomic, weak) MASLayoutConstraint *layoutConstraint; -@property (nonatomic, assign) NSLayoutRelation layoutRelation; -@property (nonatomic, assign) MASLayoutPriority layoutPriority; -@property (nonatomic, assign) CGFloat layoutMultiplier; -@property (nonatomic, assign) CGFloat layoutConstant; -@property (nonatomic, assign) BOOL hasLayoutRelation; -@property (nonatomic, strong) id mas_key; -@property (nonatomic, assign) BOOL useAnimator; - -@end - -@implementation MASViewConstraint - -- (id)initWithFirstViewAttribute:(MASViewAttribute *)firstViewAttribute { - self = [super init]; - if (!self) return nil; - - _firstViewAttribute = firstViewAttribute; - self.layoutPriority = MASLayoutPriorityRequired; - self.layoutMultiplier = 1; - - return self; -} - -#pragma mark - NSCoping - -- (id)copyWithZone:(NSZone __unused *)zone { - MASViewConstraint *constraint = [[MASViewConstraint alloc] initWithFirstViewAttribute:self.firstViewAttribute]; - constraint.layoutConstant = self.layoutConstant; - constraint.layoutRelation = self.layoutRelation; - constraint.layoutPriority = self.layoutPriority; - constraint.layoutMultiplier = self.layoutMultiplier; - constraint.delegate = self.delegate; - return constraint; -} - -#pragma mark - Public - -+ (NSArray *)installedConstraintsForView:(MAS_VIEW *)view { - return [view.mas_installedConstraints allObjects]; -} - -#pragma mark - Private - -- (void)setLayoutConstant:(CGFloat)layoutConstant { - _layoutConstant = layoutConstant; - -#if TARGET_OS_MAC && !(TARGET_OS_IPHONE || TARGET_OS_TV) - if (self.useAnimator) { - [self.layoutConstraint.animator setConstant:layoutConstant]; - } else { - self.layoutConstraint.constant = layoutConstant; - } -#else - self.layoutConstraint.constant = layoutConstant; -#endif -} - -- (void)setLayoutRelation:(NSLayoutRelation)layoutRelation { - _layoutRelation = layoutRelation; - self.hasLayoutRelation = YES; -} - -- (BOOL)supportsActiveProperty { - return [self.layoutConstraint respondsToSelector:@selector(isActive)]; -} - -- (BOOL)isActive { - BOOL active = YES; - if ([self supportsActiveProperty]) { - active = [self.layoutConstraint isActive]; - } - - return active; -} - -- (BOOL)hasBeenInstalled { - return (self.layoutConstraint != nil) && [self isActive]; -} - -- (void)setSecondViewAttribute:(id)secondViewAttribute { - if ([secondViewAttribute isKindOfClass:NSValue.class]) { - [self setLayoutConstantWithValue:secondViewAttribute]; - } else if ([secondViewAttribute isKindOfClass:MAS_VIEW.class]) { - _secondViewAttribute = [[MASViewAttribute alloc] initWithView:secondViewAttribute layoutAttribute:self.firstViewAttribute.layoutAttribute]; - } else if ([secondViewAttribute isKindOfClass:MASViewAttribute.class]) { - _secondViewAttribute = secondViewAttribute; - } else { - NSAssert(NO, @"attempting to add unsupported attribute: %@", secondViewAttribute); - } -} - -#pragma mark - NSLayoutConstraint multiplier proxies - -- (MASConstraint * (^)(CGFloat))multipliedBy { - return ^id(CGFloat multiplier) { - NSAssert(!self.hasBeenInstalled, - @"Cannot modify constraint multiplier after it has been installed"); - - self.layoutMultiplier = multiplier; - return self; - }; -} - - -- (MASConstraint * (^)(CGFloat))dividedBy { - return ^id(CGFloat divider) { - NSAssert(!self.hasBeenInstalled, - @"Cannot modify constraint multiplier after it has been installed"); - - self.layoutMultiplier = 1.0/divider; - return self; - }; -} - -#pragma mark - MASLayoutPriority proxy - -- (MASConstraint * (^)(MASLayoutPriority))priority { - return ^id(MASLayoutPriority priority) { - NSAssert(!self.hasBeenInstalled, - @"Cannot modify constraint priority after it has been installed"); - - self.layoutPriority = priority; - return self; - }; -} - -#pragma mark - NSLayoutRelation proxy - -- (MASConstraint * (^)(id, NSLayoutRelation))equalToWithRelation { - return ^id(id attribute, NSLayoutRelation relation) { - if ([attribute isKindOfClass:NSArray.class]) { - NSAssert(!self.hasLayoutRelation, @"Redefinition of constraint relation"); - NSMutableArray *children = NSMutableArray.new; - for (id attr in attribute) { - MASViewConstraint *viewConstraint = [self copy]; - viewConstraint.layoutRelation = relation; - viewConstraint.secondViewAttribute = attr; - [children addObject:viewConstraint]; - } - MASCompositeConstraint *compositeConstraint = [[MASCompositeConstraint alloc] initWithChildren:children]; - compositeConstraint.delegate = self.delegate; - [self.delegate constraint:self shouldBeReplacedWithConstraint:compositeConstraint]; - return compositeConstraint; - } else { - NSAssert(!self.hasLayoutRelation || self.layoutRelation == relation && [attribute isKindOfClass:NSValue.class], @"Redefinition of constraint relation"); - self.layoutRelation = relation; - self.secondViewAttribute = attribute; - return self; - } - }; -} - -#pragma mark - Semantic properties - -- (MASConstraint *)with { - return self; -} - -- (MASConstraint *)and { - return self; -} - -#pragma mark - attribute chaining - -- (MASConstraint *)addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute { - NSAssert(!self.hasLayoutRelation, @"Attributes should be chained before defining the constraint relation"); - - return [self.delegate constraint:self addConstraintWithLayoutAttribute:layoutAttribute]; -} - -#pragma mark - Animator proxy - -#if TARGET_OS_MAC && !(TARGET_OS_IPHONE || TARGET_OS_TV) - -- (MASConstraint *)animator { - self.useAnimator = YES; - return self; -} - -#endif - -#pragma mark - debug helpers - -- (MASConstraint * (^)(id))key { - return ^id(id key) { - self.mas_key = key; - return self; - }; -} - -#pragma mark - NSLayoutConstraint constant setters - -- (void)setInsets:(MASEdgeInsets)insets { - NSLayoutAttribute layoutAttribute = self.firstViewAttribute.layoutAttribute; - switch (layoutAttribute) { - case NSLayoutAttributeLeft: - case NSLayoutAttributeLeading: - self.layoutConstant = insets.left; - break; - case NSLayoutAttributeTop: - self.layoutConstant = insets.top; - break; - case NSLayoutAttributeBottom: - self.layoutConstant = -insets.bottom; - break; - case NSLayoutAttributeRight: - case NSLayoutAttributeTrailing: - self.layoutConstant = -insets.right; - break; - default: - break; - } -} - -- (void)setInset:(CGFloat)inset { - [self setInsets:(MASEdgeInsets){.top = inset, .left = inset, .bottom = inset, .right = inset}]; -} - -- (void)setOffset:(CGFloat)offset { - self.layoutConstant = offset; -} - -- (void)setSizeOffset:(CGSize)sizeOffset { - NSLayoutAttribute layoutAttribute = self.firstViewAttribute.layoutAttribute; - switch (layoutAttribute) { - case NSLayoutAttributeWidth: - self.layoutConstant = sizeOffset.width; - break; - case NSLayoutAttributeHeight: - self.layoutConstant = sizeOffset.height; - break; - default: - break; - } -} - -- (void)setCenterOffset:(CGPoint)centerOffset { - NSLayoutAttribute layoutAttribute = self.firstViewAttribute.layoutAttribute; - switch (layoutAttribute) { - case NSLayoutAttributeCenterX: - self.layoutConstant = centerOffset.x; - break; - case NSLayoutAttributeCenterY: - self.layoutConstant = centerOffset.y; - break; - default: - break; - } -} - -#pragma mark - MASConstraint - -- (void)activate { - [self install]; -} - -- (void)deactivate { - [self uninstall]; -} - -- (void)install { - if (self.hasBeenInstalled) { - return; - } - - if ([self supportsActiveProperty] && self.layoutConstraint) { - self.layoutConstraint.active = YES; - [self.firstViewAttribute.view.mas_installedConstraints addObject:self]; - return; - } - - MAS_VIEW *firstLayoutItem = self.firstViewAttribute.item; - NSLayoutAttribute firstLayoutAttribute = self.firstViewAttribute.layoutAttribute; - MAS_VIEW *secondLayoutItem = self.secondViewAttribute.item; - NSLayoutAttribute secondLayoutAttribute = self.secondViewAttribute.layoutAttribute; - - // alignment attributes must have a secondViewAttribute - // therefore we assume that is refering to superview - // eg make.left.equalTo(@10) - if (!self.firstViewAttribute.isSizeAttribute && !self.secondViewAttribute) { - secondLayoutItem = self.firstViewAttribute.view.superview; - secondLayoutAttribute = firstLayoutAttribute; - } - - MASLayoutConstraint *layoutConstraint - = [MASLayoutConstraint constraintWithItem:firstLayoutItem - attribute:firstLayoutAttribute - relatedBy:self.layoutRelation - toItem:secondLayoutItem - attribute:secondLayoutAttribute - multiplier:self.layoutMultiplier - constant:self.layoutConstant]; - - layoutConstraint.priority = self.layoutPriority; - layoutConstraint.mas_key = self.mas_key; - - if (self.secondViewAttribute.view) { - MAS_VIEW *closestCommonSuperview = [self.firstViewAttribute.view mas_closestCommonSuperview:self.secondViewAttribute.view]; - NSAssert(closestCommonSuperview, - @"couldn't find a common superview for %@ and %@", - self.firstViewAttribute.view, self.secondViewAttribute.view); - self.installedView = closestCommonSuperview; - } else if (self.firstViewAttribute.isSizeAttribute) { - self.installedView = self.firstViewAttribute.view; - } else { - self.installedView = self.firstViewAttribute.view.superview; - } - - - MASLayoutConstraint *existingConstraint = nil; - if (self.updateExisting) { - existingConstraint = [self layoutConstraintSimilarTo:layoutConstraint]; - } - if (existingConstraint) { - // just update the constant - existingConstraint.constant = layoutConstraint.constant; - self.layoutConstraint = existingConstraint; - } else { - [self.installedView addConstraint:layoutConstraint]; - self.layoutConstraint = layoutConstraint; - [firstLayoutItem.mas_installedConstraints addObject:self]; - } -} - -- (MASLayoutConstraint *)layoutConstraintSimilarTo:(MASLayoutConstraint *)layoutConstraint { - // check if any constraints are the same apart from the only mutable property constant - - // go through constraints in reverse as we do not want to match auto-resizing or interface builder constraints - // and they are likely to be added first. - for (NSLayoutConstraint *existingConstraint in self.installedView.constraints.reverseObjectEnumerator) { - if (![existingConstraint isKindOfClass:MASLayoutConstraint.class]) continue; - if (existingConstraint.firstItem != layoutConstraint.firstItem) continue; - if (existingConstraint.secondItem != layoutConstraint.secondItem) continue; - if (existingConstraint.firstAttribute != layoutConstraint.firstAttribute) continue; - if (existingConstraint.secondAttribute != layoutConstraint.secondAttribute) continue; - if (existingConstraint.relation != layoutConstraint.relation) continue; - if (existingConstraint.multiplier != layoutConstraint.multiplier) continue; - if (existingConstraint.priority != layoutConstraint.priority) continue; - - return (id)existingConstraint; - } - return nil; -} - -- (void)uninstall { - if ([self supportsActiveProperty]) { - self.layoutConstraint.active = NO; - [self.firstViewAttribute.view.mas_installedConstraints removeObject:self]; - return; - } - - [self.installedView removeConstraint:self.layoutConstraint]; - self.layoutConstraint = nil; - self.installedView = nil; - - [self.firstViewAttribute.view.mas_installedConstraints removeObject:self]; -} - -@end diff --git a/CustomKeyboard/Masonry/Masonry/Masonry.h b/CustomKeyboard/Masonry/Masonry/Masonry.h deleted file mode 100755 index d1bd579..0000000 --- a/CustomKeyboard/Masonry/Masonry/Masonry.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// Masonry.h -// Masonry -// -// Created by Jonas Budelmann on 20/07/13. -// Copyright (c) 2013 cloudling. All rights reserved. -// - -#import - -//! Project version number for Masonry. -FOUNDATION_EXPORT double MasonryVersionNumber; - -//! Project version string for Masonry. -FOUNDATION_EXPORT const unsigned char MasonryVersionString[]; - -#import "MASUtilities.h" -#import "View+MASAdditions.h" -#import "View+MASShorthandAdditions.h" -#import "ViewController+MASAdditions.h" -#import "NSArray+MASAdditions.h" -#import "NSArray+MASShorthandAdditions.h" -#import "MASConstraint.h" -#import "MASCompositeConstraint.h" -#import "MASViewAttribute.h" -#import "MASViewConstraint.h" -#import "MASConstraintMaker.h" -#import "MASLayoutConstraint.h" -#import "NSLayoutConstraint+MASDebugAdditions.h" diff --git a/CustomKeyboard/Masonry/Masonry/NSArray+MASAdditions.h b/CustomKeyboard/Masonry/Masonry/NSArray+MASAdditions.h deleted file mode 100755 index 587618d..0000000 --- a/CustomKeyboard/Masonry/Masonry/NSArray+MASAdditions.h +++ /dev/null @@ -1,72 +0,0 @@ -// -// NSArray+MASAdditions.h -// -// -// Created by Daniel Hammond on 11/26/13. -// -// - -#import "MASUtilities.h" -#import "MASConstraintMaker.h" -#import "MASViewAttribute.h" - -typedef NS_ENUM(NSUInteger, MASAxisType) { - MASAxisTypeHorizontal, - MASAxisTypeVertical -}; - -@interface NSArray (MASAdditions) - -/** - * Creates a MASConstraintMaker with each view in the callee. - * Any constraints defined are added to the view or the appropriate superview once the block has finished executing on each view - * - * @param block scope within which you can build up the constraints which you wish to apply to each view. - * - * @return Array of created MASConstraints - */ -- (NSArray *)mas_makeConstraints:(void (NS_NOESCAPE ^)(MASConstraintMaker *make))block; - -/** - * Creates a MASConstraintMaker with each view in the callee. - * Any constraints defined are added to each view or the appropriate superview once the block has finished executing on each view. - * If an existing constraint exists then it will be updated instead. - * - * @param block scope within which you can build up the constraints which you wish to apply to each view. - * - * @return Array of created/updated MASConstraints - */ -- (NSArray *)mas_updateConstraints:(void (NS_NOESCAPE ^)(MASConstraintMaker *make))block; - -/** - * Creates a MASConstraintMaker with each view in the callee. - * Any constraints defined are added to each view or the appropriate superview once the block has finished executing on each view. - * All constraints previously installed for the views will be removed. - * - * @param block scope within which you can build up the constraints which you wish to apply to each view. - * - * @return Array of created/updated MASConstraints - */ -- (NSArray *)mas_remakeConstraints:(void (NS_NOESCAPE ^)(MASConstraintMaker *make))block; - -/** - * distribute with fixed spacing - * - * @param axisType which axis to distribute items along - * @param fixedSpacing the spacing between each item - * @param leadSpacing the spacing before the first item and the container - * @param tailSpacing the spacing after the last item and the container - */ -- (void)mas_distributeViewsAlongAxis:(MASAxisType)axisType withFixedSpacing:(CGFloat)fixedSpacing leadSpacing:(CGFloat)leadSpacing tailSpacing:(CGFloat)tailSpacing; - -/** - * distribute with fixed item size - * - * @param axisType which axis to distribute items along - * @param fixedItemLength the fixed length of each item - * @param leadSpacing the spacing before the first item and the container - * @param tailSpacing the spacing after the last item and the container - */ -- (void)mas_distributeViewsAlongAxis:(MASAxisType)axisType withFixedItemLength:(CGFloat)fixedItemLength leadSpacing:(CGFloat)leadSpacing tailSpacing:(CGFloat)tailSpacing; - -@end diff --git a/CustomKeyboard/Masonry/Masonry/NSArray+MASAdditions.m b/CustomKeyboard/Masonry/Masonry/NSArray+MASAdditions.m deleted file mode 100755 index 831d8cd..0000000 --- a/CustomKeyboard/Masonry/Masonry/NSArray+MASAdditions.m +++ /dev/null @@ -1,162 +0,0 @@ -// -// NSArray+MASAdditions.m -// -// -// Created by Daniel Hammond on 11/26/13. -// -// - -#import "NSArray+MASAdditions.h" -#import "View+MASAdditions.h" - -@implementation NSArray (MASAdditions) - -- (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *make))block { - NSMutableArray *constraints = [NSMutableArray array]; - for (MAS_VIEW *view in self) { - NSAssert([view isKindOfClass:[MAS_VIEW class]], @"All objects in the array must be views"); - [constraints addObjectsFromArray:[view mas_makeConstraints:block]]; - } - return constraints; -} - -- (NSArray *)mas_updateConstraints:(void(^)(MASConstraintMaker *make))block { - NSMutableArray *constraints = [NSMutableArray array]; - for (MAS_VIEW *view in self) { - NSAssert([view isKindOfClass:[MAS_VIEW class]], @"All objects in the array must be views"); - [constraints addObjectsFromArray:[view mas_updateConstraints:block]]; - } - return constraints; -} - -- (NSArray *)mas_remakeConstraints:(void(^)(MASConstraintMaker *make))block { - NSMutableArray *constraints = [NSMutableArray array]; - for (MAS_VIEW *view in self) { - NSAssert([view isKindOfClass:[MAS_VIEW class]], @"All objects in the array must be views"); - [constraints addObjectsFromArray:[view mas_remakeConstraints:block]]; - } - return constraints; -} - -- (void)mas_distributeViewsAlongAxis:(MASAxisType)axisType withFixedSpacing:(CGFloat)fixedSpacing leadSpacing:(CGFloat)leadSpacing tailSpacing:(CGFloat)tailSpacing { - if (self.count < 2) { - NSAssert(self.count>1,@"views to distribute need to bigger than one"); - return; - } - - MAS_VIEW *tempSuperView = [self mas_commonSuperviewOfViews]; - if (axisType == MASAxisTypeHorizontal) { - MAS_VIEW *prev; - for (int i = 0; i < self.count; i++) { - MAS_VIEW *v = self[i]; - [v mas_makeConstraints:^(MASConstraintMaker *make) { - if (prev) { - make.width.equalTo(prev); - make.left.equalTo(prev.mas_right).offset(fixedSpacing); - if (i == self.count - 1) {//last one - make.right.equalTo(tempSuperView).offset(-tailSpacing); - } - } - else {//first one - make.left.equalTo(tempSuperView).offset(leadSpacing); - } - - }]; - prev = v; - } - } - else { - MAS_VIEW *prev; - for (int i = 0; i < self.count; i++) { - MAS_VIEW *v = self[i]; - [v mas_makeConstraints:^(MASConstraintMaker *make) { - if (prev) { - make.height.equalTo(prev); - make.top.equalTo(prev.mas_bottom).offset(fixedSpacing); - if (i == self.count - 1) {//last one - make.bottom.equalTo(tempSuperView).offset(-tailSpacing); - } - } - else {//first one - make.top.equalTo(tempSuperView).offset(leadSpacing); - } - - }]; - prev = v; - } - } -} - -- (void)mas_distributeViewsAlongAxis:(MASAxisType)axisType withFixedItemLength:(CGFloat)fixedItemLength leadSpacing:(CGFloat)leadSpacing tailSpacing:(CGFloat)tailSpacing { - if (self.count < 2) { - NSAssert(self.count>1,@"views to distribute need to bigger than one"); - return; - } - - MAS_VIEW *tempSuperView = [self mas_commonSuperviewOfViews]; - if (axisType == MASAxisTypeHorizontal) { - MAS_VIEW *prev; - for (int i = 0; i < self.count; i++) { - MAS_VIEW *v = self[i]; - [v mas_makeConstraints:^(MASConstraintMaker *make) { - make.width.equalTo(@(fixedItemLength)); - if (prev) { - if (i == self.count - 1) {//last one - make.right.equalTo(tempSuperView).offset(-tailSpacing); - } - else { - CGFloat offset = (1-(i/((CGFloat)self.count-1)))*(fixedItemLength+leadSpacing)-i*tailSpacing/(((CGFloat)self.count-1)); - make.right.equalTo(tempSuperView).multipliedBy(i/((CGFloat)self.count-1)).with.offset(offset); - } - } - else {//first one - make.left.equalTo(tempSuperView).offset(leadSpacing); - } - }]; - prev = v; - } - } - else { - MAS_VIEW *prev; - for (int i = 0; i < self.count; i++) { - MAS_VIEW *v = self[i]; - [v mas_makeConstraints:^(MASConstraintMaker *make) { - make.height.equalTo(@(fixedItemLength)); - if (prev) { - if (i == self.count - 1) {//last one - make.bottom.equalTo(tempSuperView).offset(-tailSpacing); - } - else { - CGFloat offset = (1-(i/((CGFloat)self.count-1)))*(fixedItemLength+leadSpacing)-i*tailSpacing/(((CGFloat)self.count-1)); - make.bottom.equalTo(tempSuperView).multipliedBy(i/((CGFloat)self.count-1)).with.offset(offset); - } - } - else {//first one - make.top.equalTo(tempSuperView).offset(leadSpacing); - } - }]; - prev = v; - } - } -} - -- (MAS_VIEW *)mas_commonSuperviewOfViews -{ - MAS_VIEW *commonSuperview = nil; - MAS_VIEW *previousView = nil; - for (id object in self) { - if ([object isKindOfClass:[MAS_VIEW class]]) { - MAS_VIEW *view = (MAS_VIEW *)object; - if (previousView) { - commonSuperview = [view mas_closestCommonSuperview:commonSuperview]; - } else { - commonSuperview = view; - } - previousView = view; - } - } - NSAssert(commonSuperview, @"Can't constrain views that do not share a common superview. Make sure that all the views in this array have been added into the same view hierarchy."); - return commonSuperview; -} - -@end diff --git a/CustomKeyboard/Masonry/Masonry/NSArray+MASShorthandAdditions.h b/CustomKeyboard/Masonry/Masonry/NSArray+MASShorthandAdditions.h deleted file mode 100755 index 8b47369..0000000 --- a/CustomKeyboard/Masonry/Masonry/NSArray+MASShorthandAdditions.h +++ /dev/null @@ -1,41 +0,0 @@ -// -// NSArray+MASShorthandAdditions.h -// Masonry -// -// Created by Jonas Budelmann on 22/07/13. -// Copyright (c) 2013 Jonas Budelmann. All rights reserved. -// - -#import "NSArray+MASAdditions.h" - -#ifdef MAS_SHORTHAND - -/** - * Shorthand array additions without the 'mas_' prefixes, - * only enabled if MAS_SHORTHAND is defined - */ -@interface NSArray (MASShorthandAdditions) - -- (NSArray *)makeConstraints:(void(^)(MASConstraintMaker *make))block; -- (NSArray *)updateConstraints:(void(^)(MASConstraintMaker *make))block; -- (NSArray *)remakeConstraints:(void(^)(MASConstraintMaker *make))block; - -@end - -@implementation NSArray (MASShorthandAdditions) - -- (NSArray *)makeConstraints:(void(^)(MASConstraintMaker *))block { - return [self mas_makeConstraints:block]; -} - -- (NSArray *)updateConstraints:(void(^)(MASConstraintMaker *))block { - return [self mas_updateConstraints:block]; -} - -- (NSArray *)remakeConstraints:(void(^)(MASConstraintMaker *))block { - return [self mas_remakeConstraints:block]; -} - -@end - -#endif diff --git a/CustomKeyboard/Masonry/Masonry/NSLayoutConstraint+MASDebugAdditions.h b/CustomKeyboard/Masonry/Masonry/NSLayoutConstraint+MASDebugAdditions.h deleted file mode 100755 index 1279b4f..0000000 --- a/CustomKeyboard/Masonry/Masonry/NSLayoutConstraint+MASDebugAdditions.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// NSLayoutConstraint+MASDebugAdditions.h -// Masonry -// -// Created by Jonas Budelmann on 3/08/13. -// Copyright (c) 2013 Jonas Budelmann. All rights reserved. -// - -#import "MASUtilities.h" - -/** - * makes debug and log output of NSLayoutConstraints more readable - */ -@interface NSLayoutConstraint (MASDebugAdditions) - -@end diff --git a/CustomKeyboard/Masonry/Masonry/NSLayoutConstraint+MASDebugAdditions.m b/CustomKeyboard/Masonry/Masonry/NSLayoutConstraint+MASDebugAdditions.m deleted file mode 100755 index ab539a2..0000000 --- a/CustomKeyboard/Masonry/Masonry/NSLayoutConstraint+MASDebugAdditions.m +++ /dev/null @@ -1,146 +0,0 @@ -// -// NSLayoutConstraint+MASDebugAdditions.m -// Masonry -// -// Created by Jonas Budelmann on 3/08/13. -// Copyright (c) 2013 Jonas Budelmann. All rights reserved. -// - -#import "NSLayoutConstraint+MASDebugAdditions.h" -#import "MASConstraint.h" -#import "MASLayoutConstraint.h" - -@implementation NSLayoutConstraint (MASDebugAdditions) - -#pragma mark - description maps - -+ (NSDictionary *)layoutRelationDescriptionsByValue { - static dispatch_once_t once; - static NSDictionary *descriptionMap; - dispatch_once(&once, ^{ - descriptionMap = @{ - @(NSLayoutRelationEqual) : @"==", - @(NSLayoutRelationGreaterThanOrEqual) : @">=", - @(NSLayoutRelationLessThanOrEqual) : @"<=", - }; - }); - return descriptionMap; -} - -+ (NSDictionary *)layoutAttributeDescriptionsByValue { - static dispatch_once_t once; - static NSDictionary *descriptionMap; - dispatch_once(&once, ^{ - descriptionMap = @{ - @(NSLayoutAttributeTop) : @"top", - @(NSLayoutAttributeLeft) : @"left", - @(NSLayoutAttributeBottom) : @"bottom", - @(NSLayoutAttributeRight) : @"right", - @(NSLayoutAttributeLeading) : @"leading", - @(NSLayoutAttributeTrailing) : @"trailing", - @(NSLayoutAttributeWidth) : @"width", - @(NSLayoutAttributeHeight) : @"height", - @(NSLayoutAttributeCenterX) : @"centerX", - @(NSLayoutAttributeCenterY) : @"centerY", - @(NSLayoutAttributeBaseline) : @"baseline", - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) - @(NSLayoutAttributeFirstBaseline) : @"firstBaseline", - @(NSLayoutAttributeLastBaseline) : @"lastBaseline", -#endif - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) - @(NSLayoutAttributeLeftMargin) : @"leftMargin", - @(NSLayoutAttributeRightMargin) : @"rightMargin", - @(NSLayoutAttributeTopMargin) : @"topMargin", - @(NSLayoutAttributeBottomMargin) : @"bottomMargin", - @(NSLayoutAttributeLeadingMargin) : @"leadingMargin", - @(NSLayoutAttributeTrailingMargin) : @"trailingMargin", - @(NSLayoutAttributeCenterXWithinMargins) : @"centerXWithinMargins", - @(NSLayoutAttributeCenterYWithinMargins) : @"centerYWithinMargins", -#endif - - }; - - }); - return descriptionMap; -} - - -+ (NSDictionary *)layoutPriorityDescriptionsByValue { - static dispatch_once_t once; - static NSDictionary *descriptionMap; - dispatch_once(&once, ^{ -#if TARGET_OS_IPHONE || TARGET_OS_TV - descriptionMap = @{ - @(MASLayoutPriorityDefaultHigh) : @"high", - @(MASLayoutPriorityDefaultLow) : @"low", - @(MASLayoutPriorityDefaultMedium) : @"medium", - @(MASLayoutPriorityRequired) : @"required", - @(MASLayoutPriorityFittingSizeLevel) : @"fitting size", - }; -#elif TARGET_OS_MAC - descriptionMap = @{ - @(MASLayoutPriorityDefaultHigh) : @"high", - @(MASLayoutPriorityDragThatCanResizeWindow) : @"drag can resize window", - @(MASLayoutPriorityDefaultMedium) : @"medium", - @(MASLayoutPriorityWindowSizeStayPut) : @"window size stay put", - @(MASLayoutPriorityDragThatCannotResizeWindow) : @"drag cannot resize window", - @(MASLayoutPriorityDefaultLow) : @"low", - @(MASLayoutPriorityFittingSizeCompression) : @"fitting size", - @(MASLayoutPriorityRequired) : @"required", - }; -#endif - }); - return descriptionMap; -} - -#pragma mark - description override - -+ (NSString *)descriptionForObject:(id)obj { - if ([obj respondsToSelector:@selector(mas_key)] && [obj mas_key]) { - return [NSString stringWithFormat:@"%@:%@", [obj class], [obj mas_key]]; - } - return [NSString stringWithFormat:@"%@:%p", [obj class], obj]; -} - -- (NSString *)description { - NSMutableString *description = [[NSMutableString alloc] initWithString:@"<"]; - - [description appendString:[self.class descriptionForObject:self]]; - - [description appendFormat:@" %@", [self.class descriptionForObject:self.firstItem]]; - if (self.firstAttribute != NSLayoutAttributeNotAnAttribute) { - [description appendFormat:@".%@", self.class.layoutAttributeDescriptionsByValue[@(self.firstAttribute)]]; - } - - [description appendFormat:@" %@", self.class.layoutRelationDescriptionsByValue[@(self.relation)]]; - - if (self.secondItem) { - [description appendFormat:@" %@", [self.class descriptionForObject:self.secondItem]]; - } - if (self.secondAttribute != NSLayoutAttributeNotAnAttribute) { - [description appendFormat:@".%@", self.class.layoutAttributeDescriptionsByValue[@(self.secondAttribute)]]; - } - - if (self.multiplier != 1) { - [description appendFormat:@" * %g", self.multiplier]; - } - - if (self.secondAttribute == NSLayoutAttributeNotAnAttribute) { - [description appendFormat:@" %g", self.constant]; - } else { - if (self.constant) { - [description appendFormat:@" %@ %g", (self.constant < 0 ? @"-" : @"+"), ABS(self.constant)]; - } - } - - if (self.priority != MASLayoutPriorityRequired) { - [description appendFormat:@" ^%@", self.class.layoutPriorityDescriptionsByValue[@(self.priority)] ?: [NSNumber numberWithDouble:self.priority]]; - } - - [description appendString:@">"]; - return description; -} - -@end diff --git a/CustomKeyboard/Masonry/Masonry/View+MASAdditions.h b/CustomKeyboard/Masonry/Masonry/View+MASAdditions.h deleted file mode 100755 index f7343d2..0000000 --- a/CustomKeyboard/Masonry/Masonry/View+MASAdditions.h +++ /dev/null @@ -1,111 +0,0 @@ -// -// UIView+MASAdditions.h -// Masonry -// -// Created by Jonas Budelmann on 20/07/13. -// Copyright (c) 2013 cloudling. All rights reserved. -// - -#import "MASUtilities.h" -#import "MASConstraintMaker.h" -#import "MASViewAttribute.h" - -/** - * Provides constraint maker block - * and convience methods for creating MASViewAttribute which are view + NSLayoutAttribute pairs - */ -@interface MAS_VIEW (MASAdditions) - -/** - * following properties return a new MASViewAttribute with current view and appropriate NSLayoutAttribute - */ -@property (nonatomic, strong, readonly) MASViewAttribute *mas_left; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_top; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_right; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_bottom; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_leading; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_trailing; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_width; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_height; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_centerX; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_centerY; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_baseline; -@property (nonatomic, strong, readonly) MASViewAttribute *(^mas_attribute)(NSLayoutAttribute attr); - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) - -@property (nonatomic, strong, readonly) MASViewAttribute *mas_firstBaseline; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_lastBaseline; - -#endif - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) - -@property (nonatomic, strong, readonly) MASViewAttribute *mas_leftMargin; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_rightMargin; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_topMargin; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_bottomMargin; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_leadingMargin; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_trailingMargin; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_centerXWithinMargins; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_centerYWithinMargins; - -#endif - -#if (__IPHONE_OS_VERSION_MAX_ALLOWED >= 110000) || (__TV_OS_VERSION_MAX_ALLOWED >= 110000) - -@property (nonatomic, strong, readonly) MASViewAttribute *mas_safeAreaLayoutGuide API_AVAILABLE(ios(11.0),tvos(11.0)); -@property (nonatomic, strong, readonly) MASViewAttribute *mas_safeAreaLayoutGuideTop API_AVAILABLE(ios(11.0),tvos(11.0)); -@property (nonatomic, strong, readonly) MASViewAttribute *mas_safeAreaLayoutGuideBottom API_AVAILABLE(ios(11.0),tvos(11.0)); -@property (nonatomic, strong, readonly) MASViewAttribute *mas_safeAreaLayoutGuideLeft API_AVAILABLE(ios(11.0),tvos(11.0)); -@property (nonatomic, strong, readonly) MASViewAttribute *mas_safeAreaLayoutGuideRight API_AVAILABLE(ios(11.0),tvos(11.0)); - -#endif - -/** - * a key to associate with this view - */ -@property (nonatomic, strong) id mas_key; - -/** - * Finds the closest common superview between this view and another view - * - * @param view other view - * - * @return returns nil if common superview could not be found - */ -- (instancetype)mas_closestCommonSuperview:(MAS_VIEW *)view; - -/** - * Creates a MASConstraintMaker with the callee view. - * Any constraints defined are added to the view or the appropriate superview once the block has finished executing - * - * @param block scope within which you can build up the constraints which you wish to apply to the view. - * - * @return Array of created MASConstraints - */ -- (NSArray *)mas_makeConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *make))block; - -/** - * Creates a MASConstraintMaker with the callee view. - * Any constraints defined are added to the view or the appropriate superview once the block has finished executing. - * If an existing constraint exists then it will be updated instead. - * - * @param block scope within which you can build up the constraints which you wish to apply to the view. - * - * @return Array of created/updated MASConstraints - */ -- (NSArray *)mas_updateConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *make))block; - -/** - * Creates a MASConstraintMaker with the callee view. - * Any constraints defined are added to the view or the appropriate superview once the block has finished executing. - * All constraints previously installed for the view will be removed. - * - * @param block scope within which you can build up the constraints which you wish to apply to the view. - * - * @return Array of created/updated MASConstraints - */ -- (NSArray *)mas_remakeConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *make))block; - -@end diff --git a/CustomKeyboard/Masonry/Masonry/View+MASAdditions.m b/CustomKeyboard/Masonry/Masonry/View+MASAdditions.m deleted file mode 100755 index 4fa07b4..0000000 --- a/CustomKeyboard/Masonry/Masonry/View+MASAdditions.m +++ /dev/null @@ -1,186 +0,0 @@ -// -// UIView+MASAdditions.m -// Masonry -// -// Created by Jonas Budelmann on 20/07/13. -// Copyright (c) 2013 cloudling. All rights reserved. -// - -#import "View+MASAdditions.h" -#import - -@implementation MAS_VIEW (MASAdditions) - -- (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *))block { - self.translatesAutoresizingMaskIntoConstraints = NO; - MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self]; - block(constraintMaker); - return [constraintMaker install]; -} - -- (NSArray *)mas_updateConstraints:(void(^)(MASConstraintMaker *))block { - self.translatesAutoresizingMaskIntoConstraints = NO; - MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self]; - constraintMaker.updateExisting = YES; - block(constraintMaker); - return [constraintMaker install]; -} - -- (NSArray *)mas_remakeConstraints:(void(^)(MASConstraintMaker *make))block { - self.translatesAutoresizingMaskIntoConstraints = NO; - MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self]; - constraintMaker.removeExisting = YES; - block(constraintMaker); - return [constraintMaker install]; -} - -#pragma mark - NSLayoutAttribute properties - -- (MASViewAttribute *)mas_left { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeLeft]; -} - -- (MASViewAttribute *)mas_top { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeTop]; -} - -- (MASViewAttribute *)mas_right { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeRight]; -} - -- (MASViewAttribute *)mas_bottom { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeBottom]; -} - -- (MASViewAttribute *)mas_leading { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeLeading]; -} - -- (MASViewAttribute *)mas_trailing { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeTrailing]; -} - -- (MASViewAttribute *)mas_width { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeWidth]; -} - -- (MASViewAttribute *)mas_height { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeHeight]; -} - -- (MASViewAttribute *)mas_centerX { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeCenterX]; -} - -- (MASViewAttribute *)mas_centerY { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeCenterY]; -} - -- (MASViewAttribute *)mas_baseline { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeBaseline]; -} - -- (MASViewAttribute *(^)(NSLayoutAttribute))mas_attribute -{ - return ^(NSLayoutAttribute attr) { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:attr]; - }; -} - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) - -- (MASViewAttribute *)mas_firstBaseline { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeFirstBaseline]; -} -- (MASViewAttribute *)mas_lastBaseline { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeLastBaseline]; -} - -#endif - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) - -- (MASViewAttribute *)mas_leftMargin { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeLeftMargin]; -} - -- (MASViewAttribute *)mas_rightMargin { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeRightMargin]; -} - -- (MASViewAttribute *)mas_topMargin { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeTopMargin]; -} - -- (MASViewAttribute *)mas_bottomMargin { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeBottomMargin]; -} - -- (MASViewAttribute *)mas_leadingMargin { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeLeadingMargin]; -} - -- (MASViewAttribute *)mas_trailingMargin { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeTrailingMargin]; -} - -- (MASViewAttribute *)mas_centerXWithinMargins { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeCenterXWithinMargins]; -} - -- (MASViewAttribute *)mas_centerYWithinMargins { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeCenterYWithinMargins]; -} - -#endif - -#if (__IPHONE_OS_VERSION_MAX_ALLOWED >= 110000) || (__TV_OS_VERSION_MAX_ALLOWED >= 110000) - -- (MASViewAttribute *)mas_safeAreaLayoutGuide { - return [[MASViewAttribute alloc] initWithView:self item:self.safeAreaLayoutGuide layoutAttribute:NSLayoutAttributeBottom]; -} -- (MASViewAttribute *)mas_safeAreaLayoutGuideTop { - return [[MASViewAttribute alloc] initWithView:self item:self.safeAreaLayoutGuide layoutAttribute:NSLayoutAttributeTop]; -} -- (MASViewAttribute *)mas_safeAreaLayoutGuideBottom { - return [[MASViewAttribute alloc] initWithView:self item:self.safeAreaLayoutGuide layoutAttribute:NSLayoutAttributeBottom]; -} -- (MASViewAttribute *)mas_safeAreaLayoutGuideLeft { - return [[MASViewAttribute alloc] initWithView:self item:self.safeAreaLayoutGuide layoutAttribute:NSLayoutAttributeLeft]; -} -- (MASViewAttribute *)mas_safeAreaLayoutGuideRight { - return [[MASViewAttribute alloc] initWithView:self item:self.safeAreaLayoutGuide layoutAttribute:NSLayoutAttributeRight]; -} - -#endif - -#pragma mark - associated properties - -- (id)mas_key { - return objc_getAssociatedObject(self, @selector(mas_key)); -} - -- (void)setMas_key:(id)key { - objc_setAssociatedObject(self, @selector(mas_key), key, OBJC_ASSOCIATION_RETAIN_NONATOMIC); -} - -#pragma mark - heirachy - -- (instancetype)mas_closestCommonSuperview:(MAS_VIEW *)view { - MAS_VIEW *closestCommonSuperview = nil; - - MAS_VIEW *secondViewSuperview = view; - while (!closestCommonSuperview && secondViewSuperview) { - MAS_VIEW *firstViewSuperview = self; - while (!closestCommonSuperview && firstViewSuperview) { - if (secondViewSuperview == firstViewSuperview) { - closestCommonSuperview = secondViewSuperview; - } - firstViewSuperview = firstViewSuperview.superview; - } - secondViewSuperview = secondViewSuperview.superview; - } - return closestCommonSuperview; -} - -@end diff --git a/CustomKeyboard/Masonry/Masonry/View+MASShorthandAdditions.h b/CustomKeyboard/Masonry/Masonry/View+MASShorthandAdditions.h deleted file mode 100755 index 1c19a94..0000000 --- a/CustomKeyboard/Masonry/Masonry/View+MASShorthandAdditions.h +++ /dev/null @@ -1,133 +0,0 @@ -// -// UIView+MASShorthandAdditions.h -// Masonry -// -// Created by Jonas Budelmann on 22/07/13. -// Copyright (c) 2013 Jonas Budelmann. All rights reserved. -// - -#import "View+MASAdditions.h" - -#ifdef MAS_SHORTHAND - -/** - * Shorthand view additions without the 'mas_' prefixes, - * only enabled if MAS_SHORTHAND is defined - */ -@interface MAS_VIEW (MASShorthandAdditions) - -@property (nonatomic, strong, readonly) MASViewAttribute *left; -@property (nonatomic, strong, readonly) MASViewAttribute *top; -@property (nonatomic, strong, readonly) MASViewAttribute *right; -@property (nonatomic, strong, readonly) MASViewAttribute *bottom; -@property (nonatomic, strong, readonly) MASViewAttribute *leading; -@property (nonatomic, strong, readonly) MASViewAttribute *trailing; -@property (nonatomic, strong, readonly) MASViewAttribute *width; -@property (nonatomic, strong, readonly) MASViewAttribute *height; -@property (nonatomic, strong, readonly) MASViewAttribute *centerX; -@property (nonatomic, strong, readonly) MASViewAttribute *centerY; -@property (nonatomic, strong, readonly) MASViewAttribute *baseline; -@property (nonatomic, strong, readonly) MASViewAttribute *(^attribute)(NSLayoutAttribute attr); - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) - -@property (nonatomic, strong, readonly) MASViewAttribute *firstBaseline; -@property (nonatomic, strong, readonly) MASViewAttribute *lastBaseline; - -#endif - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) - -@property (nonatomic, strong, readonly) MASViewAttribute *leftMargin; -@property (nonatomic, strong, readonly) MASViewAttribute *rightMargin; -@property (nonatomic, strong, readonly) MASViewAttribute *topMargin; -@property (nonatomic, strong, readonly) MASViewAttribute *bottomMargin; -@property (nonatomic, strong, readonly) MASViewAttribute *leadingMargin; -@property (nonatomic, strong, readonly) MASViewAttribute *trailingMargin; -@property (nonatomic, strong, readonly) MASViewAttribute *centerXWithinMargins; -@property (nonatomic, strong, readonly) MASViewAttribute *centerYWithinMargins; - -#endif - -#if (__IPHONE_OS_VERSION_MAX_ALLOWED >= 110000) || (__TV_OS_VERSION_MAX_ALLOWED >= 110000) - -@property (nonatomic, strong, readonly) MASViewAttribute *safeAreaLayoutGuideTop API_AVAILABLE(ios(11.0),tvos(11.0)); -@property (nonatomic, strong, readonly) MASViewAttribute *safeAreaLayoutGuideBottom API_AVAILABLE(ios(11.0),tvos(11.0)); -@property (nonatomic, strong, readonly) MASViewAttribute *safeAreaLayoutGuideLeft API_AVAILABLE(ios(11.0),tvos(11.0)); -@property (nonatomic, strong, readonly) MASViewAttribute *safeAreaLayoutGuideRight API_AVAILABLE(ios(11.0),tvos(11.0)); - -#endif - -- (NSArray *)makeConstraints:(void(^)(MASConstraintMaker *make))block; -- (NSArray *)updateConstraints:(void(^)(MASConstraintMaker *make))block; -- (NSArray *)remakeConstraints:(void(^)(MASConstraintMaker *make))block; - -@end - -#define MAS_ATTR_FORWARD(attr) \ -- (MASViewAttribute *)attr { \ - return [self mas_##attr]; \ -} - -@implementation MAS_VIEW (MASShorthandAdditions) - -MAS_ATTR_FORWARD(top); -MAS_ATTR_FORWARD(left); -MAS_ATTR_FORWARD(bottom); -MAS_ATTR_FORWARD(right); -MAS_ATTR_FORWARD(leading); -MAS_ATTR_FORWARD(trailing); -MAS_ATTR_FORWARD(width); -MAS_ATTR_FORWARD(height); -MAS_ATTR_FORWARD(centerX); -MAS_ATTR_FORWARD(centerY); -MAS_ATTR_FORWARD(baseline); - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) - -MAS_ATTR_FORWARD(firstBaseline); -MAS_ATTR_FORWARD(lastBaseline); - -#endif - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) - -MAS_ATTR_FORWARD(leftMargin); -MAS_ATTR_FORWARD(rightMargin); -MAS_ATTR_FORWARD(topMargin); -MAS_ATTR_FORWARD(bottomMargin); -MAS_ATTR_FORWARD(leadingMargin); -MAS_ATTR_FORWARD(trailingMargin); -MAS_ATTR_FORWARD(centerXWithinMargins); -MAS_ATTR_FORWARD(centerYWithinMargins); - -#endif - -#if (__IPHONE_OS_VERSION_MAX_ALLOWED >= 110000) || (__TV_OS_VERSION_MAX_ALLOWED >= 110000) - -MAS_ATTR_FORWARD(safeAreaLayoutGuideTop); -MAS_ATTR_FORWARD(safeAreaLayoutGuideBottom); -MAS_ATTR_FORWARD(safeAreaLayoutGuideLeft); -MAS_ATTR_FORWARD(safeAreaLayoutGuideRight); - -#endif - -- (MASViewAttribute *(^)(NSLayoutAttribute))attribute { - return [self mas_attribute]; -} - -- (NSArray *)makeConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *))block { - return [self mas_makeConstraints:block]; -} - -- (NSArray *)updateConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *))block { - return [self mas_updateConstraints:block]; -} - -- (NSArray *)remakeConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *))block { - return [self mas_remakeConstraints:block]; -} - -@end - -#endif diff --git a/CustomKeyboard/Masonry/Masonry/ViewController+MASAdditions.h b/CustomKeyboard/Masonry/Masonry/ViewController+MASAdditions.h deleted file mode 100755 index 79fd1fa..0000000 --- a/CustomKeyboard/Masonry/Masonry/ViewController+MASAdditions.h +++ /dev/null @@ -1,30 +0,0 @@ -// -// UIViewController+MASAdditions.h -// Masonry -// -// Created by Craig Siemens on 2015-06-23. -// -// - -#import "MASUtilities.h" -#import "MASConstraintMaker.h" -#import "MASViewAttribute.h" - -#ifdef MAS_VIEW_CONTROLLER - -@interface MAS_VIEW_CONTROLLER (MASAdditions) - -/** - * following properties return a new MASViewAttribute with appropriate UILayoutGuide and NSLayoutAttribute - */ -@property (nonatomic, strong, readonly) MASViewAttribute *mas_topLayoutGuide; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_bottomLayoutGuide; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_topLayoutGuideTop; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_topLayoutGuideBottom; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_bottomLayoutGuideTop; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_bottomLayoutGuideBottom; - - -@end - -#endif diff --git a/CustomKeyboard/Masonry/Masonry/ViewController+MASAdditions.m b/CustomKeyboard/Masonry/Masonry/ViewController+MASAdditions.m deleted file mode 100755 index 2f5139f..0000000 --- a/CustomKeyboard/Masonry/Masonry/ViewController+MASAdditions.m +++ /dev/null @@ -1,39 +0,0 @@ -// -// UIViewController+MASAdditions.m -// Masonry -// -// Created by Craig Siemens on 2015-06-23. -// -// - -#import "ViewController+MASAdditions.h" - -#ifdef MAS_VIEW_CONTROLLER - -@implementation MAS_VIEW_CONTROLLER (MASAdditions) - -- (MASViewAttribute *)mas_topLayoutGuide { - return [[MASViewAttribute alloc] initWithView:self.view item:self.topLayoutGuide layoutAttribute:NSLayoutAttributeBottom]; -} -- (MASViewAttribute *)mas_topLayoutGuideTop { - return [[MASViewAttribute alloc] initWithView:self.view item:self.topLayoutGuide layoutAttribute:NSLayoutAttributeTop]; -} -- (MASViewAttribute *)mas_topLayoutGuideBottom { - return [[MASViewAttribute alloc] initWithView:self.view item:self.topLayoutGuide layoutAttribute:NSLayoutAttributeBottom]; -} - -- (MASViewAttribute *)mas_bottomLayoutGuide { - return [[MASViewAttribute alloc] initWithView:self.view item:self.bottomLayoutGuide layoutAttribute:NSLayoutAttributeTop]; -} -- (MASViewAttribute *)mas_bottomLayoutGuideTop { - return [[MASViewAttribute alloc] initWithView:self.view item:self.bottomLayoutGuide layoutAttribute:NSLayoutAttributeTop]; -} -- (MASViewAttribute *)mas_bottomLayoutGuideBottom { - return [[MASViewAttribute alloc] initWithView:self.view item:self.bottomLayoutGuide layoutAttribute:NSLayoutAttributeBottom]; -} - - - -@end - -#endif diff --git a/CustomKeyboard/Masonry/README.md b/CustomKeyboard/Masonry/README.md deleted file mode 100755 index d428657..0000000 --- a/CustomKeyboard/Masonry/README.md +++ /dev/null @@ -1,415 +0,0 @@ -# Masonry [![Build Status](https://travis-ci.org/SnapKit/Masonry.svg?branch=master)](https://travis-ci.org/SnapKit/Masonry) [![Coverage Status](https://img.shields.io/coveralls/SnapKit/Masonry.svg?style=flat-square)](https://coveralls.io/r/SnapKit/Masonry) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) ![Pod Version](https://img.shields.io/cocoapods/v/Masonry.svg?style=flat) - -**Masonry is still actively maintained, we are committed to fixing bugs and merging good quality PRs from the wider community. However if you're using Swift in your project, we recommend using [SnapKit](https://github.com/SnapKit/SnapKit) as it provides better type safety with a simpler API.** - -Masonry is a light-weight layout framework which wraps AutoLayout with a nicer syntax. Masonry has its own layout DSL which provides a chainable way of describing your NSLayoutConstraints which results in layout code that is more concise and readable. -Masonry supports iOS and Mac OS X. - -For examples take a look at the **Masonry iOS Examples** project in the Masonry workspace. You will need to run `pod install` after downloading. - -## What's wrong with NSLayoutConstraints? - -Under the hood Auto Layout is a powerful and flexible way of organising and laying out your views. However creating constraints from code is verbose and not very descriptive. -Imagine a simple example in which you want to have a view fill its superview but inset by 10 pixels on every side -```obj-c -UIView *superview = self.view; - -UIView *view1 = [[UIView alloc] init]; -view1.translatesAutoresizingMaskIntoConstraints = NO; -view1.backgroundColor = [UIColor greenColor]; -[superview addSubview:view1]; - -UIEdgeInsets padding = UIEdgeInsetsMake(10, 10, 10, 10); - -[superview addConstraints:@[ - - //view1 constraints - [NSLayoutConstraint constraintWithItem:view1 - attribute:NSLayoutAttributeTop - relatedBy:NSLayoutRelationEqual - toItem:superview - attribute:NSLayoutAttributeTop - multiplier:1.0 - constant:padding.top], - - [NSLayoutConstraint constraintWithItem:view1 - attribute:NSLayoutAttributeLeft - relatedBy:NSLayoutRelationEqual - toItem:superview - attribute:NSLayoutAttributeLeft - multiplier:1.0 - constant:padding.left], - - [NSLayoutConstraint constraintWithItem:view1 - attribute:NSLayoutAttributeBottom - relatedBy:NSLayoutRelationEqual - toItem:superview - attribute:NSLayoutAttributeBottom - multiplier:1.0 - constant:-padding.bottom], - - [NSLayoutConstraint constraintWithItem:view1 - attribute:NSLayoutAttributeRight - relatedBy:NSLayoutRelationEqual - toItem:superview - attribute:NSLayoutAttributeRight - multiplier:1 - constant:-padding.right], - - ]]; -``` -Even with such a simple example the code needed is quite verbose and quickly becomes unreadable when you have more than 2 or 3 views. -Another option is to use Visual Format Language (VFL), which is a bit less long winded. -However the ASCII type syntax has its own pitfalls and its also a bit harder to animate as `NSLayoutConstraint constraintsWithVisualFormat:` returns an array. - -## Prepare to meet your Maker! - -Heres the same constraints created using MASConstraintMaker - -```obj-c -UIEdgeInsets padding = UIEdgeInsetsMake(10, 10, 10, 10); - -[view1 mas_makeConstraints:^(MASConstraintMaker *make) { - make.top.equalTo(superview.mas_top).with.offset(padding.top); //with is an optional semantic filler - make.left.equalTo(superview.mas_left).with.offset(padding.left); - make.bottom.equalTo(superview.mas_bottom).with.offset(-padding.bottom); - make.right.equalTo(superview.mas_right).with.offset(-padding.right); -}]; -``` -Or even shorter - -```obj-c -[view1 mas_makeConstraints:^(MASConstraintMaker *make) { - make.edges.equalTo(superview).with.insets(padding); -}]; -``` - -Also note in the first example we had to add the constraints to the superview `[superview addConstraints:...`. -Masonry however will automagically add constraints to the appropriate view. - -Masonry will also call `view1.translatesAutoresizingMaskIntoConstraints = NO;` for you. - -## Not all things are created equal - -> `.equalTo` equivalent to **NSLayoutRelationEqual** - -> `.lessThanOrEqualTo` equivalent to **NSLayoutRelationLessThanOrEqual** - -> `.greaterThanOrEqualTo` equivalent to **NSLayoutRelationGreaterThanOrEqual** - -These three equality constraints accept one argument which can be any of the following: - -#### 1. MASViewAttribute - -```obj-c -make.centerX.lessThanOrEqualTo(view2.mas_left); -``` - -MASViewAttribute | NSLayoutAttribute -------------------------- | -------------------------- -view.mas_left | NSLayoutAttributeLeft -view.mas_right | NSLayoutAttributeRight -view.mas_top | NSLayoutAttributeTop -view.mas_bottom | NSLayoutAttributeBottom -view.mas_leading | NSLayoutAttributeLeading -view.mas_trailing | NSLayoutAttributeTrailing -view.mas_width | NSLayoutAttributeWidth -view.mas_height | NSLayoutAttributeHeight -view.mas_centerX | NSLayoutAttributeCenterX -view.mas_centerY | NSLayoutAttributeCenterY -view.mas_baseline | NSLayoutAttributeBaseline - -#### 2. UIView/NSView - -if you want view.left to be greater than or equal to label.left : -```obj-c -//these two constraints are exactly the same -make.left.greaterThanOrEqualTo(label); -make.left.greaterThanOrEqualTo(label.mas_left); -``` - -#### 3. NSNumber - -Auto Layout allows width and height to be set to constant values. -if you want to set view to have a minimum and maximum width you could pass a number to the equality blocks: -```obj-c -//width >= 200 && width <= 400 -make.width.greaterThanOrEqualTo(@200); -make.width.lessThanOrEqualTo(@400) -``` - -However Auto Layout does not allow alignment attributes such as left, right, centerY etc to be set to constant values. -So if you pass a NSNumber for these attributes Masonry will turn these into constraints relative to the view’s superview ie: -```obj-c -//creates view.left = view.superview.left + 10 -make.left.lessThanOrEqualTo(@10) -``` - -Instead of using NSNumber, you can use primitives and structs to build your constraints, like so: -```obj-c -make.top.mas_equalTo(42); -make.height.mas_equalTo(20); -make.size.mas_equalTo(CGSizeMake(50, 100)); -make.edges.mas_equalTo(UIEdgeInsetsMake(10, 0, 10, 0)); -make.left.mas_equalTo(view).mas_offset(UIEdgeInsetsMake(10, 0, 10, 0)); -``` - -By default, macros which support [autoboxing](https://en.wikipedia.org/wiki/Autoboxing#Autoboxing) are prefixed with `mas_`. Unprefixed versions are available by defining `MAS_SHORTHAND_GLOBALS` before importing Masonry. - -#### 4. NSArray - -An array of a mixture of any of the previous types -```obj-c -make.height.equalTo(@[view1.mas_height, view2.mas_height]); -make.height.equalTo(@[view1, view2]); -make.left.equalTo(@[view1, @100, view3.right]); -```` - -## Learn to prioritize - -> `.priority` allows you to specify an exact priority - -> `.priorityHigh` equivalent to **UILayoutPriorityDefaultHigh** - -> `.priorityMedium` is half way between high and low - -> `.priorityLow` equivalent to **UILayoutPriorityDefaultLow** - -Priorities are can be tacked on to the end of a constraint chain like so: -```obj-c -make.left.greaterThanOrEqualTo(label.mas_left).with.priorityLow(); - -make.top.equalTo(label.mas_top).with.priority(600); -``` - -## Composition, composition, composition - -Masonry also gives you a few convenience methods which create multiple constraints at the same time. These are called MASCompositeConstraints - -#### edges - -```obj-c -// make top, left, bottom, right equal view2 -make.edges.equalTo(view2); - -// make top = superview.top + 5, left = superview.left + 10, -// bottom = superview.bottom - 15, right = superview.right - 20 -make.edges.equalTo(superview).insets(UIEdgeInsetsMake(5, 10, 15, 20)) -``` - -#### size - -```obj-c -// make width and height greater than or equal to titleLabel -make.size.greaterThanOrEqualTo(titleLabel) - -// make width = superview.width + 100, height = superview.height - 50 -make.size.equalTo(superview).sizeOffset(CGSizeMake(100, -50)) -``` - -#### center -```obj-c -// make centerX and centerY = button1 -make.center.equalTo(button1) - -// make centerX = superview.centerX - 5, centerY = superview.centerY + 10 -make.center.equalTo(superview).centerOffset(CGPointMake(-5, 10)) -``` - -You can chain view attributes for increased readability: - -```obj-c -// All edges but the top should equal those of the superview -make.left.right.and.bottom.equalTo(superview); -make.top.equalTo(otherView); -``` - -## Hold on for dear life - -Sometimes you need modify existing constraints in order to animate or remove/replace constraints. -In Masonry there are a few different approaches to updating constraints. - -#### 1. References -You can hold on to a reference of a particular constraint by assigning the result of a constraint make expression to a local variable or a class property. -You could also reference multiple constraints by storing them away in an array. - -```obj-c -// in public/private interface -@property (nonatomic, strong) MASConstraint *topConstraint; - -... - -// when making constraints -[view1 mas_makeConstraints:^(MASConstraintMaker *make) { - self.topConstraint = make.top.equalTo(superview.mas_top).with.offset(padding.top); - make.left.equalTo(superview.mas_left).with.offset(padding.left); -}]; - -... -// then later you can call -[self.topConstraint uninstall]; -``` - -#### 2. mas_updateConstraints -Alternatively if you are only updating the constant value of the constraint you can use the convience method `mas_updateConstraints` instead of `mas_makeConstraints` - -```obj-c -// this is Apple's recommended place for adding/updating constraints -// this method can get called multiple times in response to setNeedsUpdateConstraints -// which can be called by UIKit internally or in your code if you need to trigger an update to your constraints -- (void)updateConstraints { - [self.growingButton mas_updateConstraints:^(MASConstraintMaker *make) { - make.center.equalTo(self); - make.width.equalTo(@(self.buttonSize.width)).priorityLow(); - make.height.equalTo(@(self.buttonSize.height)).priorityLow(); - make.width.lessThanOrEqualTo(self); - make.height.lessThanOrEqualTo(self); - }]; - - //according to apple super should be called at end of method - [super updateConstraints]; -} -``` - -### 3. mas_remakeConstraints -`mas_updateConstraints` is useful for updating a set of constraints, but doing anything beyond updating constant values can get exhausting. That's where `mas_remakeConstraints` comes in. - -`mas_remakeConstraints` is similar to `mas_updateConstraints`, but instead of updating constant values, it will remove all of its constraints before installing them again. This lets you provide different constraints without having to keep around references to ones which you want to remove. - -```obj-c -- (void)changeButtonPosition { - [self.button mas_remakeConstraints:^(MASConstraintMaker *make) { - make.size.equalTo(self.buttonSize); - - if (topLeft) { - make.top.and.left.offset(10); - } else { - make.bottom.and.right.offset(-10); - } - }]; -} -``` - -You can find more detailed examples of all three approaches in the **Masonry iOS Examples** project. - -## When the ^&*!@ hits the fan! - -Laying out your views doesn't always goto plan. So when things literally go pear shaped, you don't want to be looking at console output like this: - -```obj-c -Unable to simultaneously satisfy constraints.....blah blah blah.... -( - "=5000)]>", - "", - "", - "" -) - -Will attempt to recover by breaking constraint -=5000)]> -``` - -Masonry adds a category to NSLayoutConstraint which overrides the default implementation of `- (NSString *)description`. -Now you can give meaningful names to views and constraints, and also easily pick out the constraints created by Masonry. - -which means your console output can now look like this: - -```obj-c -Unable to simultaneously satisfy constraints......blah blah blah.... -( - "", - "= 5000>", - "", - "" -) - -Will attempt to recover by breaking constraint -= 5000> -``` - -For an example of how to set this up take a look at the **Masonry iOS Examples** project in the Masonry workspace. - -## Where should I create my constraints? - -```objc -@implementation DIYCustomView - -- (id)init { - self = [super init]; - if (!self) return nil; - - // --- Create your views here --- - self.button = [[UIButton alloc] init]; - - return self; -} - -// tell UIKit that you are using AutoLayout -+ (BOOL)requiresConstraintBasedLayout { - return YES; -} - -// this is Apple's recommended place for adding/updating constraints -- (void)updateConstraints { - - // --- remake/update constraints here - [self.button remakeConstraints:^(MASConstraintMaker *make) { - make.width.equalTo(@(self.buttonSize.width)); - make.height.equalTo(@(self.buttonSize.height)); - }]; - - //according to apple super should be called at end of method - [super updateConstraints]; -} - -- (void)didTapButton:(UIButton *)button { - // --- Do your changes ie change variables that affect your layout etc --- - self.buttonSize = CGSize(200, 200); - - // tell constraints they need updating - [self setNeedsUpdateConstraints]; -} - -@end -``` - -## Installation -Use the [orsome](http://www.youtube.com/watch?v=YaIZF8uUTtk) [CocoaPods](http://github.com/CocoaPods/CocoaPods). - -In your Podfile ->`pod 'Masonry'` - -If you want to use masonry without all those pesky 'mas_' prefixes. Add #define MAS_SHORTHAND to your prefix.pch before importing Masonry ->`#define MAS_SHORTHAND` - -Get busy Masoning ->`#import "Masonry.h"` - -## Code Snippets - -Copy the included code snippets to ``~/Library/Developer/Xcode/UserData/CodeSnippets`` to write your masonry blocks at lightning speed! - -`mas_make` -> ` [<#view#> mas_makeConstraints:^(MASConstraintMaker *make) { - <#code#> - }];` - -`mas_update` -> ` [<#view#> mas_updateConstraints:^(MASConstraintMaker *make) { - <#code#> - }];` - -`mas_remake` -> ` [<#view#> mas_remakeConstraints:^(MASConstraintMaker *make) { - <#code#> - }];` - -## Features -* Not limited to subset of Auto Layout. Anything NSLayoutConstraint can do, Masonry can do too! -* Great debug support, give your views and constraints meaningful names. -* Constraints read like sentences. -* No crazy macro magic. Masonry won't pollute the global namespace with macros. -* Not string or dictionary based and hence you get compile time checking. - -## TODO -* Eye candy -* Mac example project -* More tests and examples - diff --git a/CustomKeyboard/Model/KBKey.h b/CustomKeyboard/Model/KBKey.h new file mode 100644 index 0000000..44bcdda --- /dev/null +++ b/CustomKeyboard/Model/KBKey.h @@ -0,0 +1,32 @@ +// +// KBKey.h +// CustomKeyboard +// +// 简单的键位数据模型,用于描述键盘上的一个键。 +// + +#import +#import + +typedef NS_ENUM(NSInteger, KBKeyType) { + KBKeyTypeCharacter = 0, // 普通字符输出 + KBKeyTypeBackspace, // 删除 + KBKeyTypeShift, // 大小写切换 + KBKeyTypeModeChange, // 模式切换(如 123/ABC) + KBKeyTypeSpace, // 空格 + KBKeyTypeReturn, // 回车/发送 + KBKeyTypeGlobe, // 系统地球键 + KBKeyTypeCustom, // 自定义功能占位 + KBKeyTypeSymbolsToggle // 数字面板内的“#+=/123”切换 +}; + +@interface KBKey : NSObject + +@property (nonatomic, assign) KBKeyType type; +@property (nonatomic, copy) NSString *title; // 显示标题 +@property (nonatomic, copy) NSString *output; // 字符键插入的文本 + ++ (instancetype)keyWithTitle:(NSString *)title output:(NSString *)output; ++ (instancetype)keyWithTitle:(NSString *)title type:(KBKeyType)type; + +@end diff --git a/CustomKeyboard/Model/KBKey.m b/CustomKeyboard/Model/KBKey.m new file mode 100644 index 0000000..92d2625 --- /dev/null +++ b/CustomKeyboard/Model/KBKey.m @@ -0,0 +1,27 @@ +// +// KBKey.m +// CustomKeyboard +// + +#import "KBKey.h" + +@implementation KBKey + ++ (instancetype)keyWithTitle:(NSString *)title output:(NSString *)output { + KBKey *k = [[KBKey alloc] init]; + k.type = KBKeyTypeCharacter; + k.title = title ?: @""; + k.output = output ?: title ?: @""; + return k; +} + ++ (instancetype)keyWithTitle:(NSString *)title type:(KBKeyType)type { + KBKey *k = [[KBKey alloc] init]; + k.type = type; + k.title = title ?: @""; + k.output = @""; + return k; +} + +@end + diff --git a/CustomKeyboard/Network/KBNetworkManager.h b/CustomKeyboard/Network/KBNetworkManager.h new file mode 100644 index 0000000..c0dfc9e --- /dev/null +++ b/CustomKeyboard/Network/KBNetworkManager.h @@ -0,0 +1,57 @@ +// +// KBNetworkManager.h +// CustomKeyboard +// +// 轻量网络层封装(扩展安全)。支持 GET/POST(JSON)。 +// 注意:键盘扩展需要"允许完全访问"后才可联网, +// 建议由宿主控制器在确认后调用 `setEnabled:YES` 再发起请求。 +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +extern NSErrorDomain const KBNetworkErrorDomain; +typedef NS_ERROR_ENUM(KBNetworkErrorDomain, KBNetworkError) { + KBNetworkErrorDisabled = 1, // 未启用网络(例如未开启完全访问) + KBNetworkErrorInvalidURL = 2, + KBNetworkErrorInvalidResponse = 3, + KBNetworkErrorDecodeFailed = 4, +}; + +/// 简单的 JSON 回调:json 为 NSDictionary/NSArray 或者在非 JSON 情况下返回 NSData +typedef void(^KBNetworkCompletion)(id _Nullable jsonOrData, NSURLResponse * _Nullable response, NSError * _Nullable error); + +@interface KBNetworkManager : NSObject + +/// 单例 ++ (instancetype)shared; + +/// 是否允许网络(默认为 NO,宿主在合适时机置 YES) +@property (atomic, assign, getter=isEnabled) BOOL enabled; + +/// 可选的基础域名,例如 https://api.example.com +@property (nonatomic, strong, nullable) NSURL *baseURL; + +/// 全局默认请求头(每次请求会与局部 headers 合并,局部优先) +@property (nonatomic, copy) NSDictionary *defaultHeaders; + +/// 超时时间(默认 10s) +@property (nonatomic, assign) NSTimeInterval timeout; + +/// GET 请求,parameters 会拼到 URL 上 +- (nullable NSURLSessionDataTask *)GET:(NSString *)path + parameters:(nullable NSDictionary *)parameters + headers:(nullable NSDictionary *)headers + completion:(KBNetworkCompletion)completion; + +/// POST JSON 请求,jsonBody 会以 application/json 发送 +- (nullable NSURLSessionDataTask *)POST:(NSString *)path + jsonBody:(nullable id)jsonBody + headers:(nullable NSDictionary *)headers + completion:(KBNetworkCompletion)completion; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/CustomKeyboard/Network/KBNetworkManager.m b/CustomKeyboard/Network/KBNetworkManager.m new file mode 100644 index 0000000..824109b --- /dev/null +++ b/CustomKeyboard/Network/KBNetworkManager.m @@ -0,0 +1,169 @@ +// +// KBNetworkManager.m +// CustomKeyboard +// + +#import "KBNetworkManager.h" +#import "AFNetworking.h" +#import "KBAuthManager.h" + +NSErrorDomain const KBNetworkErrorDomain = @"com.company.keyboard.network"; + +@interface KBNetworkManager () +@property (nonatomic, strong) AFHTTPSessionManager *manager; // AFN 管理器(ephemeral 配置) +// 私有错误派发 +- (void)fail:(KBNetworkError)code completion:(KBNetworkCompletion)completion; +@end + +@implementation KBNetworkManager + ++ (instancetype)shared { + static KBNetworkManager *m; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ m = [KBNetworkManager new]; }); + return m; +} + +- (instancetype)init { + if (self = [super init]) { + _enabled = NO; // 键盘扩展默认无网络能力,需外部显式开启 + _timeout = 10.0; + _defaultHeaders = @{ @"Accept": @"application/json" }; + // 设置基础域名,路径可相对该地址拼接 + _baseURL = [NSURL URLWithString:KB_BASE_URL]; + } + return self; +} + +#pragma mark - Public + +- (NSURLSessionDataTask *)GET:(NSString *)path + parameters:(NSDictionary *)parameters + headers:(NSDictionary *)headers + completion:(KBNetworkCompletion)completion { + if (![self ensureEnabled:completion]) return nil; + NSString *urlString = [self buildURLStringWithPath:path]; + if (!urlString) { [self fail:KBNetworkErrorInvalidURL completion:completion]; return nil; } + // 使用 AFHTTPRequestSerializer 生成带参数与头的请求 + AFHTTPRequestSerializer *serializer = [AFHTTPRequestSerializer serializer]; + serializer.timeoutInterval = self.timeout; + NSMutableURLRequest *req = [serializer requestWithMethod:@"GET" + URLString:urlString + parameters:parameters + error:NULL]; + [self applyHeaders:headers toMutableRequest:req contentType:nil]; + return [self startAFTaskWithRequest:req completion:completion]; +} + +- (NSURLSessionDataTask *)POST:(NSString *)path + jsonBody:(id)jsonBody + headers:(NSDictionary *)headers + completion:(KBNetworkCompletion)completion { + if (![self ensureEnabled:completion]) return nil; + NSString *urlString = [self buildURLStringWithPath:path]; + if (!urlString) { [self fail:KBNetworkErrorInvalidURL completion:completion]; return nil; } + // 用 JSON 序列化器生成 JSON Body 的请求 + AFJSONRequestSerializer *serializer = [AFJSONRequestSerializer serializer]; + serializer.timeoutInterval = self.timeout; + NSError *error = nil; + NSMutableURLRequest *req = [serializer requestWithMethod:@"POST" + URLString:urlString + parameters:jsonBody + error:&error]; + if (error) { if (completion) completion(nil, nil, error); return nil; } + [self applyHeaders:headers toMutableRequest:req contentType:nil]; + return [self startAFTaskWithRequest:req completion:completion]; +} + +#pragma mark - Core + +- (BOOL)ensureEnabled:(KBNetworkCompletion)completion { + if (!self.isEnabled) { + NSError *e = [NSError errorWithDomain:KBNetworkErrorDomain code:KBNetworkErrorDisabled userInfo:@{NSLocalizedDescriptionKey: @"网络未启用(可能未开启完全访问)"}]; + if (completion) completion(nil, nil, e); + return NO; + } + return YES; +} + +- (NSString *)buildURLStringWithPath:(NSString *)path { + if (path.length == 0) return nil; + if ([path hasPrefix:@"http://"] || [path hasPrefix:@"https://"]) { + return path; + } + if (self.baseURL) { + return [NSURL URLWithString:path relativeToURL:self.baseURL].absoluteURL.absoluteString; + } + return path; // 当无 baseURL 且 path 不是完整 URL 时,让 AFN 处理(可能失败) +} + +- (void)applyHeaders:(NSDictionary *)headers toMutableRequest:(NSMutableURLRequest *)req contentType:(NSString *)contentType { + // 合并默认头与局部头,并注入授权头(若可用)。局部覆盖优先。 + NSMutableDictionary *all = [self.defaultHeaders mutableCopy] ?: [NSMutableDictionary new]; + NSDictionary *auth = [[KBAuthManager shared] authorizationHeader]; + [auth enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *obj, BOOL *stop) { all[key] = obj; }]; + if (contentType) all[@"Content-Type"] = contentType; + [headers enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *obj, BOOL *stop) { all[key] = obj; }]; + [all enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *obj, BOOL *stop) { [req setValue:obj forHTTPHeaderField:key]; }]; +} + +- (NSURLSessionDataTask *)startAFTaskWithRequest:(NSURLRequest *)req completion:(KBNetworkCompletion)completion { + // 响应先用原始数据返回,再按 Content-Type 解析 JSON(与原实现一致) + self.manager.responseSerializer = [AFHTTPResponseSerializer serializer]; + NSURLSessionDataTask *task = [self.manager dataTaskWithRequest:req uploadProgress:nil downloadProgress:nil completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) { + if (error) { if (completion) completion(nil, response, error); return; } + NSData *data = (NSData *)responseObject; + if (![data isKindOfClass:[NSData class]]) { + if (completion) completion(nil, response, [NSError errorWithDomain:KBNetworkErrorDomain code:KBNetworkErrorInvalidResponse userInfo:@{NSLocalizedDescriptionKey:@"无数据"}]); + return; + } + NSString *ct = nil; + if ([response isKindOfClass:[NSHTTPURLResponse class]]) { + ct = ((NSHTTPURLResponse *)response).allHeaderFields[@"Content-Type"]; + } + BOOL looksJSON = (ct && [ct.lowercaseString containsString:@"application/json"]); + if (looksJSON) { + NSError *jsonErr = nil; + id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonErr]; + if (jsonErr) { if (completion) completion(nil, response, [NSError errorWithDomain:KBNetworkErrorDomain code:KBNetworkErrorDecodeFailed userInfo:@{NSLocalizedDescriptionKey:@"JSON解析失败"}]); return; } + if (completion) completion(json, response, nil); + } else { + if (completion) completion(data, response, nil); + } + }]; + [task resume]; + return task; +} + +#pragma mark - AFHTTPSessionManager + +- (AFHTTPSessionManager *)manager { + if (!_manager) { + NSURLSessionConfiguration *cfg = [NSURLSessionConfiguration ephemeralSessionConfiguration]; + cfg.requestCachePolicy = NSURLRequestReloadIgnoringLocalCacheData; + cfg.timeoutIntervalForRequest = self.timeout; + cfg.timeoutIntervalForResource = MAX(self.timeout, 30.0); + if (@available(iOS 11.0, *)) { cfg.waitsForConnectivity = YES; } + _manager = [[AFHTTPSessionManager alloc] initWithBaseURL:nil sessionConfiguration:cfg]; + // 默认不使用 JSON 解析器,保持原生数据,再按需解析 + _manager.responseSerializer = [AFHTTPResponseSerializer serializer]; + } + return _manager; +} + +#pragma mark - Private helpers + +- (void)fail:(KBNetworkError)code completion:(KBNetworkCompletion)completion { + NSString *msg = @"网络错误"; + switch (code) { + case KBNetworkErrorDisabled: msg = @"网络未启用(可能未开启完全访问)"; break; + case KBNetworkErrorInvalidURL: msg = @"无效的URL"; break; + case KBNetworkErrorInvalidResponse: msg = @"无效的响应"; break; + case KBNetworkErrorDecodeFailed: msg = @"解析失败"; break; + default: break; + } + NSError *e = [NSError errorWithDomain:KBNetworkErrorDomain + code:code + userInfo:@{NSLocalizedDescriptionKey: msg}]; + if (completion) completion(nil, nil, e); +} + +@end diff --git a/CustomKeyboard/PrefixHeader.pch b/CustomKeyboard/PrefixHeader.pch index b761eff..5d96a48 100644 --- a/CustomKeyboard/PrefixHeader.pch +++ b/CustomKeyboard/PrefixHeader.pch @@ -12,10 +12,20 @@ // You will also need to set the Prefix Header build setting of one or more of your targets to reference this file. #define SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width -#define SCREEN_HEIGHT [UIScreen mainScreen].bounds.size.width +#define SCREEN_HEIGHT [UIScreen mainScreen].bounds.size.height #define imageNamed(s) [UIImage imageNamed:s] +// 公共配置 +#import "KBConfig.h" #import "Masonry.h" +#import "KBHUD.h" // 复用 App 内的 HUD 封装 +#import "KBLocalizationManager.h" // 复用多语言封装(可在扩展内使用) + +// 通用链接(Universal Links)统一配置 +// 配置好 AASA 与 Associated Domains 后,只需修改这里即可切换域名/path。 +#define KB_UL_BASE @"https://your.domain/ul" // 替换为你的真实域名与前缀路径 +#define KB_UL_LOGIN KB_UL_BASE @"/login" +#define KB_UL_SETTINGS KB_UL_BASE @"/settings" #endif /* PrefixHeader_pch */ diff --git a/CustomKeyboard/View/KBFullAccessGuideView.h b/CustomKeyboard/View/KBFullAccessGuideView.h new file mode 100644 index 0000000..dc8c8e4 --- /dev/null +++ b/CustomKeyboard/View/KBFullAccessGuideView.h @@ -0,0 +1,19 @@ +// +// KBFullAccessGuideView.h +// CustomKeyboard +// +// A lightweight overlay prompting user to enable "Allow Full Access". +// + +#import + +@interface KBFullAccessGuideView : UIView + +/// Present the guide overlay inside a given parent view (or its window). ++ (void)showInView:(UIView *)parent; + +/// Dismiss if shown. ++ (void)dismissFromView:(UIView *)parent; + +@end + diff --git a/CustomKeyboard/View/KBFullAccessGuideView.m b/CustomKeyboard/View/KBFullAccessGuideView.m new file mode 100644 index 0000000..6b7b49e --- /dev/null +++ b/CustomKeyboard/View/KBFullAccessGuideView.m @@ -0,0 +1,185 @@ +// +// KBFullAccessGuideView.m +// CustomKeyboard +// 没有开启完全访问的提示框 + +#import "KBFullAccessGuideView.h" +#import "Masonry.h" + +@interface KBFullAccessGuideView () +@property (nonatomic, strong) UIControl *backdrop; +@property (nonatomic, strong) UIView *card; +@end + +@implementation KBFullAccessGuideView + ++ (instancetype)build { + KBFullAccessGuideView *v = [[KBFullAccessGuideView alloc] initWithFrame:CGRectZero]; + [v setupUI]; + return v; +} + +- (void)setupUI { + self.backgroundColor = [UIColor clearColor]; + + self.backdrop = [[UIControl alloc] init]; + self.backdrop.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.35]; + // [self.backdrop addTarget:self action:@selector(dismiss) forControlEvents:UIControlEventTouchUpInside]; + [self addSubview:self.backdrop]; + [self.backdrop mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self); + }]; + + self.card = [[UIView alloc] init]; + self.card.backgroundColor = [UIColor whiteColor]; + self.card.layer.cornerRadius = 16; + self.card.layer.masksToBounds = YES; + [self addSubview:self.card]; + [self.card mas_makeConstraints:^(MASConstraintMaker *make) { + make.center.equalTo(self); + make.left.equalTo(self).offset(28); + make.right.equalTo(self).offset(-28); + }]; + + UILabel *title = [UILabel new]; + title.text = @"开启【允许完全访问】,体验完整功能"; + title.font = [UIFont boldSystemFontOfSize:16]; + title.textColor = [UIColor blackColor]; + title.textAlignment = NSTextAlignmentCenter; + [self.card addSubview:title]; + [title mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.card).offset(16); + make.left.right.equalTo(self.card).insets(UIEdgeInsetsMake(0, 16, 0, 16)); + }]; + + // 模拟两行开关(纯展示,不真实控制) + UIView *box = [UIView new]; + box.backgroundColor = [UIColor colorWithWhite:0.98 alpha:1.0]; + box.layer.cornerRadius = 12; + [self.card addSubview:box]; + [box mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(title.mas_bottom).offset(12); + make.left.equalTo(self.card).offset(16); + make.right.equalTo(self.card).offset(-16); + make.height.mas_equalTo(100); + }]; + + UILabel *row1 = [UILabel new]; row1.text = @"恋爱键盘"; row1.textColor = [UIColor blackColor]; + UILabel *row2 = [UILabel new]; row2.text = @"允许完全访问"; row2.textColor = [UIColor blackColor]; + [box addSubview:row1]; [box addSubview:row2]; + [row1 mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(box).offset(16); make.top.equalTo(box).offset(14); }]; + UIView *line = [UIView new]; line.backgroundColor = [UIColor colorWithWhite:0.9 alpha:1.0]; + [box addSubview:line]; + [line mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(box).offset(12); make.right.equalTo(box).offset(-12); make.centerY.equalTo(box); make.height.mas_equalTo(1); }]; + [row2 mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(box).offset(16); make.bottom.equalTo(box).offset(-14); }]; + + // 右侧绿色开关的装饰 + UIView* (^switchView)(void) = ^UIView *{ + UIView *sw = [UIView new]; + sw.backgroundColor = [UIColor colorWithRed:0.12 green:0.75 blue:0.35 alpha:1.0]; + sw.layer.cornerRadius = 15; + UIView *dot = [UIView new]; + dot.backgroundColor = [UIColor whiteColor]; + dot.layer.cornerRadius = 12; + [sw addSubview:dot]; + [dot mas_makeConstraints:^(MASConstraintMaker *make) { make.centerY.equalTo(sw); make.right.equalTo(sw).offset(-3); make.width.height.mas_equalTo(24); }]; + [sw mas_makeConstraints:^(MASConstraintMaker *make) { make.width.mas_equalTo(52); make.height.mas_equalTo(30); }]; + return sw; + }; + UIView *sw1 = switchView(); UIView *sw2 = switchView(); + [box addSubview:sw1]; [box addSubview:sw2]; + [sw1 mas_makeConstraints:^(MASConstraintMaker *make) { make.right.equalTo(box).offset(-12); make.centerY.equalTo(row1); }]; + [sw2 mas_makeConstraints:^(MASConstraintMaker *make) { make.right.equalTo(box).offset(-12); make.centerY.equalTo(row2); }]; + + UIButton *go = [UIButton buttonWithType:UIButtonTypeSystem]; + go.backgroundColor = [UIColor blackColor]; + [go setTitle:@"去开启" forState:UIControlStateNormal]; + [go setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + go.titleLabel.font = [UIFont boldSystemFontOfSize:18]; + go.layer.cornerRadius = 12; + [go addTarget:self action:@selector(onTapGoEnable) forControlEvents:UIControlEventTouchUpInside]; + [self.card addSubview:go]; + [go mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(box.mas_bottom).offset(16); + make.left.equalTo(self.card).offset(16); + make.right.equalTo(self.card).offset(-16); + make.height.mas_equalTo(48); + make.bottom.equalTo(self.card).offset(-16); + }]; +} + +- (void)presentIn:(UIView *)parent { + UIView *container = parent.window ?: parent; + self.frame = container.bounds; + self.alpha = 0; + [container addSubview:self]; + [self mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.equalTo(container); }]; + [UIView animateWithDuration:0.2 animations:^{ self.alpha = 1; }]; +} + +- (void)dismiss { + [UIView animateWithDuration:0.18 animations:^{ self.alpha = 0; } completion:^(BOOL finished) { + [self removeFromSuperview]; + }]; +} + ++ (void)showInView:(UIView *)parent { + if (!parent) return; + // 避免重复 + for (UIView *v in (parent.window ?: parent).subviews) { + if ([v isKindOfClass:[KBFullAccessGuideView class]]) return; + } + [[KBFullAccessGuideView build] presentIn:parent]; +} + ++ (void)dismissFromView:(UIView *)parent { + UIView *container = parent.window ?: parent; + for (UIView *v in container.subviews) { + if ([v isKindOfClass:[KBFullAccessGuideView class]]) { + [(KBFullAccessGuideView *)v dismiss]; + break; + } + } +} + + + +#pragma mark - Actions + +- (UIInputViewController *)kb_findInputController { + UIResponder *res = self; + while (res) { + if ([res isKindOfClass:[UIInputViewController class]]) { + return (UIInputViewController *)res; + } + res = res.nextResponder; + } + return nil; +} + +- (void)onTapGoEnable { + // 在扩展中无法使用 UIApplication。改为委托宿主打开链接: + // 方案:优先拉起主 App 并由主 App 打开设置页,避免宿主拦截。 + UIInputViewController *ivc = [self kb_findInputController]; + if (!ivc) { [self dismiss]; return; } + + // 先尝试 Universal Link(如未配置可改为你的域名),失败再用自定义 scheme。 + 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]; + }]; + }; + + if (ul) { + [ivc.extensionContext openURL:ul completionHandler:^(BOOL ok) { + if (ok) { [self dismiss]; } + else { fallback(); } + }]; + } else { + fallback(); + } +} +@end diff --git a/CustomKeyboard/View/KBFunctionBarView.h b/CustomKeyboard/View/KBFunctionBarView.h new file mode 100644 index 0000000..e422613 --- /dev/null +++ b/CustomKeyboard/View/KBFunctionBarView.h @@ -0,0 +1,39 @@ +// +// KBFunctionBarView.h +// CustomKeyboard +// +// Created by Mac on 2025/10/28. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// 功能区顶部的Bar:左侧4个按钮,右侧3个按钮 +@class KBFunctionBarView; + +@protocol KBFunctionBarViewDelegate +@optional +/// 左侧 4 个按钮点击(index: 0~3) +- (void)functionBarView:(KBFunctionBarView *)bar didTapLeftAtIndex:(NSInteger)index; +/// 右侧 3 个按钮点击(index: 0~2) +- (void)functionBarView:(KBFunctionBarView *)bar didTapRightAtIndex:(NSInteger)index; +@end + +@interface KBFunctionBarView : UIView + +@property (nonatomic, weak, nullable) id delegate; + +/// 左侧4个按钮(懒加载创建,等宽水平排布) +@property (nonatomic, strong, readonly) NSArray *leftButtons; + +/// 右侧3个按钮(懒加载创建,等宽水平排布,靠右) +@property (nonatomic, strong, readonly) NSArray *rightButtons; + +/// 配置按钮标题(可选) +@property (nonatomic, copy) NSArray *leftTitles; // 默认 @[@"帮回", @"会说", @"话术", @"更多"] +@property (nonatomic, copy) NSArray *rightTitles; // 默认 @[@"❤", @"收藏", @"宫格"] + +@end + +NS_ASSUME_NONNULL_END diff --git a/CustomKeyboard/View/KBFunctionBarView.m b/CustomKeyboard/View/KBFunctionBarView.m new file mode 100644 index 0000000..cc8aca9 --- /dev/null +++ b/CustomKeyboard/View/KBFunctionBarView.m @@ -0,0 +1,161 @@ +// +// KBFunctionBarView.m +// CustomKeyboard +// +// Created by Mac on 2025/10/28. +// 功能 - barview + +#import "KBFunctionBarView.h" +#import "Masonry.h" + +@interface KBFunctionBarView () +@property (nonatomic, strong) UIView *leftContainer; // 左侧按钮容器 +@property (nonatomic, strong) UIView *rightContainer; // 右侧按钮容器 +@property (nonatomic, strong) NSArray *leftButtonsInternal; +@property (nonatomic, strong) NSArray *rightButtonsInternal; +@end + +@implementation KBFunctionBarView + +- (instancetype)initWithFrame:(CGRect)frame{ + if (self = [super initWithFrame:frame]) { + self.backgroundColor = [UIColor clearColor]; + _leftTitles = @[@"ABC"]; + _rightTitles = @[@"Upgrade VIP"]; + [self buildUI]; + } + return self; +} + +#pragma mark - Public + +- (NSArray *)leftButtons { return self.leftButtonsInternal; } +- (NSArray *)rightButtons { return self.rightButtonsInternal; } + + +#pragma mark - UI + +- (void)buildUI { + // 左右两个容器,方便分别布局 + [self addSubview:self.leftContainer]; + [self addSubview:self.rightContainer]; + + [self.rightContainer mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.equalTo(self.mas_right).offset(-12); + make.centerY.equalTo(self.mas_centerY); + make.height.mas_equalTo(36); + }]; + + [self.leftContainer mas_makeConstraints:^(MASConstraintMaker *make) { + 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); + }]; + + // 左侧4个等宽按钮 + NSMutableArray *leftBtns = [NSMutableArray arrayWithCapacity:4]; + UIView *prev = nil; + for (NSInteger i = 0; i < self.leftTitles.count; i++) { + UIButton *btn = [self buildButtonWithTitle:(i < self.leftTitles.count ? self.leftTitles[i] : [NSString stringWithFormat:@"L%ld", (long)i])]; + btn.tag = 100 + i; + [btn addTarget:self action:@selector(onLeftTap:) forControlEvents:UIControlEventTouchUpInside]; + [self.leftContainer addSubview:btn]; + [btn mas_makeConstraints:^(MASConstraintMaker *make) { + if (prev) { + make.left.equalTo(prev.mas_right).offset(8); + make.width.equalTo(prev); + } else { + make.left.equalTo(self.leftContainer.mas_left); + } + make.top.bottom.equalTo(self.leftContainer); + }]; + prev = btn; + [leftBtns addObject:btn]; + } + [prev mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.equalTo(self.leftContainer.mas_right); + }]; + self.leftButtonsInternal = leftBtns.copy; + + // 右侧N个按钮(靠右、两两等宽) + NSMutableArray *rightBtns = [NSMutableArray arrayWithCapacity:3]; + for (NSInteger i = 0; i < self.rightTitles.count; i++) { + UIButton *btn = [self buildButtonWithTitle:(i < self.rightTitles.count ? self.rightTitles[i] : [NSString stringWithFormat:@"R%ld", (long)i])]; + btn.tag = 200 + i; + [self.rightContainer addSubview:btn]; + [btn addTarget:self action:@selector(onRightTap:) forControlEvents:UIControlEventTouchUpInside]; + [rightBtns addObject:btn]; + } + + // 从右往左链式布局,保证整体靠右;支持 1/2/3... 任意数量 + UIView *prevRight = nil; // 指向右侧已布局的按钮 + for (NSInteger i = rightBtns.count - 1; i >= 0; i--) { + UIButton *btn = rightBtns[i]; + [btn mas_makeConstraints:^(MASConstraintMaker *make) { + if (!prevRight) { + // 最右侧按钮贴右 + make.right.equalTo(self.rightContainer.mas_right); + } else { + // 其余按钮紧挨左侧兄弟,且与其等宽 + make.right.equalTo(prevRight.mas_left).offset(-8); + make.width.equalTo(prevRight); + } + make.top.bottom.equalTo(self.rightContainer); + }]; + prevRight = btn; + } + // 最左侧一个不超出容器左边(允许根据内容自然宽度收缩) + if (prevRight) { + [prevRight mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.greaterThanOrEqualTo(self.rightContainer.mas_left); + }]; + } + + self.rightButtonsInternal = rightBtns.copy; +} + +#pragma mark - Actions + +- (void)onLeftTap:(UIButton *)sender { + NSInteger idx = sender.tag - 100; + if ([self.delegate respondsToSelector:@selector(functionBarView:didTapLeftAtIndex:)]) { + [self.delegate functionBarView:self didTapLeftAtIndex:idx]; + } +} + +- (void)onRightTap:(UIButton *)sender { + NSInteger idx = sender.tag - 200; + if ([self.delegate respondsToSelector:@selector(functionBarView:didTapRightAtIndex:)]) { + [self.delegate functionBarView:self didTapRightAtIndex:idx]; + } +} + +- (UIButton *)buildButtonWithTitle:(NSString *)title { + UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem]; + btn.layer.cornerRadius = 18; + btn.layer.masksToBounds = YES; + btn.backgroundColor = [UIColor colorWithWhite:1 alpha:0.9]; + btn.titleLabel.font = [UIFont systemFontOfSize:14 weight:UIFontWeightMedium]; + [btn setTitle:title forState:UIControlStateNormal]; + [btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; + return btn; +} + +#pragma mark - Lazy + +- (UIView *)leftContainer { + if (!_leftContainer) { + _leftContainer = [[UIView alloc] init]; + } + return _leftContainer; +} + +- (UIView *)rightContainer { + if (!_rightContainer) { + _rightContainer = [[UIView alloc] init]; + } + return _rightContainer; +} + +@end diff --git a/CustomKeyboard/View/KBFunctionPasteView.h b/CustomKeyboard/View/KBFunctionPasteView.h new file mode 100644 index 0000000..c4c5d2b --- /dev/null +++ b/CustomKeyboard/View/KBFunctionPasteView.h @@ -0,0 +1,23 @@ +// +// KBFunctionPasteView.h +// CustomKeyboard +// +// Created by Mac on 2025/10/28. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// 粘贴提示输入框区域(左侧图标+占位文案,圆角白底) +@interface KBFunctionPasteView : UIView + +/// 左侧图标 +@property (nonatomic, strong, readonly) UIImageView *iconView; + +/// 提示文案,例如:点击粘贴TA的话 +@property (nonatomic, strong, readonly) UILabel *placeholderLabel; + +@end + +NS_ASSUME_NONNULL_END diff --git a/CustomKeyboard/View/KBFunctionPasteView.m b/CustomKeyboard/View/KBFunctionPasteView.m new file mode 100644 index 0000000..61caa7b --- /dev/null +++ b/CustomKeyboard/View/KBFunctionPasteView.m @@ -0,0 +1,75 @@ +// +// KBFunctionPasteView.m +// CustomKeyboard +// +// Created by Mac on 2025/10/28. +// 粘贴View + +#import "KBFunctionPasteView.h" +#import "Masonry.h" + +@interface KBFunctionPasteView () +@property (nonatomic, strong) UIImageView *iconViewInternal; +@property (nonatomic, strong) UILabel *placeholderLabelInternal; +@end + +@implementation KBFunctionPasteView + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + // 白底圆角容器 + self.backgroundColor = [UIColor colorWithWhite:1 alpha:0.95]; + self.layer.cornerRadius = 12.0; + self.layer.masksToBounds = YES; + + [self addSubview:self.iconViewInternal]; + [self addSubview:self.placeholderLabelInternal]; + + [self.iconViewInternal mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.mas_left).offset(12); + make.centerY.equalTo(self.mas_centerY); + make.width.height.mas_equalTo(20); + }]; + [self.placeholderLabelInternal mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.iconViewInternal.mas_right).offset(8); + make.right.equalTo(self.mas_right).offset(-12); + make.centerY.equalTo(self.mas_centerY); + }]; + } + return self; +} + +#pragma mark - Lazy + +- (UIImageView *)iconViewInternal { + if (!_iconViewInternal) { + _iconViewInternal = [[UIImageView alloc] init]; + // 用简单的系统表情代替资源图(项目可替换成实际图片) + UILabel *emoji = [[UILabel alloc] init]; + emoji.text = @"📋"; // 粘贴/剪贴板含义 + emoji.font = [UIFont systemFontOfSize:18]; + emoji.textAlignment = NSTextAlignmentCenter; + [_iconViewInternal addSubview:emoji]; + [emoji mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(_iconViewInternal); + }]; + } + return _iconViewInternal; +} + +- (UILabel *)placeholderLabelInternal { + if (!_placeholderLabelInternal) { + _placeholderLabelInternal = [[UILabel alloc] init]; + _placeholderLabelInternal.text = @"点击粘贴TA的话"; + _placeholderLabelInternal.textColor = [UIColor colorWithRed:0.20 green:0.64 blue:0.54 alpha:1.0]; + _placeholderLabelInternal.font = [UIFont systemFontOfSize:16 weight:UIFontWeightMedium]; + } + return _placeholderLabelInternal; +} + +#pragma mark - Expose + +- (UIImageView *)iconView { return self.iconViewInternal; } +- (UILabel *)placeholderLabel { return self.placeholderLabelInternal; } + +@end diff --git a/CustomKeyboard/View/KBFunctionTagCell.h b/CustomKeyboard/View/KBFunctionTagCell.h new file mode 100644 index 0000000..e4c00f7 --- /dev/null +++ b/CustomKeyboard/View/KBFunctionTagCell.h @@ -0,0 +1,23 @@ +// +// KBFunctionTagCell.h +// CustomKeyboard +// +// Created by Codex on 2025/10/28. +// 话术标签Cell:左图标+右标题,圆角灰白底 + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface KBFunctionTagCell : UICollectionViewCell + +/// 标题 +@property (nonatomic, strong, readonly) UILabel *titleLabel; + +/// 头像/图标 +@property (nonatomic, strong, readonly) UIImageView *iconView; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/CustomKeyboard/View/KBFunctionTagCell.m b/CustomKeyboard/View/KBFunctionTagCell.m new file mode 100644 index 0000000..06df6b3 --- /dev/null +++ b/CustomKeyboard/View/KBFunctionTagCell.m @@ -0,0 +1,73 @@ +// +// KBFunctionTagCell.m +// CustomKeyboard +// +// Created by Codex on 2025/10/28. +// + +#import "KBFunctionTagCell.h" +#import "Masonry.h" + +@interface KBFunctionTagCell () +@property (nonatomic, strong) UILabel *titleLabelInternal; +@property (nonatomic, strong) UIImageView *iconViewInternal; +@end + +@implementation KBFunctionTagCell + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + self.contentView.backgroundColor = [UIColor colorWithWhite:1 alpha:0.9]; + self.contentView.layer.cornerRadius = 12; + self.contentView.layer.masksToBounds = YES; + + [self.contentView addSubview:self.iconViewInternal]; + [self.contentView addSubview:self.titleLabelInternal]; + + [self.iconViewInternal mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.contentView.mas_left).offset(10); + make.centerY.equalTo(self.contentView.mas_centerY); + make.width.height.mas_equalTo(24); + }]; + [self.titleLabelInternal mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.iconViewInternal.mas_right).offset(6); + make.right.equalTo(self.contentView.mas_right).offset(-10); + make.centerY.equalTo(self.contentView.mas_centerY); + }]; + } + return self; +} + +#pragma mark - Lazy + +- (UIImageView *)iconViewInternal { + if (!_iconViewInternal) { + _iconViewInternal = [[UIImageView alloc] init]; + UILabel *emoji = [[UILabel alloc] init]; + emoji.text = @"🙂"; // 占位图标 + emoji.textAlignment = NSTextAlignmentCenter; + emoji.font = [UIFont systemFontOfSize:20]; + [_iconViewInternal addSubview:emoji]; + [emoji mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(_iconViewInternal); + }]; + } + return _iconViewInternal; +} + +- (UILabel *)titleLabelInternal { + if (!_titleLabelInternal) { + _titleLabelInternal = [[UILabel alloc] init]; + _titleLabelInternal.font = [UIFont systemFontOfSize:15 weight:UIFontWeightSemibold]; + _titleLabelInternal.textColor = [UIColor blackColor]; + } + return _titleLabelInternal; +} + +#pragma mark - Expose + +- (UILabel *)titleLabel { return self.titleLabelInternal; } +- (UIImageView *)iconView { return self.iconViewInternal; } + +@end + diff --git a/CustomKeyboard/View/KBFunctionView.h b/CustomKeyboard/View/KBFunctionView.h new file mode 100644 index 0000000..ebe7247 --- /dev/null +++ b/CustomKeyboard/View/KBFunctionView.h @@ -0,0 +1,38 @@ +// +// KBFunctionView.h +// CustomKeyboard +// +// Created by Mac on 2025/10/28. +// + +#import +@class KBFunctionBarView, KBFunctionPasteView,KBFunctionView; + +@protocol KBFunctionViewDelegate +@optional +- (void)functionView:(KBFunctionView *_Nullable)functionView didTapToolActionAtIndex:(NSInteger)index; +@end + +NS_ASSUME_NONNULL_BEGIN + +/// 整个功能面板视图:顶部Bar + 粘贴区 + 标签列表 + 右侧操作按钮 +@interface KBFunctionView : UIView + +@property (nonatomic, weak) id delegate; + + +@property (nonatomic, strong, readonly) UICollectionView *collectionView; // 话术分类/标签列表 +@property (nonatomic, strong, readonly) NSArray *items; // 简单数据源(演示用) + +// 子视图暴露,便于外部接入事件 +@property (nonatomic, strong, readonly) KBFunctionBarView *barView; +@property (nonatomic, strong, readonly) KBFunctionPasteView *pasteView; + +@property (nonatomic, strong, readonly) UIButton *pasteButton; // 右侧-粘贴 +@property (nonatomic, strong, readonly) UIButton *deleteButton; // 右侧-删除 +@property (nonatomic, strong, readonly) UIButton *clearButton; // 右侧-清空 +@property (nonatomic, strong, readonly) UIButton *sendButton; // 右侧-发送 + +@end + +NS_ASSUME_NONNULL_END diff --git a/CustomKeyboard/View/KBFunctionView.m b/CustomKeyboard/View/KBFunctionView.m new file mode 100644 index 0000000..08c11f1 --- /dev/null +++ b/CustomKeyboard/View/KBFunctionView.m @@ -0,0 +1,432 @@ +// +// KBFunctionView.m +// CustomKeyboard +// +// Created by Mac on 2025/10/28. +// + +#import "KBFunctionView.h" +#import "KBFunctionBarView.h" +#import "KBFunctionPasteView.h" +#import "KBFunctionTagCell.h" +#import "Masonry.h" +#import +#import "KBFullAccessGuideView.h" +#import "KBFullAccessManager.h" + +static NSString * const kKBFunctionTagCellId = @"KBFunctionTagCellId"; + +@interface KBFunctionView () +// UI +@property (nonatomic, strong) KBFunctionBarView *barViewInternal; +@property (nonatomic, strong) KBFunctionPasteView *pasteViewInternal; +@property (nonatomic, strong) UICollectionView *collectionViewInternal; +@property (nonatomic, strong) UIView *rightButtonContainer; // 右侧竖排按钮容器 +@property (nonatomic, strong) UIButton *pasteButtonInternal; +@property (nonatomic, strong) UIButton *deleteButtonInternal; +@property (nonatomic, strong) UIButton *clearButtonInternal; +@property (nonatomic, strong) UIButton *sendButtonInternal; + +// Data +@property (nonatomic, strong) NSArray *itemsInternal; + +// 剪贴板自动检测 +@property (nonatomic, strong) NSTimer *pasteboardTimer; // 轮询定时器(轻量、主线程) +@property (nonatomic, assign) NSInteger lastHandledPBCount; // 上次处理过的 changeCount,避免重复弹窗 +@end + +@implementation KBFunctionView + +- (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 setupUI]; + [self reloadDemoData]; + + // 初始化剪贴板监控状态 + _lastHandledPBCount = [UIPasteboard generalPasteboard].changeCount; + } + return self; +} + +- (void)dealloc { + [self stopPasteboardMonitor]; +} + +#pragma mark - UI + +- (void)setupUI { + // 1. 顶部 Bar + [self addSubview:self.barViewInternal]; + [self.barViewInternal mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.equalTo(self); + make.top.equalTo(self.mas_top).offset(6); + make.height.mas_equalTo(48); + }]; + + // 右侧竖排按钮容器 + [self addSubview:self.rightButtonContainer]; + [self.rightButtonContainer mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.equalTo(self.mas_right).offset(-12); + make.top.equalTo(self.barViewInternal.mas_bottom).offset(8); + make.bottom.equalTo(self.mas_bottom).offset(-10); + make.width.mas_equalTo(72); + }]; + + // 右侧四个按钮 + [self.rightButtonContainer addSubview:self.pasteButtonInternal]; + [self.rightButtonContainer addSubview:self.deleteButtonInternal]; + [self.rightButtonContainer addSubview:self.clearButtonInternal]; + [self.rightButtonContainer addSubview:self.sendButtonInternal]; + + // 竖向排布:粘贴、删除、清空为等高,发送略高 + CGFloat smallH = 44; + CGFloat bigH = 56; + CGFloat vSpace = 10; + [self.pasteButtonInternal mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.rightButtonContainer.mas_top); + make.left.right.equalTo(self.rightButtonContainer); + make.height.mas_equalTo(smallH); + }]; + [self.deleteButtonInternal mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.pasteButtonInternal.mas_bottom).offset(vSpace); + make.left.right.equalTo(self.rightButtonContainer); + make.height.equalTo(self.pasteButtonInternal); + }]; + [self.clearButtonInternal mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.deleteButtonInternal.mas_bottom).offset(vSpace); + make.left.right.equalTo(self.rightButtonContainer); + make.height.equalTo(self.pasteButtonInternal); + }]; + [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); // 底部可伸缩 + }]; + + // 2. 粘贴区(位于右侧按钮左侧) + [self addSubview:self.pasteViewInternal]; + [self.pasteViewInternal mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.mas_left).offset(12); + make.right.equalTo(self.rightButtonContainer.mas_left).offset(-12); + make.top.equalTo(self.barViewInternal.mas_bottom).offset(8); + make.height.mas_equalTo(48); + }]; + + // 3. CollectionView + [self addSubview:self.collectionViewInternal]; + [self.collectionViewInternal mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.mas_left).offset(12); + make.right.equalTo(self.rightButtonContainer.mas_left).offset(-12); + make.top.equalTo(self.pasteViewInternal.mas_bottom).offset(10); + make.bottom.equalTo(self.mas_bottom).offset(-10); + }]; +} + +#pragma mark - Data + +- (void)reloadDemoData { + // 演示数据(可由外部替换) + self.itemsInternal = @[@"高情商", @"暖味拉扯", @"风趣幽默", @"撩女生", @"社交惬匿", @"情场高手", @"一枚暖男", @"聊天搭子", @"表达爱意", @"更多话术"]; + [self.collectionViewInternal reloadData]; +} + +#pragma mark - UICollectionView + +- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { + return self.itemsInternal.count; +} + +- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { + KBFunctionTagCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kKBFunctionTagCellId forIndexPath:indexPath]; + cell.titleLabel.text = self.itemsInternal[indexPath.item]; + return cell; +} + +- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { + // 三列等宽 + CGFloat totalW = collectionView.bounds.size.width; + CGFloat space = 10.0; + NSInteger columns = 3; + CGFloat width = floor((totalW - space * (columns - 1)) / columns); + return CGSizeMake(width, 48); +} + +- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section { + return 10.0; +} + +- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section { + return 12.0; +} + +// 用户点击功能标签:优先 UL 拉起主App,失败再 Scheme;两次都失败则提示开启完全访问 +- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { + + [KBHUD showInfo:@"处理中…"]; +// return; + + UIInputViewController *ivc = [self findInputViewController]; + if (!ivc) return; + + NSString *title = (indexPath.item < self.itemsInternal.count) ? self.itemsInternal[indexPath.item] : @""; + NSString *encodedTitle = [title stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]] ?: @""; + + NSURL *ul = [NSURL URLWithString:[NSString stringWithFormat:@"%@?src=functionView&index=%ld&title=%@", KB_UL_LOGIN, (long)indexPath.item, encodedTitle]]; + if (!ul) return; + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.05 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [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]]; + [ivc.extensionContext openURL:scheme completionHandler:^(BOOL ok2) { + if (!ok2) { + // 两条路都失败:大概率未开完全访问或宿主拦截。统一交由 Manager 引导。 + dispatch_async(dispatch_get_main_queue(), ^{ [[KBFullAccessManager shared] ensureFullAccessOrGuideInView:self]; }); + } + }]; + }]; + }); +} + + +#pragma mark - Button Actions + +- (void)onTapPaste { + // 用户点击“粘贴”时才读取剪贴板: + // - iOS16+ 会在跨 App 首次读取时自动弹出系统权限弹窗; + // - iOS15 及以下不会弹窗,直接返回内容; + // 注意:不要在非用户触发的时机主动读取(如 viewDidLoad),否则会造成“立刻弹窗”的体验。 + UIPasteboard *pb = [UIPasteboard generalPasteboard]; + NSString *text = pb.string; // 读取纯文本(可能触发系统粘贴权限弹窗) + + if (text.length > 0) { + // 将粘贴内容展示到左侧“粘贴区”的占位文案上 + self.pasteView.placeholderLabel.text = text; + // 如果需要多行展示,可按需放开(高度由外部约束决定,默认一行会截断) + // self.pasteView.placeholderLabel.numberOfLines = 0; + } else { + // 无可用文本或用户拒绝了粘贴权限;保持占位文案不变 + NSLog(@"粘贴板无可用文本或未授权粘贴"); + } +} + +#pragma mark - 自动监控剪贴板(复制即弹窗) +// 说明: +// - 仅在视图可见时开启轮询,避免不必要的读取与打扰; +// - 当检测到 changeCount 变化,立即读 pasteboard.string: +// * iOS16+:此处会触发系统“是否允许粘贴”弹窗; +// * iOS15:不会弹窗,直接得到文本; +// - 无论允许/拒绝,都把本次 changeCount 记为已处理,避免一直重复询问。 + +- (void)startPasteboardMonitor { + if (self.pasteboardTimer) return; + __weak typeof(self) weakSelf = self; + self.pasteboardTimer = [NSTimer scheduledTimerWithTimeInterval:0.5 repeats:YES block:^(NSTimer * _Nonnull timer) { + __strong typeof(weakSelf) self = weakSelf; if (!self) return; + UIPasteboard *pb = [UIPasteboard generalPasteboard]; + NSInteger cc = pb.changeCount; + if (cc <= self.lastHandledPBCount) return; // 没有新复制 + self.lastHandledPBCount = cc; // 标记已处理,避免重复 + + // 实际读取触发系统弹窗(iOS16+) + NSString *text = pb.string; + if (text.length > 0) { + self.pasteView.placeholderLabel.text = text; + } + }]; +} + +- (void)stopPasteboardMonitor { + [self.pasteboardTimer invalidate]; + self.pasteboardTimer = nil; +} + +- (void)didMoveToWindow { + [super didMoveToWindow]; + if (self.window && !self.isHidden) { + [self startPasteboardMonitor]; + } else { + [self stopPasteboardMonitor]; + } +} + +- (void)setHidden:(BOOL)hidden { + BOOL wasHidden = self.isHidden; + [super setHidden:hidden]; + if (wasHidden != hidden) { + if (!hidden && self.window) { + [self startPasteboardMonitor]; + } else { + [self stopPasteboardMonitor]; + } + } +} +- (void)onTapDelete { + NSLog(@"点击:删除"); + UIInputViewController *ivc = [self findInputViewController]; + id proxy = ivc.textDocumentProxy; + [proxy deleteBackward]; +} +- (void)onTapClear { + NSLog(@"点击:清空"); + // 连续删除:仅清空光标之前的输入(不改动 pasteView 的内容) + UIInputViewController *ivc = [self findInputViewController]; + id proxy = ivc.textDocumentProxy; + // 逐批读取 documentContextBeforeInput 并删除,避免 50 字符窗口限制带来的残留 + NSInteger guard = 0; // 上限保护,避免极端情况下长时间阻塞 + while (guard < 10000) { + NSString *before = proxy.documentContextBeforeInput ?: @""; + NSInteger count = before.length; + if (count <= 0) { break; } // 光标前已无内容 + for (NSInteger i = 0; i < count; i++) { + [proxy deleteBackward]; + } + guard += count; + } +} +- (void)onTapSend { + NSLog(@"点击:发送"); + // 发送:插入换行。大多数聊天类 App 会把回车视为“发送” + UIInputViewController *ivc = [self findInputViewController]; + id proxy = ivc.textDocumentProxy; + [proxy insertText:@"\n"]; +} + +#pragma mark - Lazy + +- (KBFunctionBarView *)barViewInternal { + if (!_barViewInternal) { + _barViewInternal = [[KBFunctionBarView alloc] init]; + _barViewInternal.delegate = self; // 顶部功能Bar事件下发到本View + } + return _barViewInternal; +} + +#pragma mark - KBFunctionBarViewDelegate + +- (void)functionBarView:(KBFunctionBarView *)bar didTapLeftAtIndex:(NSInteger)index { + // 将事件继续透传给上层(如键盘控制器),用于切换界面或其它业务 + if ([self.delegate respondsToSelector:@selector(functionView:didTapToolActionAtIndex:)]) { + [self.delegate functionView:self didTapToolActionAtIndex:index]; + } +} + +- (void)functionBarView:(KBFunctionBarView *)bar didTapRightAtIndex:(NSInteger)index { + // 右侧按钮点击,如收藏/宫格等,按需继续向外抛出(这里暂不定义单独协议方法,可在此内部处理或扩展) +} + +- (KBFunctionPasteView *)pasteViewInternal { + if (!_pasteViewInternal) { + _pasteViewInternal = [[KBFunctionPasteView alloc] init]; + } + return _pasteViewInternal; +} + +- (UICollectionView *)collectionViewInternal { + if (!_collectionViewInternal) { + UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; + layout.sectionInset = UIEdgeInsetsZero; // 外边距交由约束控制 + _collectionViewInternal = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; + _collectionViewInternal.backgroundColor = [UIColor clearColor]; + _collectionViewInternal.dataSource = self; + _collectionViewInternal.delegate = self; + [_collectionViewInternal registerClass:[KBFunctionTagCell class] forCellWithReuseIdentifier:kKBFunctionTagCellId]; + } + return _collectionViewInternal; +} + +- (UIView *)rightButtonContainer { + if (!_rightButtonContainer) { + _rightButtonContainer = [[UIView alloc] init]; + _rightButtonContainer.backgroundColor = [UIColor clearColor]; + } + return _rightButtonContainer; +} + +- (UIButton *)buildRightButtonWithTitle:(NSString *)title color:(UIColor *)color { + UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem]; + btn.backgroundColor = color; + btn.layer.cornerRadius = 12.0; + btn.layer.masksToBounds = YES; + btn.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold]; + [btn setTitle:title forState:UIControlStateNormal]; + [btn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + return btn; +} + +- (UIButton *)pasteButtonInternal { + if (!_pasteButtonInternal) { + _pasteButtonInternal = [self buildRightButtonWithTitle:@"粘贴" color:[UIColor colorWithRed:0.13 green:0.73 blue:0.60 alpha:1.0]]; + [_pasteButtonInternal addTarget:self action:@selector(onTapPaste) forControlEvents:UIControlEventTouchUpInside]; + } + return _pasteButtonInternal; +} + +- (UIButton *)deleteButtonInternal { + if (!_deleteButtonInternal) { + // 浅灰底深色文字,更接近截图里“删除”样式 + _deleteButtonInternal = [UIButton buttonWithType:UIButtonTypeSystem]; + _deleteButtonInternal.backgroundColor = [UIColor colorWithWhite:0.92 alpha:1.0]; + _deleteButtonInternal.layer.cornerRadius = 12.0; + _deleteButtonInternal.layer.masksToBounds = YES; + _deleteButtonInternal.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold]; + [_deleteButtonInternal setTitle:@"删除" forState:UIControlStateNormal]; + [_deleteButtonInternal setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; + [_deleteButtonInternal addTarget:self action:@selector(onTapDelete) forControlEvents:UIControlEventTouchUpInside]; + } + return _deleteButtonInternal; +} + +- (UIButton *)clearButtonInternal { + if (!_clearButtonInternal) { + _clearButtonInternal = [UIButton buttonWithType:UIButtonTypeSystem]; + _clearButtonInternal.backgroundColor = [UIColor colorWithWhite:0.92 alpha:1.0]; + _clearButtonInternal.layer.cornerRadius = 12.0; + _clearButtonInternal.layer.masksToBounds = YES; + _clearButtonInternal.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold]; + [_clearButtonInternal setTitle:@"清空" forState:UIControlStateNormal]; + [_clearButtonInternal setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; + [_clearButtonInternal addTarget:self action:@selector(onTapClear) forControlEvents:UIControlEventTouchUpInside]; + } + return _clearButtonInternal; +} + +- (UIButton *)sendButtonInternal { + if (!_sendButtonInternal) { + _sendButtonInternal = [self buildRightButtonWithTitle:@"发送" color:[UIColor colorWithRed:0.13 green:0.73 blue:0.60 alpha:1.0]]; + [_sendButtonInternal addTarget:self action:@selector(onTapSend) forControlEvents:UIControlEventTouchUpInside]; + } + return _sendButtonInternal; +} + +#pragma mark - Expose + +- (UICollectionView *)collectionView { return self.collectionViewInternal; } +- (NSArray *)items { return self.itemsInternal; } +- (KBFunctionBarView *)barView { return self.barViewInternal; } +- (KBFunctionPasteView *)pasteView { return self.pasteViewInternal; } +- (UIButton *)pasteButton { return self.pasteButtonInternal; } +- (UIButton *)deleteButton { return self.deleteButtonInternal; } +- (UIButton *)clearButton { return self.clearButtonInternal; } +- (UIButton *)sendButton { return self.sendButtonInternal; } + +#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; +} + +@end diff --git a/CustomKeyboard/View/KBKeyBoardMainView.h b/CustomKeyboard/View/KBKeyBoardMainView.h new file mode 100644 index 0000000..9f50800 --- /dev/null +++ b/CustomKeyboard/View/KBKeyBoardMainView.h @@ -0,0 +1,33 @@ +// +// KBKeyBoardMainView.h +// CustomKeyboard +// +// Created by Mac on 2025/10/28. +// + +#import + + +@class KBKeyBoardMainView, KBKey; + +NS_ASSUME_NONNULL_BEGIN + +@protocol KBKeyBoardMainViewDelegate +@optional +/// 键被点击的回调 +- (void)keyBoardMainView:(KBKeyBoardMainView *)keyBoardMainView didTapKey:(KBKey *)key; + +/// 顶部工具栏按钮点击回调(index: 0~3)。 +/// 需求:当 index == 0 时,由外部(KeyboardViewController)决定是否切换到功能面板 +- (void)keyBoardMainView:(KBKeyBoardMainView *)keyBoardMainView didTapToolActionAtIndex:(NSInteger)index; + +/// 点击了右侧设置按钮 +- (void)keyBoardMainViewDidTapSettings:(KBKeyBoardMainView *)keyBoardMainView; +@end + +@interface KBKeyBoardMainView : UIView +@property (nonatomic, weak) id delegate; + +@end + +NS_ASSUME_NONNULL_END diff --git a/CustomKeyboard/View/KBKeyBoardMainView.m b/CustomKeyboard/View/KBKeyBoardMainView.m new file mode 100644 index 0000000..fb41669 --- /dev/null +++ b/CustomKeyboard/View/KBKeyBoardMainView.m @@ -0,0 +1,118 @@ +// +// KBKeyBoardMainView.m +// CustomKeyboard +// +// Created by Mac on 2025/10/28. +// + +#import "KBKeyBoardMainView.h" +#import "KBToolBar.h" +#import "KBKeyboardView.h" +#import "KBFunctionView.h" +#import "KBKey.h" +#import "Masonry.h" + +@interface KBKeyBoardMainView () +@property (nonatomic, strong) KBToolBar *topBar; +@property (nonatomic, strong) KBKeyboardView *keyboardView; +// 注意:功能面板的展示/隐藏由外部控制器决定,此处不再直接管理显隐 +@end +@implementation KBKeyBoardMainView + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + self.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.0]; + // 顶部栏 + self.topBar = [[KBToolBar alloc] init]; + self.topBar.delegate = self; + [self addSubview:self.topBar]; + [self.topBar mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.equalTo(self); + make.top.equalTo(self.mas_top).offset(6); + make.height.mas_equalTo(40); + }]; + + // 键盘区域 + self.keyboardView = [[KBKeyboardView alloc] init]; + self.keyboardView.delegate = self; + [self addSubview:self.keyboardView]; + [self.keyboardView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.equalTo(self); + make.top.equalTo(self.topBar.mas_bottom).offset(4); + make.bottom.equalTo(self.mas_bottom).offset(-4); + }]; + + // 功能面板切换交由外部控制器处理;此处不直接创建/管理 + + } + return self; +} + + +#pragma mark - KBToolBarDelegate + +- (void)toolBar:(KBToolBar *)toolBar didTapActionAtIndex:(NSInteger)index { + // 将事件抛给外部控制器,由其决定是否切换到功能面板 + if ([self.delegate respondsToSelector:@selector(keyBoardMainView:didTapToolActionAtIndex:)]) { + [self.delegate keyBoardMainView:self didTapToolActionAtIndex:index]; + } +} + +- (void)toolBarDidTapSettings:(KBToolBar *)toolBar { + if ([self.delegate respondsToSelector:@selector(keyBoardMainViewDidTapSettings:)]) { + [self.delegate keyBoardMainViewDidTapSettings:self]; + } +} + +#pragma mark - KBKeyboardViewDelegate + +- (void)keyboardView:(KBKeyboardView *)keyboard didTapKey:(KBKey *)key { + switch (key.type) { + case KBKeyTypeCharacter: + // 文本插入交由上层控制器处理 + if ([self.delegate respondsToSelector:@selector(keyBoardMainView:didTapKey:)]) { + [self.delegate keyBoardMainView:self didTapKey:key]; + } + break; + case KBKeyTypeBackspace: + if ([self.delegate respondsToSelector:@selector(keyBoardMainView:didTapKey:)]) { + [self.delegate keyBoardMainView:self didTapKey:key]; + } + break; + case KBKeyTypeSpace: + if ([self.delegate respondsToSelector:@selector(keyBoardMainView:didTapKey:)]) { + [self.delegate keyBoardMainView:self didTapKey:key]; + } + break; + case KBKeyTypeReturn: + if ([self.delegate respondsToSelector:@selector(keyBoardMainView:didTapKey:)]) { + [self.delegate keyBoardMainView:self didTapKey:key]; + } + break; + case KBKeyTypeModeChange: { + // 切换 字母 <-> 数字 布局 + keyboard.layoutStyle = (keyboard.layoutStyle == KBKeyboardLayoutStyleLetters) ? KBKeyboardLayoutStyleNumbers : KBKeyboardLayoutStyleLetters; + [keyboard reloadKeys]; + } break; + case KBKeyTypeGlobe: + if ([self.delegate respondsToSelector:@selector(keyBoardMainView:didTapKey:)]) { + [self.delegate keyBoardMainView:self didTapKey:key]; + } + break; + case KBKeyTypeCustom: + // 自定义占位:切换语言或其它操作 + if ([self.delegate respondsToSelector:@selector(keyBoardMainView:didTapKey:)]) { + [self.delegate keyBoardMainView:self didTapKey:key]; + } + break; + case KBKeyTypeShift: + // Shift 已在 KBKeyboardView 内部处理 + break; + } +} + +// 切换功能面板交由外部控制器处理(此处不再实现) + +// 设置页展示改由 KeyboardViewController 统一处理 + +@end diff --git a/CustomKeyboard/View/KBKeyButton.h b/CustomKeyboard/View/KBKeyButton.h new file mode 100644 index 0000000..c9a9b8a --- /dev/null +++ b/CustomKeyboard/View/KBKeyButton.h @@ -0,0 +1,20 @@ +// +// KBKeyButton.h +// CustomKeyboard +// + +#import +@class KBKey; + +/// 自定义键按钮(UIButton 子类):圆角外观,按下高亮效果。 +@interface KBKeyButton : UIButton + +@property (nonatomic, strong) KBKey *key; + +/// 配置基础样式(背景、圆角等)。创建按钮时调用。 +- (void)applyDefaultStyle; + +/// 根据选中/高亮等状态刷新外观 +- (void)refreshStateAppearance; + +@end diff --git a/CustomKeyboard/View/KBKeyButton.m b/CustomKeyboard/View/KBKeyButton.m new file mode 100644 index 0000000..085d3eb --- /dev/null +++ b/CustomKeyboard/View/KBKeyButton.m @@ -0,0 +1,56 @@ +// +// KBKeyButton.m +// CustomKeyboard +// + +#import "KBKeyButton.h" +#import "KBKey.h" + +@implementation KBKeyButton + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + [self applyDefaultStyle]; + } + return self; +} + +- (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.layer.cornerRadius = 6.0; // 圆角 + self.layer.masksToBounds = NO; + self.layer.shadowColor = [UIColor colorWithWhite:0 alpha:0.1].CGColor; // 阴影效果 + self.layer.shadowOpacity = 1.0; + self.layer.shadowOffset = CGSizeMake(0, 1); + self.layer.shadowRadius = 1.5; + [self refreshStateAppearance]; +} + +- (void)setHighlighted:(BOOL)highlighted { + [super setHighlighted:highlighted]; + // 简单按压反馈:选中态不改变透明度,避免和高亮态冲突 + if (self.isSelected) { + self.alpha = 1.0; + } else { + self.alpha = highlighted ? 0.2 : 1.0; + } +} + +- (void)setSelected:(BOOL)selected { + [super setSelected:selected]; + [self refreshStateAppearance]; +} + +- (void)refreshStateAppearance { + // 选中态用于 Shift/CapsLock 等特殊按键的高亮显示 + if (self.isSelected) { + self.backgroundColor = [UIColor colorWithWhite:0.85 alpha:1.0]; + } else { + self.backgroundColor = [UIColor whiteColor]; + } +} + +@end diff --git a/CustomKeyboard/View/KBKeyboardView.h b/CustomKeyboard/View/KBKeyboardView.h new file mode 100644 index 0000000..e3487ac --- /dev/null +++ b/CustomKeyboard/View/KBKeyboardView.h @@ -0,0 +1,33 @@ +// +// KBKeyboardView.h +// CustomKeyboard +// +// 键盘主容器,内部管理按键行布局。 +// + +#import + +@class KBKeyboardView, KBKey; + +typedef NS_ENUM(NSInteger, KBKeyboardLayoutStyle) { + KBKeyboardLayoutStyleLetters = 0, + KBKeyboardLayoutStyleNumbers +}; + +@protocol KBKeyboardViewDelegate +@optional +/// 键被点击的回调 +- (void)keyboardView:(KBKeyboardView *)keyboard didTapKey:(KBKey *)key; +@end + +@interface KBKeyboardView : UIView + +@property (nonatomic, weak) id delegate; +@property (nonatomic, assign) KBKeyboardLayoutStyle layoutStyle; // 布局样式(字母/数字) +@property (nonatomic, assign, getter=isShiftOn) BOOL shiftOn; // 大小写状态 +// 在数字布局中,是否显示“更多符号”(#+=)页 +@property (nonatomic, assign) BOOL symbolsMoreOn; + +- (void)reloadKeys; // 当布局样式/大小写变化时调用 + +@end diff --git a/CustomKeyboard/View/KBKeyboardView.m b/CustomKeyboard/View/KBKeyboardView.m new file mode 100644 index 0000000..3ab30ec --- /dev/null +++ b/CustomKeyboard/View/KBKeyboardView.m @@ -0,0 +1,303 @@ +// +// KBKeyboardView.m +// CustomKeyboard +// + +#import "KBKeyboardView.h" +#import "KBKeyButton.h" +#import "KBKey.h" + +@interface KBKeyboardView () +@property (nonatomic, strong) UIView *row1; +@property (nonatomic, strong) UIView *row2; +@property (nonatomic, strong) UIView *row3; +@property (nonatomic, strong) UIView *row4; +@property (nonatomic, strong) NSArray *> *keysForRows; +@end + +@implementation KBKeyboardView + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + self.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.0]; + _layoutStyle = KBKeyboardLayoutStyleLetters; + // 默认小写:与需求一致,初始不开启 Shift + _shiftOn = NO; + _symbolsMoreOn = NO; // 数字面板默认第一页(123) + [self buildBase]; + [self reloadKeys]; + } + return self; +} + +// 当切换大布局(字母/数字)时,重置数字二级页状态 +- (void)setLayoutStyle:(KBKeyboardLayoutStyle)layoutStyle { + _layoutStyle = layoutStyle; + if (_layoutStyle != KBKeyboardLayoutStyleNumbers) { + _symbolsMoreOn = NO; + } +} + +- (void)buildBase { + [self addSubview:self.row1]; + [self addSubview:self.row2]; + [self addSubview:self.row3]; + [self addSubview:self.row4]; + + CGFloat vSpacing = 8; + [self.row1 mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.mas_top).offset(8); + make.left.right.equalTo(self); + make.height.mas_equalTo(44); + }]; + [self.row2 mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.row1.mas_bottom).offset(vSpacing); + make.left.right.equalTo(self); + make.height.equalTo(self.row1); + }]; + [self.row3 mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.row2.mas_bottom).offset(vSpacing); + make.left.right.equalTo(self); + make.height.equalTo(self.row1); + }]; + [self.row4 mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.row3.mas_bottom).offset(vSpacing); + make.left.right.equalTo(self); + make.height.equalTo(self.row1); + make.bottom.equalTo(self.mas_bottom).offset(-6); + }]; +} + +- (void)reloadKeys { + // 移除旧按钮 + for (UIView *row in @[self.row1, self.row2, self.row3, self.row4]) { + [row.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; + } + + self.keysForRows = [self buildKeysForCurrentLayout]; + [self buildRow:self.row1 withKeys:self.keysForRows[0]]; + // 第二行:字母布局时通过左右等宽占位让整行居中 + CGFloat row2Spacer = (self.layoutStyle == KBKeyboardLayoutStyleLetters) ? 0.5 : 0.0; + [self buildRow:self.row2 withKeys:self.keysForRows[1] edgeSpacerMultiplier:row2Spacer]; + [self buildRow:self.row3 withKeys:self.keysForRows[2]]; + [self buildRow:self.row4 withKeys:self.keysForRows[3]]; +} + +- (NSArray *> *)buildKeysForCurrentLayout { + if (self.layoutStyle == KBKeyboardLayoutStyleNumbers) { + // 数字/符号布局:3 行主键 + 底部控制行 + NSArray *r1 = nil; + NSArray *r2 = nil; + NSArray *r3 = nil; + + if (!self.symbolsMoreOn) { + // 数字第一页(123) + r1 = @[ [KBKey keyWithTitle:@"1" output:@"1"], [KBKey keyWithTitle:@"2" output:@"2"], [KBKey keyWithTitle:@"3" output:@"3"], + [KBKey keyWithTitle:@"4" output:@"4"], [KBKey keyWithTitle:@"5" output:@"5"], [KBKey keyWithTitle:@"6" output:@"6"], + [KBKey keyWithTitle:@"7" output:@"7"], [KBKey keyWithTitle:@"8" output:@"8"], [KBKey keyWithTitle:@"9" output:@"9"], [KBKey keyWithTitle:@"0" output:@"0"] ]; + r2 = @[ [KBKey keyWithTitle:@"-" output:@"-"], [KBKey keyWithTitle:@"/" output:@"/"], [KBKey keyWithTitle:@":" output:@":"], + [KBKey keyWithTitle:@";" output:@";"], [KBKey keyWithTitle:@"(" output:@"("], [KBKey keyWithTitle:@")" output:@")"], + [KBKey keyWithTitle:@"$" output:@"$"], [KBKey keyWithTitle:@"&" output:@"&"], [KBKey keyWithTitle:@"@" output:@"@"], [KBKey keyWithTitle:@"\"" output:@"\""] ]; + r3 = @[ [KBKey keyWithTitle:@"#+=" type:KBKeyTypeSymbolsToggle], + [KBKey keyWithTitle:@"," output:@","], [KBKey keyWithTitle:@"." output:@"."], [KBKey keyWithTitle:@"?" output:@"?"], + [KBKey keyWithTitle:@"!" output:@"!"], [KBKey keyWithTitle:@"'" output:@"'"], + [KBKey keyWithTitle:@"⌫" type:KBKeyTypeBackspace] ]; + } else { + // 数字第二页(#+=):前两行替换为更多符号,左下角按钮文案改为“123” + r1 = @[ [KBKey keyWithTitle:@"[" output:@"["], [KBKey keyWithTitle:@"]" output:@"]"], [KBKey keyWithTitle:@"{" output:@"{"], + [KBKey keyWithTitle:@"}" output:@"}"], [KBKey keyWithTitle:@"#" output:@"#"], [KBKey keyWithTitle:@"%" output:@"%"], + [KBKey keyWithTitle:@"^" output:@"^"], [KBKey keyWithTitle:@"*" output:@"*"], [KBKey keyWithTitle:@"+" output:@"+"], + [KBKey keyWithTitle:@"=" output:@"="] ]; + r2 = @[ [KBKey keyWithTitle:@"_" output:@"_"], [KBKey keyWithTitle:@"\\" output:@"\\"], [KBKey keyWithTitle:@"|" output:@"|"], + [KBKey keyWithTitle:@"~" output:@"~"], [KBKey keyWithTitle:@"<" output:@"<"], [KBKey keyWithTitle:@">" output:@">"], + [KBKey keyWithTitle:@"$" output:@"$"], [KBKey keyWithTitle:@"€" output:@"€"], [KBKey keyWithTitle:@"£" output:@"£"], + [KBKey keyWithTitle:@"•" output:@"•"] ]; + r3 = @[ [KBKey keyWithTitle:@"123" type:KBKeyTypeSymbolsToggle], + [KBKey keyWithTitle:@"," output:@","], [KBKey keyWithTitle:@"." output:@"."], [KBKey keyWithTitle:@"?" output:@"?"], + [KBKey keyWithTitle:@"!" output:@"!"], [KBKey keyWithTitle:@"'" output:@"'"], + [KBKey keyWithTitle:@"⌫" type:KBKeyTypeBackspace] ]; + } + + NSArray *r4 = @[ [KBKey keyWithTitle:@"abc" type:KBKeyTypeModeChange], + [KBKey keyWithTitle:@"AI" type:KBKeyTypeCustom], + [KBKey keyWithTitle:@"space" type:KBKeyTypeSpace], + [KBKey keyWithTitle:@"发送" type:KBKeyTypeReturn] ]; + + return @[r1, r2, r3, r4]; + } + + // 字母布局(QWERTY) + NSArray *r1 = @[ @"Q", @"W", @"E", @"R", @"T", @"Y", @"U", @"I", @"O", @"P" ]; + NSArray *r2 = @[ @"A", @"S", @"D", @"F", @"G", @"H", @"J", @"K", @"L" ]; + NSArray *r3chars = @[ @"Z", @"X", @"C", @"V", @"B", @"N", @"M" ]; + + NSMutableArray *row1 = [NSMutableArray arrayWithCapacity:r1.count]; + // 字母键标题与输出同时随 Shift 切换大小写,界面与输入保持一致 + for (NSString *s in r1) { + NSString *shown = self.shiftOn ? s : s.lowercaseString; + [row1 addObject:[KBKey keyWithTitle:shown output:shown]]; + } + + NSMutableArray *row2 = [NSMutableArray arrayWithCapacity:r2.count]; + for (NSString *s in r2) { + NSString *shown = self.shiftOn ? s : s.lowercaseString; + [row2 addObject:[KBKey keyWithTitle:shown output:shown]]; + } + + NSMutableArray *row3 = [NSMutableArray array]; + [row3 addObject:[KBKey keyWithTitle:@"⇧" type:KBKeyTypeShift]]; + for (NSString *s in r3chars) { + NSString *shown = self.shiftOn ? s : s.lowercaseString; + [row3 addObject:[KBKey keyWithTitle:shown output:shown]]; + } + [row3 addObject:[KBKey keyWithTitle:@"⌫" type:KBKeyTypeBackspace]]; + + NSArray *row4 = @[ [KBKey keyWithTitle:@"123" type:KBKeyTypeModeChange], + [KBKey keyWithTitle:@"AI" type:KBKeyTypeCustom], + [KBKey keyWithTitle:@"space" type:KBKeyTypeSpace], + [KBKey keyWithTitle:@"发送" type:KBKeyTypeReturn] ]; + + return @[row1.copy, row2.copy, row3.copy, row4]; +} + +- (void)buildRow:(UIView *)row withKeys:(NSArray *)keys { + [self buildRow:row withKeys:keys edgeSpacerMultiplier:0.0]; +} + +- (void)buildRow:(UIView *)row withKeys:(NSArray *)keys edgeSpacerMultiplier:(CGFloat)edgeSpacerMultiplier { + CGFloat hInset = 6; // 行左右内边距 + CGFloat spacing = 6; // 键与键之间的间距 + UIView *previous = nil; + UIView *leftSpacer = nil; + UIView *rightSpacer = nil; + if (edgeSpacerMultiplier > 0.0) { + leftSpacer = [UIView new]; + rightSpacer = [UIView new]; + leftSpacer.backgroundColor = [UIColor clearColor]; + rightSpacer.backgroundColor = [UIColor clearColor]; + [row addSubview:leftSpacer]; + [row addSubview:rightSpacer]; + [leftSpacer mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(row.mas_left).offset(hInset); + make.centerY.equalTo(row); + make.height.mas_equalTo(1); + }]; + [rightSpacer mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.equalTo(row.mas_right).offset(-hInset); + make.centerY.equalTo(row); + make.height.mas_equalTo(1); + }]; + } + for (NSInteger i = 0; i < keys.count; i++) { + KBKey *key = keys[i]; + KBKeyButton *btn = [[KBKeyButton alloc] init]; + btn.key = key; + [btn setTitle:key.title forState:UIControlStateNormal]; + [btn addTarget:self action:@selector(onKeyTapped:) forControlEvents:UIControlEventTouchUpInside]; + [row addSubview:btn]; + + // Shift 按钮选中态随大小写状态变化 + if (key.type == KBKeyTypeShift) { + btn.selected = self.shiftOn; + } + + [btn mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.bottom.equalTo(row); + if (previous) { + make.left.equalTo(previous.mas_right).offset(spacing); + } else { + if (leftSpacer) { + make.left.equalTo(leftSpacer.mas_right).offset(spacing); + } else { + make.left.equalTo(row.mas_left).offset(hInset); + } + } + }]; + + // 宽度规则:字符键等宽;特殊键按倍数放大 + if (key.type == KBKeyTypeCharacter) { + if (previous && previous != nil) { + if (((KBKeyButton *)previous).key.type == KBKeyTypeCharacter) { + [btn mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.equalTo(previous); + }]; + } + } + } else { + // special keys: give 1.5x of a character key by deferring constraint equalities after loop + } + + previous = btn; + } + // 右侧使用内边距或右占位 + [previous mas_makeConstraints:^(MASConstraintMaker *make) { + if (rightSpacer) { + make.right.equalTo(rightSpacer.mas_left).offset(-spacing); + } else { + make.right.equalTo(row.mas_right).offset(-hInset); + } + }]; + + // 第二遍:以首个字符键为基准,统一设置特殊键宽度倍数 + KBKeyButton *firstChar = nil; + for (KBKeyButton *b in row.subviews) { + if ([b isKindOfClass:[KBKeyButton class]] && b.key.type == KBKeyTypeCharacter) { firstChar = b; break; } + } + // 若该行没有字符键(例如底部控制行),则使用行内第一个按钮作为基准宽度 + if (!firstChar) { + for (KBKeyButton *b in row.subviews) { if ([b isKindOfClass:[KBKeyButton class]]) { firstChar = b; break; } } + } + if (firstChar) { + for (KBKeyButton *b in row.subviews) { + if (![b isKindOfClass:[KBKeyButton class]]) continue; + if (b.key.type == KBKeyTypeCharacter) continue; + CGFloat multiplier = 1.5; + if (b.key.type == KBKeyTypeSpace) multiplier = 4.0; + if (b.key.type == KBKeyTypeReturn) multiplier = 1.8; + if (b.key.type == KBKeyTypeModeChange || b.key.type == KBKeyTypeGlobe || b.key.type == KBKeyTypeShift || b.key.type == KBKeyTypeBackspace) { + multiplier = 1.5; + } + [b mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.equalTo(firstChar).multipliedBy(multiplier); + }]; + } + // 如果有左右占位,则把占位宽度设置为字符键宽度的一定倍数,以实现整体居中 + if (leftSpacer && rightSpacer) { + [leftSpacer mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.equalTo(firstChar).multipliedBy(edgeSpacerMultiplier); + }]; + [rightSpacer mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.equalTo(firstChar).multipliedBy(edgeSpacerMultiplier); + }]; + } + } +} + +#pragma mark - Actions + +- (void)onKeyTapped:(KBKeyButton *)sender { + KBKey *key = sender.key; + if (key.type == KBKeyTypeShift) { + self.shiftOn = !self.shiftOn; + [self reloadKeys]; + return; + } + if (key.type == KBKeyTypeSymbolsToggle) { + // 在数字布局内切换 123 <-> #+= + self.symbolsMoreOn = !self.symbolsMoreOn; + [self reloadKeys]; + return; + } + if ([self.delegate respondsToSelector:@selector(keyboardView:didTapKey:)]) { + [self.delegate keyboardView:self didTapKey:key]; + } +} + +#pragma mark - Lazy + +- (UIView *)row1 { if (!_row1) _row1 = [UIView new]; return _row1; } +- (UIView *)row2 { if (!_row2) _row2 = [UIView new]; return _row2; } +- (UIView *)row3 { if (!_row3) _row3 = [UIView new]; return _row3; } +- (UIView *)row4 { if (!_row4) _row4 = [UIView new]; return _row4; } + +@end diff --git a/CustomKeyboard/View/KBSettingView.h b/CustomKeyboard/View/KBSettingView.h new file mode 100644 index 0000000..a802f6a --- /dev/null +++ b/CustomKeyboard/View/KBSettingView.h @@ -0,0 +1,20 @@ +// +// KBSettingView.h +// CustomKeyboard +// +// 简单的设置页面:左上角返回箭头按钮 + 占位内容区域。 +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface KBSettingView : UIView + +/// 左上角返回按钮(外部添加 target 实现返回) +@property (nonatomic, strong, readonly) UIButton *backButton; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/CustomKeyboard/View/KBSettingView.m b/CustomKeyboard/View/KBSettingView.m new file mode 100644 index 0000000..f8fa089 --- /dev/null +++ b/CustomKeyboard/View/KBSettingView.m @@ -0,0 +1,71 @@ +// +// KBSettingView.m +// CustomKeyboard +// + +#import "KBSettingView.h" +#import "Masonry.h" + +@interface KBSettingView () +@property (nonatomic, strong) UIButton *backButtonInternal; +@property (nonatomic, strong) UILabel *titleLabel; +@end + +@implementation KBSettingView + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + // 背景做成淡色,和主界面区分 + self.backgroundColor = [UIColor colorWithWhite:1 alpha:0.96]; + + [self addSubview:self.backButtonInternal]; + [self.backButtonInternal mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.mas_left).offset(10); + make.top.equalTo(self.mas_top).offset(8); + make.width.height.mas_equalTo(32); + }]; + + self.titleLabel = [[UILabel alloc] init]; + self.titleLabel.text = @"设置"; + self.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold]; + self.titleLabel.textColor = [UIColor blackColor]; + [self addSubview:self.titleLabel]; + [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.equalTo(self.backButtonInternal.mas_centerY); + make.centerX.equalTo(self.mas_centerX); + }]; + + // 占位内容 + UILabel *place = [[UILabel alloc] init]; + place.text = @"这里是设置内容占位"; + place.textColor = [UIColor darkGrayColor]; + place.font = [UIFont systemFontOfSize:14]; + [self addSubview:place]; + [place mas_makeConstraints:^(MASConstraintMaker *make) { + make.center.equalTo(self); + }]; + } + return self; +} + +#pragma mark - Lazy + +- (UIButton *)backButtonInternal { + if (!_backButtonInternal) { + _backButtonInternal = [UIButton buttonWithType:UIButtonTypeSystem]; + _backButtonInternal.layer.cornerRadius = 16; + _backButtonInternal.layer.masksToBounds = YES; + _backButtonInternal.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.0]; + [_backButtonInternal setTitle:@"←" forState:UIControlStateNormal]; // 返回箭头 + [_backButtonInternal setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; + _backButtonInternal.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold]; + } + return _backButtonInternal; +} + +#pragma mark - Expose + +- (UIButton *)backButton { return self.backButtonInternal; } + +@end + diff --git a/CustomKeyboard/View/KBToolBar.h b/CustomKeyboard/View/KBToolBar.h index e48a19c..8286c46 100644 --- a/CustomKeyboard/View/KBToolBar.h +++ b/CustomKeyboard/View/KBToolBar.h @@ -2,15 +2,35 @@ // KBToolBar.h // CustomKeyboard // -// Created by Mac on 2025/10/27. +// Created by Mac on 2025/10/28. // #import NS_ASSUME_NONNULL_BEGIN +@class KBToolBar; + +@protocol KBToolBarDelegate +@optional +/// 左侧 4 个功能按钮点击(index: 0~3) +- (void)toolBar:(KBToolBar *)toolBar didTapActionAtIndex:(NSInteger)index; +/// 右侧设置按钮点击 +- (void)toolBarDidTapSettings:(KBToolBar *)toolBar; +@end + +/// 顶部工具栏:左侧 4 个按钮,右侧 1 个设置按钮。 @interface KBToolBar : UIView +@property (nonatomic, weak, nullable) id delegate; + +/// 左侧 4 个按钮的标题。默认值:@[@"Item1", @"Item2", @"Item3", @"Item4"]。 +@property (nonatomic, copy) NSArray *leftButtonTitles; + +/// 暴露按钮以便外部定制(只读;首次访问时懒加载创建) +@property (nonatomic, strong, readonly) NSArray *leftButtons; +@property (nonatomic, strong, readonly) UIButton *settingsButton; + @end NS_ASSUME_NONNULL_END diff --git a/CustomKeyboard/View/KBToolBar.m b/CustomKeyboard/View/KBToolBar.m index dbea27a..ab1a602 100644 --- a/CustomKeyboard/View/KBToolBar.m +++ b/CustomKeyboard/View/KBToolBar.m @@ -2,20 +2,144 @@ // KBToolBar.m // CustomKeyboard // -// Created by Mac on 2025/10/27. +// Created by Mac on 2025/10/28. // #import "KBToolBar.h" +@interface KBToolBar () +@property (nonatomic, strong) UIView *leftContainer; +@property (nonatomic, strong) NSArray *leftButtonsInternal; +@property (nonatomic, strong) UIButton *settingsButtonInternal; +@end + @implementation KBToolBar - (instancetype)initWithFrame:(CGRect)frame{ if (self = [super initWithFrame:frame]) { - + self.backgroundColor = [UIColor clearColor]; + _leftButtonTitles = @[@"Item1", @"Item2", @"Item3", @"Item4"]; // 默认标题 + [self setupUI]; } return self; } +#pragma mark - Public + +- (NSArray *)leftButtons { + return self.leftButtonsInternal; +} + +- (UIButton *)settingsButton { + return self.settingsButtonInternal; +} + +- (void)setLeftButtonTitles:(NSArray *)leftButtonTitles { + _leftButtonTitles = [leftButtonTitles copy]; + // Update titles if buttons already exist + [self.leftButtonsInternal enumerateObjectsUsingBlock:^(UIButton * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + if (idx < self.leftButtonTitles.count) { + [obj setTitle:self.leftButtonTitles[idx] forState:UIControlStateNormal]; + } + }]; +} + +#pragma mark - 视图搭建 + +- (void)setupUI { + [self addSubview:self.leftContainer]; + [self addSubview:self.settingsButtonInternal]; + + // 右侧设置按钮 + [self.settingsButtonInternal mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.equalTo(self.mas_right).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.right.equalTo(self.settingsButtonInternal.mas_left).offset(-12); + make.centerY.equalTo(self.mas_centerY); + make.height.mas_equalTo(32); + }]; + + // 在左侧容器中创建 4 个等宽按钮 + NSMutableArray *buttons = [NSMutableArray arrayWithCapacity:4]; + UIView *previous = nil; + for (NSInteger i = 0; i < 4; i++) { + UIButton *btn = [self buildActionButtonAtIndex:i]; + [self.leftContainer addSubview:btn]; + [buttons addObject:btn]; + [btn mas_makeConstraints:^(MASConstraintMaker *make) { + if (previous) { + make.left.equalTo(previous.mas_right).offset(8); + make.width.equalTo(previous); + } else { + make.left.equalTo(self.leftContainer.mas_left); + } + make.top.bottom.equalTo(self.leftContainer); + }]; + previous = btn; + } + // 最后一个按钮贴右侧 + [previous mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.equalTo(self.leftContainer.mas_right); + }]; + self.leftButtonsInternal = buttons.copy; +} + +- (UIButton *)buildActionButtonAtIndex:(NSInteger)idx { + UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem]; + btn.layer.cornerRadius = 16; + btn.layer.masksToBounds = YES; + btn.backgroundColor = [UIColor colorWithWhite:1 alpha:0.9]; + btn.titleLabel.font = [UIFont systemFontOfSize:14 weight:UIFontWeightMedium]; + NSString *title = (idx < self.leftButtonTitles.count) ? self.leftButtonTitles[idx] : [NSString stringWithFormat:@"Item%ld", (long)(idx+1)]; + [btn setTitle:title forState:UIControlStateNormal]; + [btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; + btn.tag = idx; + [btn addTarget:self action:@selector(onLeftAction:) forControlEvents:UIControlEventTouchUpInside]; + return btn; +} + +#pragma mark - Actions + +- (void)onLeftAction:(UIButton *)sender { + if ([self.delegate respondsToSelector:@selector(toolBar:didTapActionAtIndex:)]) { + [self.delegate toolBar:self didTapActionAtIndex:sender.tag]; + } +} + +- (void)onSettings { + if ([self.delegate respondsToSelector:@selector(toolBarDidTapSettings:)]) { + [self.delegate toolBarDidTapSettings:self]; + } +} + +#pragma mark - Lazy + +- (UIView *)leftContainer { + if (!_leftContainer) { + _leftContainer = [[UIView alloc] init]; + _leftContainer.backgroundColor = [UIColor clearColor]; + } + return _leftContainer; +} + +- (UIButton *)settingsButtonInternal { + if (!_settingsButtonInternal) { + _settingsButtonInternal = [UIButton buttonWithType:UIButtonTypeSystem]; + _settingsButtonInternal.layer.cornerRadius = 16; + _settingsButtonInternal.layer.masksToBounds = YES; + _settingsButtonInternal.backgroundColor = [UIColor colorWithWhite:1 alpha:0.9]; + [_settingsButtonInternal setTitle:@"⚙︎" forState:UIControlStateNormal]; // 简单的齿轮符号 + [_settingsButtonInternal setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; + [_settingsButtonInternal addTarget:self action:@selector(onSettings) forControlEvents:UIControlEventTouchUpInside]; + } + return _settingsButtonInternal; +} @end diff --git a/Podfile b/Podfile index 1bcc590..f86c536 100644 --- a/Podfile +++ b/Podfile @@ -2,14 +2,6 @@ source 'https://github.com/CocoaPods/Specs.git' platform :ios, '13.0' -target 'CustomKeyboard' do - # Comment the next line if you don't want to use dynamic frameworks - use_frameworks! - - # Pods for CustomKeyboard - -end - target 'keyBoard' do # Comment the next line if you don't want to use dynamic frameworks use_frameworks! @@ -17,8 +9,24 @@ target 'keyBoard' do pod 'AFNetworking','4.0.1' pod 'Bugly','2.6.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 + # Comment the next line if you don't want to use dynamic frameworks + use_frameworks! + + pod 'AFNetworking','4.0.1' + + pod 'Masonry', '1.1.0' + pod 'MBProgressHUD', '1.2.0' + pod 'MJExtension', '3.4.2' + pod 'DZNEmptyDataSet', '1.8.1' +end + + diff --git a/Podfile.lock b/Podfile.lock index ff55f71..5242fd1 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -15,7 +15,12 @@ PODS: - AFNetworking/UIKit (4.0.1): - AFNetworking/NSURLSession - Bugly (2.6.1) + - DZNEmptyDataSet (1.8.1) + - LookinServer (1.2.8): + - LookinServer/Core (= 1.2.8) + - LookinServer/Core (1.2.8) - Masonry (1.1.0) + - MBProgressHUD (1.2.0) - MJExtension (3.4.2) - MJRefresh (3.7.9) - SDWebImage (5.21.1): @@ -25,16 +30,23 @@ PODS: DEPENDENCIES: - AFNetworking (= 4.0.1) - Bugly (= 2.6.1) + - DZNEmptyDataSet (= 1.8.1) + - LookinServer - Masonry (= 1.1.0) + - MBProgressHUD (= 1.2.0) - MJExtension (= 3.4.2) - MJRefresh (= 3.7.9) + - SDWebImage - SDWebImage (= 5.21.1) SPEC REPOS: https://github.com/CocoaPods/Specs.git: - AFNetworking - Bugly + - DZNEmptyDataSet + - LookinServer - Masonry + - MBProgressHUD - MJExtension - MJRefresh - SDWebImage @@ -42,11 +54,14 @@ SPEC REPOS: SPEC CHECKSUMS: AFNetworking: 3bd23d814e976cd148d7d44c3ab78017b744cd58 Bugly: 217ac2ce5f0f2626d43dbaa4f70764c953a26a31 + DZNEmptyDataSet: 9525833b9e68ac21c30253e1d3d7076cc828eaa7 + LookinServer: 1b2b61c6402ae29fa22182d48f5cd067b4e99e80 Masonry: 678fab65091a9290e40e2832a55e7ab731aad201 + MBProgressHUD: 3ee5efcc380f6a79a7cc9b363dd669c5e1ae7406 MJExtension: e97d164cb411aa9795cf576093a1fa208b4a8dd8 MJRefresh: ff9e531227924c84ce459338414550a05d2aea78 SDWebImage: f29024626962457f3470184232766516dee8dfea -PODFILE CHECKSUM: b3c72fe500149c35040cdd73c1d91fe05777bc5f +PODFILE CHECKSUM: 6e0fcb7cf319a770ac7883c7cf3b1df1a6829e77 COCOAPODS: 1.16.2 diff --git a/Pods/DZNEmptyDataSet/LICENSE b/Pods/DZNEmptyDataSet/LICENSE new file mode 100644 index 0000000..199759a --- /dev/null +++ b/Pods/DZNEmptyDataSet/LICENSE @@ -0,0 +1,9 @@ +The MIT License (MIT) + +Copyright (c) 2016 Ignacio Romero Zurbuchen iromero@dzen.cl + +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/DZNEmptyDataSet/README.md b/Pods/DZNEmptyDataSet/README.md new file mode 100644 index 0000000..6f6be21 --- /dev/null +++ b/Pods/DZNEmptyDataSet/README.md @@ -0,0 +1,296 @@ +DZNEmptyDataSet +================= + +[![Pod Version](http://img.shields.io/cocoapods/v/DZNEmptyDataSet.svg)](http://cocoadocs.org/docsets/DZNEmptyDataSet/) +[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) +[![License](http://img.shields.io/badge/license-MIT-blue.svg)](http://opensource.org/licenses/MIT) + +### Projects using this library + +[Add your project to the list here](https://github.com/dzenbot/DZNEmptyDataSet/wiki/Projects-using-DZNEmptyDataSet) and provide a (320px wide) render of the result. + + +### The Empty Data Set Pattern +Also known as *[Empty State](http://emptystat.es/)* or *[Blank Slate](http://patternry.com/p=blank-slate/)*. + +Most applications show lists of content (data sets), which many turn out to be empty at one point, specially for new users with blank accounts. Empty screens create confusion by not being clear about what's going on, if there is an error/bug or if the user is supposed to do something within your app to be able to consume the content. + +Please read this very interesting article about [*Designing For The Empty States*](http://tympanus.net/codrops/2013/01/09/designing-for-the-empty-states/). + +![Screenshots_Row1](https://raw.githubusercontent.com/dzenbot/UITableView-DataSet/master/Examples/Applications/Screenshots/Screenshots_row1.png) +![Screenshots_Row2](https://raw.githubusercontent.com/dzenbot/UITableView-DataSet/master/Examples/Applications/Screenshots/Screenshots_row2.png) +(*These are real life examples, available in the 'Applications' sample project*) + +**[Empty Data Sets](http://pttrns.com/?did=1&scid=30)** are helpful for: +* Avoiding white-screens and communicating to your users why the screen is empty. +* Calling to action (particularly as an onboarding process). +* Avoiding other interruptive mechanisms like showing error alerts. +* Being consistent and improving the user experience. +* Delivering a brand presence. + + +### Features +* Compatible with UITableView and UICollectionView. Also compatible with UISearchDisplayController and UIScrollView. +* Gives multiple possibilities of layout and appearance, by showing an image and/or title label and/or description label and/or button. +* Uses NSAttributedString for easier appearance customisation. +* Uses auto-layout to automagically center the content to the tableview, with auto-rotation support. Also accepts custom vertical and horizontal alignment. +* Background color customisation. +* Allows tap gesture on the whole tableview rectangle (useful for resigning first responder or similar actions). +* For more advanced customisation, it allows a custom view. +* Compatible with Storyboard. +* Compatible with iOS 6 or later. +* Compatible with iPhone and iPad. +* **App Store ready** + +This library has been designed in a way where you won't need to extend UITableView or UICollectionView class. It will still work when using UITableViewController or UICollectionViewController. +By just conforming to DZNEmptyDataSetSource & DZNEmptyDataSetDelegate, you will be able to fully customize the content and appearance of the empty states for your application. + + +## Installation + +Available in [CocoaPods](http://cocoapods.org/?q=DZNEmptyDataSet) +```ruby +pod 'DZNEmptyDataSet' +``` + +To integrate DZNEmptyDataSet into your Xcode project using Carthage, specify it in your `Cartfile`: + +```ruby +github "dzenbot/DZNEmptyDataSet" +``` + + +## How to use +For complete documentation, [visit CocoaPods' auto-generated doc](http://cocoadocs.org/docsets/DZNEmptyDataSet/) + +### Import +```objc +#import "UIScrollView+EmptyDataSet.h" +``` +Unless you are importing as a framework, then do: +```objc +#import "" +``` + +### Protocol Conformance +Conform to datasource and/or delegate. +```objc +@interface MainViewController : UITableViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.tableView.emptyDataSetSource = self; + self.tableView.emptyDataSetDelegate = self; + + // A little trick for removing the cell separators + self.tableView.tableFooterView = [UIView new]; +} +``` + +### Data Source Implementation +Return the content you want to show on the empty state, and take advantage of NSAttributedString features to customise the text appearance. + +The image for the empty state: +```objc +- (UIImage *)imageForEmptyDataSet:(UIScrollView *)scrollView +{ + return [UIImage imageNamed:@"empty_placeholder"]; +} +``` + +The image view animation +```objc +- (CAAnimation *)imageAnimationForEmptyDataSet:(UIScrollView *)scrollView +{ + CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath: @"transform"]; + + animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity]; + animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI_2, 0.0, 0.0, 1.0)]; + + animation.duration = 0.25; + animation.cumulative = YES; + animation.repeatCount = MAXFLOAT; + + return animation; +} +``` + +The attributed string for the title of the empty state: +```objc +- (NSAttributedString *)titleForEmptyDataSet:(UIScrollView *)scrollView +{ + NSString *text = @"Please Allow Photo Access"; + + NSDictionary *attributes = @{NSFontAttributeName: [UIFont boldSystemFontOfSize:18.0f], + NSForegroundColorAttributeName: [UIColor darkGrayColor]}; + + return [[NSAttributedString alloc] initWithString:text attributes:attributes]; +} +``` + +The attributed string for the description of the empty state: +```objc +- (NSAttributedString *)descriptionForEmptyDataSet:(UIScrollView *)scrollView +{ + NSString *text = @"This allows you to share photos from your library and save photos to your camera roll."; + + NSMutableParagraphStyle *paragraph = [NSMutableParagraphStyle new]; + paragraph.lineBreakMode = NSLineBreakByWordWrapping; + paragraph.alignment = NSTextAlignmentCenter; + + NSDictionary *attributes = @{NSFontAttributeName: [UIFont systemFontOfSize:14.0f], + NSForegroundColorAttributeName: [UIColor lightGrayColor], + NSParagraphStyleAttributeName: paragraph}; + + return [[NSAttributedString alloc] initWithString:text attributes:attributes]; +} +``` + +The attributed string to be used for the specified button state: +```objc +- (NSAttributedString *)buttonTitleForEmptyDataSet:(UIScrollView *)scrollView forState:(UIControlState)state +{ + NSDictionary *attributes = @{NSFontAttributeName: [UIFont boldSystemFontOfSize:17.0f]}; + + return [[NSAttributedString alloc] initWithString:@"Continue" attributes:attributes]; +} +``` + +or the image to be used for the specified button state: +```objc +- (UIImage *)buttonImageForEmptyDataSet:(UIScrollView *)scrollView forState:(UIControlState)state +{ + return [UIImage imageNamed:@"button_image"]; +} +``` + +The background color for the empty state: +```objc +- (UIColor *)backgroundColorForEmptyDataSet:(UIScrollView *)scrollView +{ + return [UIColor whiteColor]; +} +``` + +If you need a more complex layout, you can return a custom view instead: +```objc +- (UIView *)customViewForEmptyDataSet:(UIScrollView *)scrollView +{ + UIActivityIndicatorView *activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; + [activityView startAnimating]; + return activityView; +} +``` + +Additionally, you can also adjust the vertical alignment of the content view (ie: useful when there is tableHeaderView visible): +```objc +- (CGFloat)verticalOffsetForEmptyDataSet:(UIScrollView *)scrollView +{ + return -self.tableView.tableHeaderView.frame.size.height/2.0f; +} +``` + +Finally, you can separate components from each other (default separation is 11 pts): +```objc +- (CGFloat)spaceHeightForEmptyDataSet:(UIScrollView *)scrollView +{ + return 20.0f; +} +``` + + +### Delegate Implementation +Return the behaviours you would expect from the empty states, and receive the user events. + +Asks to know if the empty state should be rendered and displayed (Default is YES) : +```objc +- (BOOL)emptyDataSetShouldDisplay:(UIScrollView *)scrollView +{ + return YES; +} +``` + +Asks for interaction permission (Default is YES) : +```objc +- (BOOL)emptyDataSetShouldAllowTouch:(UIScrollView *)scrollView +{ + return YES; +} +``` + +Asks for scrolling permission (Default is NO) : +```objc +- (BOOL)emptyDataSetShouldAllowScroll:(UIScrollView *)scrollView +{ + return YES; +} +``` + +Asks for image view animation permission (Default is NO) : +```objc +- (BOOL) emptyDataSetShouldAllowImageViewAnimate:(UIScrollView *)scrollView +{ + return YES; +} +``` + +Notifies when the dataset view was tapped: +```objc +- (void)emptyDataSet:(UIScrollView *)scrollView didTapView:(UIView *)view +{ + // Do something +} +``` + +Notifies when the data set call to action button was tapped: +```objc +- (void)emptyDataSet:(UIScrollView *)scrollView didTapButton:(UIButton *)button +{ + // Do something +} +``` + +### Refresh layout +If you need to refresh the empty state layout, simply call: + +```objc +[self.tableView reloadData]; +``` +or +```objc +[self.collectionView reloadData]; +``` +depending of which you are using. + +### Force layout update +You can also call `[self.tableView reloadEmptyDataSet]` to invalidate the current empty state layout and trigger a layout update, bypassing `-reloadData`. This might be useful if you have a lot of logic on your data source that you want to avoid calling, when not needed. `[self.scrollView reloadEmptyDataSet]` is the only way to refresh content when using with UIScrollView. + + +## Sample projects + +#### Applications +This project replicates several popular application's empty states (~20) with their exact content and appearance, such as Airbnb, Dropbox, Facebook, Foursquare, and many others. See how easy and flexible it is to customize the appearance of your empty states. You can also use this project as a playground to test things. + +#### Countries +This project shows a list of the world countries loaded from CoreData. It uses NSFecthedResultController for filtering search. When searching and no content is matched, a simple empty state is shown. See how to interact between the UITableViewDataSource and the DZNEmptyDataSetSource protocols, while using a typical CoreData stack. + +#### Colors +This project is a simple example of how this library also works with UICollectionView and UISearchDisplayController, while using Storyboards. + + +## Collaboration +Feel free to collaborate with ideas, issues and/or pull requests. + + +## License +(The MIT License) + +Copyright (c) 2016 Ignacio Romero Zurbuchen iromero@dzen.cl + +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/DZNEmptyDataSet/Source/UIScrollView+EmptyDataSet.h b/Pods/DZNEmptyDataSet/Source/UIScrollView+EmptyDataSet.h new file mode 100644 index 0000000..5dd70f2 --- /dev/null +++ b/Pods/DZNEmptyDataSet/Source/UIScrollView+EmptyDataSet.h @@ -0,0 +1,280 @@ +// +// UIScrollView+EmptyDataSet.h +// DZNEmptyDataSet +// https://github.com/dzenbot/DZNEmptyDataSet +// +// Created by Ignacio Romero Zurbuchen on 6/20/14. +// Copyright (c) 2016 DZN Labs. All rights reserved. +// Licence: MIT-Licence +// + +#import + +@protocol DZNEmptyDataSetSource; +@protocol DZNEmptyDataSetDelegate; + +#define DZNEmptyDataSetDeprecated(instead) DEPRECATED_MSG_ATTRIBUTE(" Use " # instead " instead") + +/** + A drop-in UITableView/UICollectionView superclass category for showing empty datasets whenever the view has no content to display. + @discussion It will work automatically, by just conforming to DZNEmptyDataSetSource, and returning the data you want to show. + */ +@interface UIScrollView (EmptyDataSet) + +/** The empty datasets data source. */ +@property (nonatomic, weak) IBOutlet id emptyDataSetSource; +/** The empty datasets delegate. */ +@property (nonatomic, weak) IBOutlet id emptyDataSetDelegate; +/** YES if any empty dataset is visible. */ +@property (nonatomic, readonly, getter = isEmptyDataSetVisible) BOOL emptyDataSetVisible; + +/** + Reloads the empty dataset content receiver. + @discussion Call this method to force all the data to refresh. Calling -reloadData is similar, but this forces only the empty dataset to reload, not the entire table view or collection view. + */ +- (void)reloadEmptyDataSet; + +@end + + +/** + The object that acts as the data source of the empty datasets. + @discussion The data source must adopt the DZNEmptyDataSetSource protocol. The data source is not retained. All data source methods are optional. + */ +@protocol DZNEmptyDataSetSource +@optional + +/** + Asks the data source for the title of the dataset. + The dataset uses a fixed font style by default, if no attributes are set. If you want a different font style, return a attributed string. + + @param scrollView A scrollView subclass informing the data source. + @return An attributed string for the dataset title, combining font, text color, text pararaph style, etc. + */ +- (NSAttributedString *)titleForEmptyDataSet:(UIScrollView *)scrollView; + +/** + Asks the data source for the description of the dataset. + The dataset uses a fixed font style by default, if no attributes are set. If you want a different font style, return a attributed string. + + @param scrollView A scrollView subclass informing the data source. + @return An attributed string for the dataset description text, combining font, text color, text pararaph style, etc. + */ +- (NSAttributedString *)descriptionForEmptyDataSet:(UIScrollView *)scrollView; + +/** + Asks the data source for the image of the dataset. + + @param scrollView A scrollView subclass informing the data source. + @return An image for the dataset. + */ +- (UIImage *)imageForEmptyDataSet:(UIScrollView *)scrollView; + + +/** + Asks the data source for a tint color of the image dataset. Default is nil. + + @param scrollView A scrollView subclass object informing the data source. + @return A color to tint the image of the dataset. + */ +- (UIColor *)imageTintColorForEmptyDataSet:(UIScrollView *)scrollView; + +/** + * Asks the data source for the image animation of the dataset. + * + * @param scrollView A scrollView subclass object informing the delegate. + * + * @return image animation + */ +- (CAAnimation *) imageAnimationForEmptyDataSet:(UIScrollView *) scrollView; + +/** + Asks the data source for the title to be used for the specified button state. + The dataset uses a fixed font style by default, if no attributes are set. If you want a different font style, return a attributed string. + + @param scrollView A scrollView subclass object informing the data source. + @param state The state that uses the specified title. The possible values are described in UIControlState. + @return An attributed string for the dataset button title, combining font, text color, text pararaph style, etc. + */ +- (NSAttributedString *)buttonTitleForEmptyDataSet:(UIScrollView *)scrollView forState:(UIControlState)state; + +/** + Asks the data source for the image to be used for the specified button state. + This method will override buttonTitleForEmptyDataSet:forState: and present the image only without any text. + + @param scrollView A scrollView subclass object informing the data source. + @param state The state that uses the specified title. The possible values are described in UIControlState. + @return An image for the dataset button imageview. + */ +- (UIImage *)buttonImageForEmptyDataSet:(UIScrollView *)scrollView forState:(UIControlState)state; + +/** + Asks the data source for a background image to be used for the specified button state. + There is no default style for this call. + + @param scrollView A scrollView subclass informing the data source. + @param state The state that uses the specified image. The values are described in UIControlState. + @return An attributed string for the dataset button title, combining font, text color, text pararaph style, etc. + */ +- (UIImage *)buttonBackgroundImageForEmptyDataSet:(UIScrollView *)scrollView forState:(UIControlState)state; + +/** + Asks the data source for the background color of the dataset. Default is clear color. + + @param scrollView A scrollView subclass object informing the data source. + @return A color to be applied to the dataset background view. + */ +- (UIColor *)backgroundColorForEmptyDataSet:(UIScrollView *)scrollView; + +/** + Asks the data source for a custom view to be displayed instead of the default views such as labels, imageview and button. Default is nil. + Use this method to show an activity view indicator for loading feedback, or for complete custom empty data set. + Returning a custom view will ignore -offsetForEmptyDataSet and -spaceHeightForEmptyDataSet configurations. + + @param scrollView A scrollView subclass object informing the delegate. + @return The custom view. + */ +- (UIView *)customViewForEmptyDataSet:(UIScrollView *)scrollView; + +/** + Asks the data source for a offset for vertical and horizontal alignment of the content. Default is CGPointZero. + + @param scrollView A scrollView subclass object informing the delegate. + @return The offset for vertical and horizontal alignment. + */ +- (CGPoint)offsetForEmptyDataSet:(UIScrollView *)scrollView DZNEmptyDataSetDeprecated(-verticalOffsetForEmptyDataSet:); +- (CGFloat)verticalOffsetForEmptyDataSet:(UIScrollView *)scrollView; + +/** + Asks the data source for a vertical space between elements. Default is 11 pts. + + @param scrollView A scrollView subclass object informing the delegate. + @return The space height between elements. + */ +- (CGFloat)spaceHeightForEmptyDataSet:(UIScrollView *)scrollView; + +@end + + +/** + The object that acts as the delegate of the empty datasets. + @discussion The delegate can adopt the DZNEmptyDataSetDelegate protocol. The delegate is not retained. All delegate methods are optional. + + @discussion All delegate methods are optional. Use this delegate for receiving action callbacks. + */ +@protocol DZNEmptyDataSetDelegate +@optional + +/** + Asks the delegate to know if the empty dataset should fade in when displayed. Default is YES. + + @param scrollView A scrollView subclass object informing the delegate. + @return YES if the empty dataset should fade in. + */ +- (BOOL)emptyDataSetShouldFadeIn:(UIScrollView *)scrollView; + +/** + Asks the delegate to know if the empty dataset should still be displayed when the amount of items is more than 0. Default is NO + + @param scrollView A scrollView subclass object informing the delegate. + @return YES if empty dataset should be forced to display + */ +- (BOOL)emptyDataSetShouldBeForcedToDisplay:(UIScrollView *)scrollView; + +/** + Asks the delegate to know if the empty dataset should be rendered and displayed. Default is YES. + + @param scrollView A scrollView subclass object informing the delegate. + @return YES if the empty dataset should show. + */ +- (BOOL)emptyDataSetShouldDisplay:(UIScrollView *)scrollView; + +/** + Asks the delegate for touch permission. Default is YES. + + @param scrollView A scrollView subclass object informing the delegate. + @return YES if the empty dataset receives touch gestures. + */ +- (BOOL)emptyDataSetShouldAllowTouch:(UIScrollView *)scrollView; + +/** + Asks the delegate for scroll permission. Default is NO. + + @param scrollView A scrollView subclass object informing the delegate. + @return YES if the empty dataset is allowed to be scrollable. + */ +- (BOOL)emptyDataSetShouldAllowScroll:(UIScrollView *)scrollView; + +/** + Asks the delegate for image view animation permission. Default is NO. + Make sure to return a valid CAAnimation object from imageAnimationForEmptyDataSet: + + @param scrollView A scrollView subclass object informing the delegate. + @return YES if the empty dataset is allowed to animate + */ +- (BOOL)emptyDataSetShouldAnimateImageView:(UIScrollView *)scrollView; + +/** + Tells the delegate that the empty dataset view was tapped. + Use this method either to resignFirstResponder of a textfield or searchBar. + + @param scrollView A scrollView subclass informing the delegate. + */ +- (void)emptyDataSetDidTapView:(UIScrollView *)scrollView DZNEmptyDataSetDeprecated(-emptyDataSet:didTapView:); + +/** + Tells the delegate that the action button was tapped. + + @param scrollView A scrollView subclass informing the delegate. + */ +- (void)emptyDataSetDidTapButton:(UIScrollView *)scrollView DZNEmptyDataSetDeprecated(-emptyDataSet:didTapButton:); + +/** + Tells the delegate that the empty dataset view was tapped. + Use this method either to resignFirstResponder of a textfield or searchBar. + + @param scrollView A scrollView subclass informing the delegate. + @param view the view tapped by the user + */ +- (void)emptyDataSet:(UIScrollView *)scrollView didTapView:(UIView *)view; + +/** + Tells the delegate that the action button was tapped. + + @param scrollView A scrollView subclass informing the delegate. + @param button the button tapped by the user + */ +- (void)emptyDataSet:(UIScrollView *)scrollView didTapButton:(UIButton *)button; + +/** + Tells the delegate that the empty data set will appear. + + @param scrollView A scrollView subclass informing the delegate. + */ +- (void)emptyDataSetWillAppear:(UIScrollView *)scrollView; + +/** + Tells the delegate that the empty data set did appear. + + @param scrollView A scrollView subclass informing the delegate. + */ +- (void)emptyDataSetDidAppear:(UIScrollView *)scrollView; + +/** + Tells the delegate that the empty data set will disappear. + + @param scrollView A scrollView subclass informing the delegate. + */ +- (void)emptyDataSetWillDisappear:(UIScrollView *)scrollView; + +/** + Tells the delegate that the empty data set did disappear. + + @param scrollView A scrollView subclass informing the delegate. + */ +- (void)emptyDataSetDidDisappear:(UIScrollView *)scrollView; + +@end + +#undef DZNEmptyDataSetDeprecated + diff --git a/Pods/DZNEmptyDataSet/Source/UIScrollView+EmptyDataSet.m b/Pods/DZNEmptyDataSet/Source/UIScrollView+EmptyDataSet.m new file mode 100644 index 0000000..ce43ffc --- /dev/null +++ b/Pods/DZNEmptyDataSet/Source/UIScrollView+EmptyDataSet.m @@ -0,0 +1,1074 @@ +// +// UIScrollView+EmptyDataSet.m +// DZNEmptyDataSet +// https://github.com/dzenbot/DZNEmptyDataSet +// +// Created by Ignacio Romero Zurbuchen on 6/20/14. +// Copyright (c) 2016 DZN Labs. All rights reserved. +// Licence: MIT-Licence +// + +#import "UIScrollView+EmptyDataSet.h" +#import + +@interface UIView (DZNConstraintBasedLayoutExtensions) + +- (NSLayoutConstraint *)equallyRelatedConstraintWithView:(UIView *)view attribute:(NSLayoutAttribute)attribute; + +@end + +@interface DZNWeakObjectContainer : NSObject + +@property (nonatomic, readonly, weak) id weakObject; + +- (instancetype)initWithWeakObject:(id)object; + +@end + +@interface DZNEmptyDataSetView : UIView + +@property (nonatomic, readonly) UIView *contentView; +@property (nonatomic, readonly) UILabel *titleLabel; +@property (nonatomic, readonly) UILabel *detailLabel; +@property (nonatomic, readonly) UIImageView *imageView; +@property (nonatomic, readonly) UIButton *button; +@property (nonatomic, strong) UIView *customView; +@property (nonatomic, strong) UITapGestureRecognizer *tapGesture; + +@property (nonatomic, assign) CGFloat verticalOffset; +@property (nonatomic, assign) CGFloat verticalSpace; + +@property (nonatomic, assign) BOOL fadeInOnDisplay; + +- (void)setupConstraints; +- (void)prepareForReuse; + +@end + + +#pragma mark - UIScrollView+EmptyDataSet + +static char const * const kEmptyDataSetSource = "emptyDataSetSource"; +static char const * const kEmptyDataSetDelegate = "emptyDataSetDelegate"; +static char const * const kEmptyDataSetView = "emptyDataSetView"; + +#define kEmptyImageViewAnimationKey @"com.dzn.emptyDataSet.imageViewAnimation" + +@interface UIScrollView () +@property (nonatomic, readonly) DZNEmptyDataSetView *emptyDataSetView; +@end + +@implementation UIScrollView (DZNEmptyDataSet) + +#pragma mark - Getters (Public) + +- (id)emptyDataSetSource +{ + DZNWeakObjectContainer *container = objc_getAssociatedObject(self, kEmptyDataSetSource); + return container.weakObject; +} + +- (id)emptyDataSetDelegate +{ + DZNWeakObjectContainer *container = objc_getAssociatedObject(self, kEmptyDataSetDelegate); + return container.weakObject; +} + +- (BOOL)isEmptyDataSetVisible +{ + UIView *view = objc_getAssociatedObject(self, kEmptyDataSetView); + return view ? !view.hidden : NO; +} + + +#pragma mark - Getters (Private) + +- (DZNEmptyDataSetView *)emptyDataSetView +{ + DZNEmptyDataSetView *view = objc_getAssociatedObject(self, kEmptyDataSetView); + + if (!view) + { + view = [DZNEmptyDataSetView new]; + view.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight; + view.hidden = YES; + + view.tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dzn_didTapContentView:)]; + view.tapGesture.delegate = self; + [view addGestureRecognizer:view.tapGesture]; + + [self setEmptyDataSetView:view]; + } + return view; +} + +- (BOOL)dzn_canDisplay +{ + if (self.emptyDataSetSource && [self.emptyDataSetSource conformsToProtocol:@protocol(DZNEmptyDataSetSource)]) { + if ([self isKindOfClass:[UITableView class]] || [self isKindOfClass:[UICollectionView class]] || [self isKindOfClass:[UIScrollView class]]) { + return YES; + } + } + + return NO; +} + +- (NSInteger)dzn_itemsCount +{ + NSInteger items = 0; + + // UIScollView doesn't respond to 'dataSource' so let's exit + if (![self respondsToSelector:@selector(dataSource)]) { + return items; + } + + // UITableView support + if ([self isKindOfClass:[UITableView class]]) { + + UITableView *tableView = (UITableView *)self; + id dataSource = tableView.dataSource; + + NSInteger sections = 1; + + if (dataSource && [dataSource respondsToSelector:@selector(numberOfSectionsInTableView:)]) { + sections = [dataSource numberOfSectionsInTableView:tableView]; + } + + if (dataSource && [dataSource respondsToSelector:@selector(tableView:numberOfRowsInSection:)]) { + for (NSInteger section = 0; section < sections; section++) { + items += [dataSource tableView:tableView numberOfRowsInSection:section]; + } + } + } + // UICollectionView support + else if ([self isKindOfClass:[UICollectionView class]]) { + + UICollectionView *collectionView = (UICollectionView *)self; + id dataSource = collectionView.dataSource; + + NSInteger sections = 1; + + if (dataSource && [dataSource respondsToSelector:@selector(numberOfSectionsInCollectionView:)]) { + sections = [dataSource numberOfSectionsInCollectionView:collectionView]; + } + + if (dataSource && [dataSource respondsToSelector:@selector(collectionView:numberOfItemsInSection:)]) { + for (NSInteger section = 0; section < sections; section++) { + items += [dataSource collectionView:collectionView numberOfItemsInSection:section]; + } + } + } + + return items; +} + + +#pragma mark - Data Source Getters + +- (NSAttributedString *)dzn_titleLabelString +{ + if (self.emptyDataSetSource && [self.emptyDataSetSource respondsToSelector:@selector(titleForEmptyDataSet:)]) { + NSAttributedString *string = [self.emptyDataSetSource titleForEmptyDataSet:self]; + if (string) NSAssert([string isKindOfClass:[NSAttributedString class]], @"You must return a valid NSAttributedString object for -titleForEmptyDataSet:"); + return string; + } + return nil; +} + +- (NSAttributedString *)dzn_detailLabelString +{ + if (self.emptyDataSetSource && [self.emptyDataSetSource respondsToSelector:@selector(descriptionForEmptyDataSet:)]) { + NSAttributedString *string = [self.emptyDataSetSource descriptionForEmptyDataSet:self]; + if (string) NSAssert([string isKindOfClass:[NSAttributedString class]], @"You must return a valid NSAttributedString object for -descriptionForEmptyDataSet:"); + return string; + } + return nil; +} + +- (UIImage *)dzn_image +{ + if (self.emptyDataSetSource && [self.emptyDataSetSource respondsToSelector:@selector(imageForEmptyDataSet:)]) { + UIImage *image = [self.emptyDataSetSource imageForEmptyDataSet:self]; + if (image) NSAssert([image isKindOfClass:[UIImage class]], @"You must return a valid UIImage object for -imageForEmptyDataSet:"); + return image; + } + return nil; +} + +- (CAAnimation *)dzn_imageAnimation +{ + if (self.emptyDataSetSource && [self.emptyDataSetSource respondsToSelector:@selector(imageAnimationForEmptyDataSet:)]) { + CAAnimation *imageAnimation = [self.emptyDataSetSource imageAnimationForEmptyDataSet:self]; + if (imageAnimation) NSAssert([imageAnimation isKindOfClass:[CAAnimation class]], @"You must return a valid CAAnimation object for -imageAnimationForEmptyDataSet:"); + return imageAnimation; + } + return nil; +} + +- (UIColor *)dzn_imageTintColor +{ + if (self.emptyDataSetSource && [self.emptyDataSetSource respondsToSelector:@selector(imageTintColorForEmptyDataSet:)]) { + UIColor *color = [self.emptyDataSetSource imageTintColorForEmptyDataSet:self]; + if (color) NSAssert([color isKindOfClass:[UIColor class]], @"You must return a valid UIColor object for -imageTintColorForEmptyDataSet:"); + return color; + } + return nil; +} + +- (NSAttributedString *)dzn_buttonTitleForState:(UIControlState)state +{ + if (self.emptyDataSetSource && [self.emptyDataSetSource respondsToSelector:@selector(buttonTitleForEmptyDataSet:forState:)]) { + NSAttributedString *string = [self.emptyDataSetSource buttonTitleForEmptyDataSet:self forState:state]; + if (string) NSAssert([string isKindOfClass:[NSAttributedString class]], @"You must return a valid NSAttributedString object for -buttonTitleForEmptyDataSet:forState:"); + return string; + } + return nil; +} + +- (UIImage *)dzn_buttonImageForState:(UIControlState)state +{ + if (self.emptyDataSetSource && [self.emptyDataSetSource respondsToSelector:@selector(buttonImageForEmptyDataSet:forState:)]) { + UIImage *image = [self.emptyDataSetSource buttonImageForEmptyDataSet:self forState:state]; + if (image) NSAssert([image isKindOfClass:[UIImage class]], @"You must return a valid UIImage object for -buttonImageForEmptyDataSet:forState:"); + return image; + } + return nil; +} + +- (UIImage *)dzn_buttonBackgroundImageForState:(UIControlState)state +{ + if (self.emptyDataSetSource && [self.emptyDataSetSource respondsToSelector:@selector(buttonBackgroundImageForEmptyDataSet:forState:)]) { + UIImage *image = [self.emptyDataSetSource buttonBackgroundImageForEmptyDataSet:self forState:state]; + if (image) NSAssert([image isKindOfClass:[UIImage class]], @"You must return a valid UIImage object for -buttonBackgroundImageForEmptyDataSet:forState:"); + return image; + } + return nil; +} + +- (UIColor *)dzn_dataSetBackgroundColor +{ + if (self.emptyDataSetSource && [self.emptyDataSetSource respondsToSelector:@selector(backgroundColorForEmptyDataSet:)]) { + UIColor *color = [self.emptyDataSetSource backgroundColorForEmptyDataSet:self]; + if (color) NSAssert([color isKindOfClass:[UIColor class]], @"You must return a valid UIColor object for -backgroundColorForEmptyDataSet:"); + return color; + } + return [UIColor clearColor]; +} + +- (UIView *)dzn_customView +{ + if (self.emptyDataSetSource && [self.emptyDataSetSource respondsToSelector:@selector(customViewForEmptyDataSet:)]) { + UIView *view = [self.emptyDataSetSource customViewForEmptyDataSet:self]; + if (view) NSAssert([view isKindOfClass:[UIView class]], @"You must return a valid UIView object for -customViewForEmptyDataSet:"); + return view; + } + return nil; +} + +- (CGFloat)dzn_verticalOffset +{ + CGFloat offset = 0.0; + + if (self.emptyDataSetSource && [self.emptyDataSetSource respondsToSelector:@selector(verticalOffsetForEmptyDataSet:)]) { + offset = [self.emptyDataSetSource verticalOffsetForEmptyDataSet:self]; + } + return offset; +} + +- (CGFloat)dzn_verticalSpace +{ + if (self.emptyDataSetSource && [self.emptyDataSetSource respondsToSelector:@selector(spaceHeightForEmptyDataSet:)]) { + return [self.emptyDataSetSource spaceHeightForEmptyDataSet:self]; + } + return 0.0; +} + + +#pragma mark - Delegate Getters & Events (Private) + +- (BOOL)dzn_shouldFadeIn { + if (self.emptyDataSetDelegate && [self.emptyDataSetDelegate respondsToSelector:@selector(emptyDataSetShouldFadeIn:)]) { + return [self.emptyDataSetDelegate emptyDataSetShouldFadeIn:self]; + } + return YES; +} + +- (BOOL)dzn_shouldDisplay +{ + if (self.emptyDataSetDelegate && [self.emptyDataSetDelegate respondsToSelector:@selector(emptyDataSetShouldDisplay:)]) { + return [self.emptyDataSetDelegate emptyDataSetShouldDisplay:self]; + } + return YES; +} + +- (BOOL)dzn_shouldBeForcedToDisplay +{ + if (self.emptyDataSetDelegate && [self.emptyDataSetDelegate respondsToSelector:@selector(emptyDataSetShouldBeForcedToDisplay:)]) { + return [self.emptyDataSetDelegate emptyDataSetShouldBeForcedToDisplay:self]; + } + return NO; +} + +- (BOOL)dzn_isTouchAllowed +{ + if (self.emptyDataSetDelegate && [self.emptyDataSetDelegate respondsToSelector:@selector(emptyDataSetShouldAllowTouch:)]) { + return [self.emptyDataSetDelegate emptyDataSetShouldAllowTouch:self]; + } + return YES; +} + +- (BOOL)dzn_isScrollAllowed +{ + if (self.emptyDataSetDelegate && [self.emptyDataSetDelegate respondsToSelector:@selector(emptyDataSetShouldAllowScroll:)]) { + return [self.emptyDataSetDelegate emptyDataSetShouldAllowScroll:self]; + } + return NO; +} + +- (BOOL)dzn_isImageViewAnimateAllowed +{ + if (self.emptyDataSetDelegate && [self.emptyDataSetDelegate respondsToSelector:@selector(emptyDataSetShouldAnimateImageView:)]) { + return [self.emptyDataSetDelegate emptyDataSetShouldAnimateImageView:self]; + } + return NO; +} + +- (void)dzn_willAppear +{ + if (self.emptyDataSetDelegate && [self.emptyDataSetDelegate respondsToSelector:@selector(emptyDataSetWillAppear:)]) { + [self.emptyDataSetDelegate emptyDataSetWillAppear:self]; + } +} + +- (void)dzn_didAppear +{ + if (self.emptyDataSetDelegate && [self.emptyDataSetDelegate respondsToSelector:@selector(emptyDataSetDidAppear:)]) { + [self.emptyDataSetDelegate emptyDataSetDidAppear:self]; + } +} + +- (void)dzn_willDisappear +{ + if (self.emptyDataSetDelegate && [self.emptyDataSetDelegate respondsToSelector:@selector(emptyDataSetWillDisappear:)]) { + [self.emptyDataSetDelegate emptyDataSetWillDisappear:self]; + } +} + +- (void)dzn_didDisappear +{ + if (self.emptyDataSetDelegate && [self.emptyDataSetDelegate respondsToSelector:@selector(emptyDataSetDidDisappear:)]) { + [self.emptyDataSetDelegate emptyDataSetDidDisappear:self]; + } +} + +- (void)dzn_didTapContentView:(id)sender +{ + if (self.emptyDataSetDelegate && [self.emptyDataSetDelegate respondsToSelector:@selector(emptyDataSet:didTapView:)]) { + [self.emptyDataSetDelegate emptyDataSet:self didTapView:sender]; + } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + else if (self.emptyDataSetDelegate && [self.emptyDataSetDelegate respondsToSelector:@selector(emptyDataSetDidTapView:)]) { + [self.emptyDataSetDelegate emptyDataSetDidTapView:self]; + } +#pragma clang diagnostic pop +} + +- (void)dzn_didTapDataButton:(id)sender +{ + if (self.emptyDataSetDelegate && [self.emptyDataSetDelegate respondsToSelector:@selector(emptyDataSet:didTapButton:)]) { + [self.emptyDataSetDelegate emptyDataSet:self didTapButton:sender]; + } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + else if (self.emptyDataSetDelegate && [self.emptyDataSetDelegate respondsToSelector:@selector(emptyDataSetDidTapButton:)]) { + [self.emptyDataSetDelegate emptyDataSetDidTapButton:self]; + } +#pragma clang diagnostic pop +} + + +#pragma mark - Setters (Public) + +- (void)setEmptyDataSetSource:(id)datasource +{ + if (!datasource || ![self dzn_canDisplay]) { + [self dzn_invalidate]; + } + + objc_setAssociatedObject(self, kEmptyDataSetSource, [[DZNWeakObjectContainer alloc] initWithWeakObject:datasource], OBJC_ASSOCIATION_RETAIN_NONATOMIC); + + // We add method sizzling for injecting -dzn_reloadData implementation to the native -reloadData implementation + [self swizzleIfPossible:@selector(reloadData)]; + + // Exclusively for UITableView, we also inject -dzn_reloadData to -endUpdates + if ([self isKindOfClass:[UITableView class]]) { + [self swizzleIfPossible:@selector(endUpdates)]; + } +} + +- (void)setEmptyDataSetDelegate:(id)delegate +{ + if (!delegate) { + [self dzn_invalidate]; + } + + objc_setAssociatedObject(self, kEmptyDataSetDelegate, [[DZNWeakObjectContainer alloc] initWithWeakObject:delegate], OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + + +#pragma mark - Setters (Private) + +- (void)setEmptyDataSetView:(DZNEmptyDataSetView *)view +{ + objc_setAssociatedObject(self, kEmptyDataSetView, view, OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + + +#pragma mark - Reload APIs (Public) + +- (void)reloadEmptyDataSet +{ + [self dzn_reloadEmptyDataSet]; +} + + +#pragma mark - Reload APIs (Private) + +- (void)dzn_reloadEmptyDataSet +{ + if (![self dzn_canDisplay]) { + return; + } + + if (([self dzn_shouldDisplay] && [self dzn_itemsCount] == 0) || [self dzn_shouldBeForcedToDisplay]) + { + // Notifies that the empty dataset view will appear + [self dzn_willAppear]; + + DZNEmptyDataSetView *view = self.emptyDataSetView; + + if (!view.superview) { + // Send the view all the way to the back, in case a header and/or footer is present, as well as for sectionHeaders or any other content + if (([self isKindOfClass:[UITableView class]] || [self isKindOfClass:[UICollectionView class]]) && self.subviews.count > 1) { + [self insertSubview:view atIndex:0]; + } + else { + [self addSubview:view]; + } + } + + // Removing view resetting the view and its constraints it very important to guarantee a good state + [view prepareForReuse]; + + UIView *customView = [self dzn_customView]; + + // If a non-nil custom view is available, let's configure it instead + if (customView) { + view.customView = customView; + } + else { + // Get the data from the data source + NSAttributedString *titleLabelString = [self dzn_titleLabelString]; + NSAttributedString *detailLabelString = [self dzn_detailLabelString]; + + UIImage *buttonImage = [self dzn_buttonImageForState:UIControlStateNormal]; + NSAttributedString *buttonTitle = [self dzn_buttonTitleForState:UIControlStateNormal]; + + UIImage *image = [self dzn_image]; + UIColor *imageTintColor = [self dzn_imageTintColor]; + UIImageRenderingMode renderingMode = imageTintColor ? UIImageRenderingModeAlwaysTemplate : UIImageRenderingModeAlwaysOriginal; + + view.verticalSpace = [self dzn_verticalSpace]; + + // Configure Image + if (image) { + if ([image respondsToSelector:@selector(imageWithRenderingMode:)]) { + view.imageView.image = [image imageWithRenderingMode:renderingMode]; + view.imageView.tintColor = imageTintColor; + } + else { + // iOS 6 fallback: insert code to convert imaged if needed + view.imageView.image = image; + } + } + + // Configure title label + if (titleLabelString) { + view.titleLabel.attributedText = titleLabelString; + } + + // Configure detail label + if (detailLabelString) { + view.detailLabel.attributedText = detailLabelString; + } + + // Configure button + if (buttonImage) { + [view.button setImage:buttonImage forState:UIControlStateNormal]; + [view.button setImage:[self dzn_buttonImageForState:UIControlStateHighlighted] forState:UIControlStateHighlighted]; + } + else if (buttonTitle) { + [view.button setAttributedTitle:buttonTitle forState:UIControlStateNormal]; + [view.button setAttributedTitle:[self dzn_buttonTitleForState:UIControlStateHighlighted] forState:UIControlStateHighlighted]; + [view.button setBackgroundImage:[self dzn_buttonBackgroundImageForState:UIControlStateNormal] forState:UIControlStateNormal]; + [view.button setBackgroundImage:[self dzn_buttonBackgroundImageForState:UIControlStateHighlighted] forState:UIControlStateHighlighted]; + } + } + + // Configure offset + view.verticalOffset = [self dzn_verticalOffset]; + + // Configure the empty dataset view + view.backgroundColor = [self dzn_dataSetBackgroundColor]; + view.hidden = NO; + view.clipsToBounds = YES; + + // Configure empty dataset userInteraction permission + view.userInteractionEnabled = [self dzn_isTouchAllowed]; + + // Configure empty dataset fade in display + view.fadeInOnDisplay = [self dzn_shouldFadeIn]; + + [view setupConstraints]; + + [UIView performWithoutAnimation:^{ + [view layoutIfNeeded]; + }]; + + // Configure scroll permission + self.scrollEnabled = [self dzn_isScrollAllowed]; + + // Configure image view animation + if ([self dzn_isImageViewAnimateAllowed]) + { + CAAnimation *animation = [self dzn_imageAnimation]; + + if (animation) { + [self.emptyDataSetView.imageView.layer addAnimation:animation forKey:kEmptyImageViewAnimationKey]; + } + } + else if ([self.emptyDataSetView.imageView.layer animationForKey:kEmptyImageViewAnimationKey]) { + [self.emptyDataSetView.imageView.layer removeAnimationForKey:kEmptyImageViewAnimationKey]; + } + + // Notifies that the empty dataset view did appear + [self dzn_didAppear]; + } + else if (self.isEmptyDataSetVisible) { + [self dzn_invalidate]; + } +} + +- (void)dzn_invalidate +{ + // Notifies that the empty dataset view will disappear + [self dzn_willDisappear]; + + if (self.emptyDataSetView) { + [self.emptyDataSetView prepareForReuse]; + [self.emptyDataSetView removeFromSuperview]; + + [self setEmptyDataSetView:nil]; + } + + self.scrollEnabled = YES; + + // Notifies that the empty dataset view did disappear + [self dzn_didDisappear]; +} + + +#pragma mark - Method Swizzling + +static NSMutableDictionary *_impLookupTable; +static NSString *const DZNSwizzleInfoPointerKey = @"pointer"; +static NSString *const DZNSwizzleInfoOwnerKey = @"owner"; +static NSString *const DZNSwizzleInfoSelectorKey = @"selector"; + +// Based on Bryce Buchanan's swizzling technique http://blog.newrelic.com/2014/04/16/right-way-to-swizzle/ +// And Juzzin's ideas https://github.com/juzzin/JUSEmptyViewController + +void dzn_original_implementation(id self, SEL _cmd) +{ + // Fetch original implementation from lookup table + Class baseClass = dzn_baseClassToSwizzleForTarget(self); + NSString *key = dzn_implementationKey(baseClass, _cmd); + + NSDictionary *swizzleInfo = [_impLookupTable objectForKey:key]; + NSValue *impValue = [swizzleInfo valueForKey:DZNSwizzleInfoPointerKey]; + + IMP impPointer = [impValue pointerValue]; + + // We then inject the additional implementation for reloading the empty dataset + // Doing it before calling the original implementation does update the 'isEmptyDataSetVisible' flag on time. + [self dzn_reloadEmptyDataSet]; + + // If found, call original implementation + if (impPointer) { + ((void(*)(id,SEL))impPointer)(self,_cmd); + } +} + +NSString *dzn_implementationKey(Class class, SEL selector) +{ + if (!class || !selector) { + return nil; + } + + NSString *className = NSStringFromClass([class class]); + + NSString *selectorName = NSStringFromSelector(selector); + return [NSString stringWithFormat:@"%@_%@",className,selectorName]; +} + +Class dzn_baseClassToSwizzleForTarget(id target) +{ + if ([target isKindOfClass:[UITableView class]]) { + return [UITableView class]; + } + else if ([target isKindOfClass:[UICollectionView class]]) { + return [UICollectionView class]; + } + else if ([target isKindOfClass:[UIScrollView class]]) { + return [UIScrollView class]; + } + + return nil; +} + +- (void)swizzleIfPossible:(SEL)selector +{ + // Check if the target responds to selector + if (![self respondsToSelector:selector]) { + return; + } + + // Create the lookup table + if (!_impLookupTable) { + _impLookupTable = [[NSMutableDictionary alloc] initWithCapacity:3]; // 3 represent the supported base classes + } + + // We make sure that setImplementation is called once per class kind, UITableView or UICollectionView. + for (NSDictionary *info in [_impLookupTable allValues]) { + Class class = [info objectForKey:DZNSwizzleInfoOwnerKey]; + NSString *selectorName = [info objectForKey:DZNSwizzleInfoSelectorKey]; + + if ([selectorName isEqualToString:NSStringFromSelector(selector)]) { + if ([self isKindOfClass:class]) { + return; + } + } + } + + Class baseClass = dzn_baseClassToSwizzleForTarget(self); + NSString *key = dzn_implementationKey(baseClass, selector); + NSValue *impValue = [[_impLookupTable objectForKey:key] valueForKey:DZNSwizzleInfoPointerKey]; + + // If the implementation for this class already exist, skip!! + if (impValue || !key || !baseClass) { + return; + } + + // Swizzle by injecting additional implementation + Method method = class_getInstanceMethod(baseClass, selector); + IMP dzn_newImplementation = method_setImplementation(method, (IMP)dzn_original_implementation); + + // Store the new implementation in the lookup table + NSDictionary *swizzledInfo = @{DZNSwizzleInfoOwnerKey: baseClass, + DZNSwizzleInfoSelectorKey: NSStringFromSelector(selector), + DZNSwizzleInfoPointerKey: [NSValue valueWithPointer:dzn_newImplementation]}; + + [_impLookupTable setObject:swizzledInfo forKey:key]; +} + + +#pragma mark - UIGestureRecognizerDelegate Methods + +- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer +{ + if ([gestureRecognizer.view isEqual:self.emptyDataSetView]) { + return [self dzn_isTouchAllowed]; + } + + return [super gestureRecognizerShouldBegin:gestureRecognizer]; +} + +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer +{ + UIGestureRecognizer *tapGesture = self.emptyDataSetView.tapGesture; + + if ([gestureRecognizer isEqual:tapGesture] || [otherGestureRecognizer isEqual:tapGesture]) { + return YES; + } + + // defer to emptyDataSetDelegate's implementation if available + if ( (self.emptyDataSetDelegate != (id)self) && [self.emptyDataSetDelegate respondsToSelector:@selector(gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:)]) { + return [(id)self.emptyDataSetDelegate gestureRecognizer:gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:otherGestureRecognizer]; + } + + return NO; +} + +@end + + +#pragma mark - DZNEmptyDataSetView + +@interface DZNEmptyDataSetView () +@end + +@implementation DZNEmptyDataSetView +@synthesize contentView = _contentView; +@synthesize titleLabel = _titleLabel, detailLabel = _detailLabel, imageView = _imageView, button = _button; + +#pragma mark - Initialization Methods + +- (instancetype)init +{ + self = [super init]; + if (self) { + [self addSubview:self.contentView]; + } + return self; +} + +- (void)didMoveToSuperview +{ + self.frame = self.superview.bounds; + + void(^fadeInBlock)(void) = ^{_contentView.alpha = 1.0;}; + + if (self.fadeInOnDisplay) { + [UIView animateWithDuration:0.25 + animations:fadeInBlock + completion:NULL]; + } + else { + fadeInBlock(); + } +} + + +#pragma mark - Getters + +- (UIView *)contentView +{ + if (!_contentView) + { + _contentView = [UIView new]; + _contentView.translatesAutoresizingMaskIntoConstraints = NO; + _contentView.backgroundColor = [UIColor clearColor]; + _contentView.userInteractionEnabled = YES; + _contentView.alpha = 0; + } + return _contentView; +} + +- (UIImageView *)imageView +{ + if (!_imageView) + { + _imageView = [UIImageView new]; + _imageView.translatesAutoresizingMaskIntoConstraints = NO; + _imageView.backgroundColor = [UIColor clearColor]; + _imageView.contentMode = UIViewContentModeScaleAspectFit; + _imageView.userInteractionEnabled = NO; + _imageView.accessibilityIdentifier = @"empty set background image"; + + [_contentView addSubview:_imageView]; + } + return _imageView; +} + +- (UILabel *)titleLabel +{ + if (!_titleLabel) + { + _titleLabel = [UILabel new]; + _titleLabel.translatesAutoresizingMaskIntoConstraints = NO; + _titleLabel.backgroundColor = [UIColor clearColor]; + + _titleLabel.font = [UIFont systemFontOfSize:27.0]; + _titleLabel.textColor = [UIColor colorWithWhite:0.6 alpha:1.0]; + _titleLabel.textAlignment = NSTextAlignmentCenter; + _titleLabel.lineBreakMode = NSLineBreakByWordWrapping; + _titleLabel.numberOfLines = 0; + _titleLabel.accessibilityIdentifier = @"empty set title"; + + [_contentView addSubview:_titleLabel]; + } + return _titleLabel; +} + +- (UILabel *)detailLabel +{ + if (!_detailLabel) + { + _detailLabel = [UILabel new]; + _detailLabel.translatesAutoresizingMaskIntoConstraints = NO; + _detailLabel.backgroundColor = [UIColor clearColor]; + + _detailLabel.font = [UIFont systemFontOfSize:17.0]; + _detailLabel.textColor = [UIColor colorWithWhite:0.6 alpha:1.0]; + _detailLabel.textAlignment = NSTextAlignmentCenter; + _detailLabel.lineBreakMode = NSLineBreakByWordWrapping; + _detailLabel.numberOfLines = 0; + _detailLabel.accessibilityIdentifier = @"empty set detail label"; + + [_contentView addSubview:_detailLabel]; + } + return _detailLabel; +} + +- (UIButton *)button +{ + if (!_button) + { + _button = [UIButton buttonWithType:UIButtonTypeCustom]; + _button.translatesAutoresizingMaskIntoConstraints = NO; + _button.backgroundColor = [UIColor clearColor]; + _button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter; + _button.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter; + _button.accessibilityIdentifier = @"empty set button"; + + [_button addTarget:self action:@selector(didTapButton:) forControlEvents:UIControlEventTouchUpInside]; + + [_contentView addSubview:_button]; + } + return _button; +} + +- (BOOL)canShowImage +{ + return (_imageView.image && _imageView.superview); +} + +- (BOOL)canShowTitle +{ + return (_titleLabel.attributedText.string.length > 0 && _titleLabel.superview); +} + +- (BOOL)canShowDetail +{ + return (_detailLabel.attributedText.string.length > 0 && _detailLabel.superview); +} + +- (BOOL)canShowButton +{ + if ([_button attributedTitleForState:UIControlStateNormal].string.length > 0 || [_button imageForState:UIControlStateNormal]) { + return (_button.superview != nil); + } + return NO; +} + + +#pragma mark - Setters + +- (void)setCustomView:(UIView *)view +{ + if (!view) { + return; + } + + if (_customView) { + [_customView removeFromSuperview]; + _customView = nil; + } + + _customView = view; + _customView.translatesAutoresizingMaskIntoConstraints = NO; + [self.contentView addSubview:_customView]; +} + + +#pragma mark - Action Methods + +- (void)didTapButton:(id)sender +{ + SEL selector = NSSelectorFromString(@"dzn_didTapDataButton:"); + + if ([self.superview respondsToSelector:selector]) { + [self.superview performSelector:selector withObject:sender afterDelay:0.0f]; + } +} + +- (void)removeAllConstraints +{ + [self removeConstraints:self.constraints]; + [_contentView removeConstraints:_contentView.constraints]; +} + +- (void)prepareForReuse +{ + [self.contentView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; + + _titleLabel = nil; + _detailLabel = nil; + _imageView = nil; + _button = nil; + _customView = nil; + + [self removeAllConstraints]; +} + + +#pragma mark - Auto-Layout Configuration + +- (void)setupConstraints +{ + // First, configure the content view constaints + // The content view must alway be centered to its superview + NSLayoutConstraint *centerXConstraint = [self equallyRelatedConstraintWithView:self.contentView attribute:NSLayoutAttributeCenterX]; + NSLayoutConstraint *centerYConstraint = [self equallyRelatedConstraintWithView:self.contentView attribute:NSLayoutAttributeCenterY]; + + [self addConstraint:centerXConstraint]; + [self addConstraint:centerYConstraint]; + [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[contentView]|" options:0 metrics:nil views:@{@"contentView": self.contentView}]]; + + // When a custom offset is available, we adjust the vertical constraints' constants + if (self.verticalOffset != 0 && self.constraints.count > 0) { + centerYConstraint.constant = self.verticalOffset; + } + + // If applicable, set the custom view's constraints + if (_customView) { + [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[customView]|" options:0 metrics:nil views:@{@"customView":_customView}]]; + [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[customView]|" options:0 metrics:nil views:@{@"customView":_customView}]]; + } + else { + CGFloat width = CGRectGetWidth(self.frame) ? : CGRectGetWidth([UIScreen mainScreen].bounds); + CGFloat padding = roundf(width/16.0); + CGFloat verticalSpace = self.verticalSpace ? : 11.0; // Default is 11 pts + + NSMutableArray *subviewStrings = [NSMutableArray array]; + NSMutableDictionary *views = [NSMutableDictionary dictionary]; + NSDictionary *metrics = @{@"padding": @(padding)}; + + // Assign the image view's horizontal constraints + if (_imageView.superview) { + + [subviewStrings addObject:@"imageView"]; + views[[subviewStrings lastObject]] = _imageView; + + [self.contentView addConstraint:[self.contentView equallyRelatedConstraintWithView:_imageView attribute:NSLayoutAttributeCenterX]]; + } + + // Assign the title label's horizontal constraints + if ([self canShowTitle]) { + + [subviewStrings addObject:@"titleLabel"]; + views[[subviewStrings lastObject]] = _titleLabel; + + [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(padding@750)-[titleLabel(>=0)]-(padding@750)-|" + options:0 metrics:metrics views:views]]; + } + // or removes from its superview + else { + [_titleLabel removeFromSuperview]; + _titleLabel = nil; + } + + // Assign the detail label's horizontal constraints + if ([self canShowDetail]) { + + [subviewStrings addObject:@"detailLabel"]; + views[[subviewStrings lastObject]] = _detailLabel; + + [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(padding@750)-[detailLabel(>=0)]-(padding@750)-|" + options:0 metrics:metrics views:views]]; + } + // or removes from its superview + else { + [_detailLabel removeFromSuperview]; + _detailLabel = nil; + } + + // Assign the button's horizontal constraints + if ([self canShowButton]) { + + [subviewStrings addObject:@"button"]; + views[[subviewStrings lastObject]] = _button; + + [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(padding@750)-[button(>=0)]-(padding@750)-|" + options:0 metrics:metrics views:views]]; + } + // or removes from its superview + else { + [_button removeFromSuperview]; + _button = nil; + } + + + NSMutableString *verticalFormat = [NSMutableString new]; + + // Build a dynamic string format for the vertical constraints, adding a margin between each element. Default is 11 pts. + for (int i = 0; i < subviewStrings.count; i++) { + + NSString *string = subviewStrings[i]; + [verticalFormat appendFormat:@"[%@]", string]; + + if (i < subviewStrings.count-1) { + [verticalFormat appendFormat:@"-(%.f@750)-", verticalSpace]; + } + } + + // Assign the vertical constraints to the content view + if (verticalFormat.length > 0) { + [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:[NSString stringWithFormat:@"V:|%@|", verticalFormat] + options:0 metrics:metrics views:views]]; + } + } +} + +- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event +{ + UIView *hitView = [super hitTest:point withEvent:event]; + + // Return any UIControl instance such as buttons, segmented controls, switches, etc. + if ([hitView isKindOfClass:[UIControl class]]) { + return hitView; + } + + // Return either the contentView or customView + if ([hitView isEqual:_contentView] || [hitView isEqual:_customView]) { + return hitView; + } + + return nil; +} + +@end + + +#pragma mark - UIView+DZNConstraintBasedLayoutExtensions + +@implementation UIView (DZNConstraintBasedLayoutExtensions) + +- (NSLayoutConstraint *)equallyRelatedConstraintWithView:(UIView *)view attribute:(NSLayoutAttribute)attribute +{ + return [NSLayoutConstraint constraintWithItem:view + attribute:attribute + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:attribute + multiplier:1.0 + constant:0.0]; +} + +@end + +#pragma mark - DZNWeakObjectContainer + +@implementation DZNWeakObjectContainer + +- (instancetype)initWithWeakObject:(id)object +{ + self = [super init]; + if (self) { + _weakObject = object; + } + return self; +} + +@end diff --git a/Pods/LookinServer/LICENSE b/Pods/LookinServer/LICENSE new file mode 100644 index 0000000..eeb2b2b --- /dev/null +++ b/Pods/LookinServer/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) [2023] [LI KAI] + +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. \ No newline at end of file diff --git a/Pods/LookinServer/README.md b/Pods/LookinServer/README.md new file mode 100644 index 0000000..548ceff --- /dev/null +++ b/Pods/LookinServer/README.md @@ -0,0 +1,73 @@ +![Preview](https://cdn.lookin.work/public/style/images/independent/homepage/preview_en_1x.jpg "Preview") + +# Introduction +You can inspect and modify views in iOS app via Lookin, just like UI Inspector in Xcode, or another app called Reveal. + +Official Website:https://lookin.work/ + +# Integration Guide +To use Lookin macOS app, you need to integrate LookinServer (iOS Framework of Lookin) into your iOS project. + +> **Warning** +> 1. Never integrate LookinServer in Release building configuration. +> 2. Do not use versions earlier than 1.0.6, as it contains a critical bug that could lead to online incidents in your project: https://qxh1ndiez2w.feishu.cn/wiki/Z9SpwT7zWiqvYvkBe7Lc6Disnab + +## via CocoaPods: +### Swift Project +`pod 'LookinServer', :subspecs => ['Swift'], :configurations => ['Debug']` +### Objective-C Project +`pod 'LookinServer', :configurations => ['Debug']` +## via Swift Package Manager: +`https://github.com/QMUI/LookinServer/` + +# Repository +LookinServer: https://github.com/QMUI/LookinServer + +macOS app: https://github.com/hughkli/Lookin/ + +# Tips +- How to display custom information in Lookin: https://bytedance.larkoffice.com/docx/TRridRXeUoErMTxs94bcnGchnlb +- How to display more member variables in Lookin: https://bytedance.larkoffice.com/docx/CKRndHqdeoub11xSqUZcMlFhnWe +- How to turn on Swift optimization for Lookin: https://bytedance.larkoffice.com/docx/GFRLdzpeKoakeyxvwgCcZ5XdnTb +- Documentation Collection: https://bytedance.larkoffice.com/docx/Yvv1d57XQoe5l0xZ0ZRc0ILfnWb + +# Acknowledgements +https://qxh1ndiez2w.feishu.cn/docx/YIFjdE4gIolp3hxn1tGckiBxnWf + +--- +# 简介 +Lookin 可以查看与修改 iOS App 里的 UI 对象,类似于 Xcode 自带的 UI Inspector 工具,或另一款叫做 Reveal 的软件。 + +官网:https://lookin.work/ + +# 安装 LookinServer Framework +如果这是你的 iOS 项目第一次使用 Lookin,则需要先把 LookinServer 这款 iOS Framework 集成到你的 iOS 项目中。 + +> **Warning** +> +> 1. 不要在 AppStore 模式下集成 LookinServer。 +> 2. 不要使用早于 1.0.6 的版本,因为它包含一个严重 Bug,可能导致线上事故: https://qxh1ndiez2w.feishu.cn/wiki/Z9SpwT7zWiqvYvkBe7Lc6Disnab +## 通过 CocoaPods: + +### Swift 项目 +`pod 'LookinServer', :subspecs => ['Swift'], :configurations => ['Debug']` +### Objective-C 项目 +`pod 'LookinServer', :configurations => ['Debug']` + +## 通过 Swift Package Manager: +`https://github.com/QMUI/LookinServer/` + +# 源代码仓库 + +iOS 端 LookinServer:https://github.com/QMUI/LookinServer + +macOS 端软件:https://github.com/hughkli/Lookin/ + +# 技巧 +- 如何在 Lookin 中展示自定义信息: https://bytedance.larkoffice.com/docx/TRridRXeUoErMTxs94bcnGchnlb +- 如何在 Lookin 中展示更多成员变量: https://bytedance.larkoffice.com/docx/CKRndHqdeoub11xSqUZcMlFhnWe +- 如何为 Lookin 开启 Swift 优化: https://bytedance.larkoffice.com/docx/GFRLdzpeKoakeyxvwgCcZ5XdnTb +- 文档汇总:https://bytedance.larkoffice.com/docx/Yvv1d57XQoe5l0xZ0ZRc0ILfnWb + +# 鸣谢 +https://qxh1ndiez2w.feishu.cn/docx/YIFjdE4gIolp3hxn1tGckiBxnWf diff --git a/Pods/LookinServer/Src/Base/LookinIvarTrace.h b/Pods/LookinServer/Src/Base/LookinIvarTrace.h new file mode 100644 index 0000000..3904385 --- /dev/null +++ b/Pods/LookinServer/Src/Base/LookinIvarTrace.h @@ -0,0 +1,40 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinIvarTrace.h +// Lookin +// +// Created by Li Kai on 2019/4/30. +// https://lookin.work +// + +#import + +extern NSString *const LookinIvarTraceRelationValue_Self; + +/// 如果 hostClassName 和 ivarName 均 equal,则认为两个 LookinIvarTrace 对象彼此 equal +/// 比如 A 是 B 的 superview,且 A 的 "_stageView" 指向 B,则 B 会有一个 LookinIvarTrace:hostType 为 “superview”,hostClassName 为 A 的 class,ivarName 为 “_stageView” +@interface LookinIvarTrace : NSObject + +/// 该值可能是 "superview"、"superlayer"、“self” 或 nil +@property(nonatomic, copy) NSString *relation; + +@property(nonatomic, copy) NSString *hostClassName; + +@property(nonatomic, copy) NSString *ivarName; + +#pragma mark - No Coding + +#if TARGET_OS_IPHONE +@property(nonatomic, weak) id hostObject; +#endif + +@end + +@interface NSObject (LookinServerTrace) + +@property(nonatomic, copy) NSArray *lks_ivarTraces; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Base/LookinIvarTrace.m b/Pods/LookinServer/Src/Base/LookinIvarTrace.m new file mode 100644 index 0000000..e272d47 --- /dev/null +++ b/Pods/LookinServer/Src/Base/LookinIvarTrace.m @@ -0,0 +1,70 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinIvarTrace.m +// Lookin +// +// Created by Li Kai on 2019/4/30. +// https://lookin.work +// + +#import "LookinIvarTrace.h" + +NSString *const LookinIvarTraceRelationValue_Self = @"self"; + +@implementation LookinIvarTrace + +#pragma mark - Equal + +- (NSUInteger)hash { + return self.hostClassName.hash ^ self.ivarName.hash; +} + +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[LookinIvarTrace class]]) { + return NO; + } + LookinIvarTrace *comparedObj = object; + if ([self.hostClassName isEqualToString:comparedObj.hostClassName] && [self.ivarName isEqualToString:comparedObj.ivarName]) { + return YES; + } + return NO; +} + +#pragma mark - + +- (id)copyWithZone:(NSZone *)zone { + LookinIvarTrace *newTrace = [[LookinIvarTrace allocWithZone:zone] init]; + newTrace.relation = self.relation; + newTrace.hostClassName = self.hostClassName; + newTrace.ivarName = self.ivarName; + return newTrace; +} + +#pragma mark - + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:self.relation forKey:@"relation"]; + [aCoder encodeObject:self.hostClassName forKey:@"hostClassName"]; + [aCoder encodeObject:self.ivarName forKey:@"ivarName"]; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if (self = [super init]) { + self.relation = [aDecoder decodeObjectForKey:@"relation"]; + self.hostClassName = [aDecoder decodeObjectForKey:@"hostClassName"]; + self.ivarName = [aDecoder decodeObjectForKey:@"ivarName"]; + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Category/CALayer+LookinServer.h b/Pods/LookinServer/Src/Main/Server/Category/CALayer+LookinServer.h new file mode 100644 index 0000000..83584a9 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Category/CALayer+LookinServer.h @@ -0,0 +1,41 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// UIView+LookinMobile.h +// WeRead +// +// Created by Li Kai on 2018/11/30. +// Copyright © 2018 tencent. All rights reserved. +// + +#import "LookinDefines.h" +#import "TargetConditionals.h" +#import + +@interface CALayer (LookinServer) + +/// 如果 myView.layer == myLayer,则 myLayer.lks_hostView 会返回 myView +@property(nonatomic, readonly, weak) UIView *lks_hostView; + +- (UIWindow *)lks_window; + +- (CGRect)lks_frameInWindow:(UIWindow *)window; + +- (UIImage *)lks_groupScreenshotWithLowQuality:(BOOL)lowQuality; +/// 当没有 sublayers 时,该方法返回 nil +- (UIImage *)lks_soloScreenshotWithLowQuality:(BOOL)lowQuality; + +/// 获取和该对象有关的对象的 Class 层级树 +- (NSArray *> *)lks_relatedClassChainList; + +- (NSArray *)lks_selfRelation; + +@property(nonatomic, strong) UIColor *lks_backgroundColor; +@property(nonatomic, strong) UIColor *lks_borderColor; +@property(nonatomic, strong) UIColor *lks_shadowColor; +@property(nonatomic, assign) CGFloat lks_shadowOffsetWidth; +@property(nonatomic, assign) CGFloat lks_shadowOffsetHeight; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Category/CALayer+LookinServer.m b/Pods/LookinServer/Src/Main/Server/Category/CALayer+LookinServer.m new file mode 100644 index 0000000..233734d --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Category/CALayer+LookinServer.m @@ -0,0 +1,233 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// UIView+LookinMobile.m +// WeRead +// +// Created by Li Kai on 2018/11/30. +// Copyright © 2018 tencent. All rights reserved. +// + +#import "CALayer+LookinServer.h" +#import "LKS_HierarchyDisplayItemsMaker.h" +#import "LookinDisplayItem.h" +#import +#import "LKS_ConnectionManager.h" +#import "LookinIvarTrace.h" +#import "LookinServerDefines.h" +#import "UIColor+LookinServer.h" +#import "LKS_MultiplatformAdapter.h" + +@implementation CALayer (LookinServer) + +- (UIWindow *)lks_window { + CALayer *layer = self; + while (layer) { + UIView *hostView = layer.lks_hostView; + if (hostView.window) { + return hostView.window; + } else if ([hostView isKindOfClass:[UIWindow class]]) { + return (UIWindow *)hostView; + } + layer = layer.superlayer; + } + return nil; +} + +- (CGRect)lks_frameInWindow:(UIWindow *)window { + UIWindow *selfWindow = [self lks_window]; + if (!selfWindow) { + return CGRectZero; + } + + CGRect rectInSelfWindow = [selfWindow.layer convertRect:self.frame fromLayer:self.superlayer]; + CGRect rectInWindow = [window convertRect:rectInSelfWindow fromWindow:selfWindow]; + return rectInWindow; +} + +#pragma mark - Host View + +- (UIView *)lks_hostView { + if (self.delegate && [self.delegate isKindOfClass:UIView.class]) { + UIView *view = (UIView *)self.delegate; + if (view.layer == self) { + return view; + } + } + return nil; +} + +#pragma mark - Screenshot + +- (UIImage *)lks_groupScreenshotWithLowQuality:(BOOL)lowQuality { + + CGFloat screenScale = [LKS_MultiplatformAdapter mainScreenScale]; + CGFloat pixelWidth = self.frame.size.width * screenScale; + CGFloat pixelHeight = self.frame.size.height * screenScale; + if (pixelWidth <= 0 || pixelHeight <= 0) { + return nil; + } + + CGFloat renderScale = lowQuality ? 1 : 0; + CGFloat maxLength = MAX(pixelWidth, pixelHeight); + if (maxLength > LookinNodeImageMaxLengthInPx) { + // 确保最终绘制出的图片长和宽都不能超过 LookinNodeImageMaxLengthInPx + // 如果算出的 renderScale 大于 1 则取 1,因为似乎用 1 渲染的速度要比一个别的奇怪的带小数点的数字要更快 + renderScale = MIN(screenScale * LookinNodeImageMaxLengthInPx / maxLength, 1); + } + + CGSize contextSize = self.frame.size; + if (contextSize.width <= 0 || contextSize.height <= 0 || contextSize.width > 20000 || contextSize.height > 20000) { + NSLog(@"LookinServer - Failed to capture screenshot. Invalid context size: %@ x %@", @(contextSize.width), @(contextSize.height)); + return nil; + } + UIGraphicsBeginImageContextWithOptions(contextSize, NO, renderScale); + CGContextRef context = UIGraphicsGetCurrentContext(); + if (self.lks_hostView && !self.lks_hostView.lks_isChildrenViewOfTabBar) { + [self.lks_hostView drawViewHierarchyInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height) afterScreenUpdates:YES]; + } else { + [self renderInContext:context]; + } + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return image; +} + +- (UIImage *)lks_soloScreenshotWithLowQuality:(BOOL)lowQuality { + if (!self.sublayers.count) { + return nil; + } + + CGFloat screenScale = [LKS_MultiplatformAdapter mainScreenScale]; + CGFloat pixelWidth = self.frame.size.width * screenScale; + CGFloat pixelHeight = self.frame.size.height * screenScale; + if (pixelWidth <= 0 || pixelHeight <= 0) { + return nil; + } + + CGFloat renderScale = lowQuality ? 1 : 0; + CGFloat maxLength = MAX(pixelWidth, pixelHeight); + if (maxLength > LookinNodeImageMaxLengthInPx) { + // 确保最终绘制出的图片长和宽都不能超过 LookinNodeImageMaxLengthInPx + // 如果算出的 renderScale 大于 1 则取 1,因为似乎用 1 渲染的速度要比一个别的奇怪的带小数点的数字要更快 + renderScale = MIN(screenScale * LookinNodeImageMaxLengthInPx / maxLength, 1); + } + + if (self.sublayers.count) { + NSArray *sublayers = [self.sublayers copy]; + NSMutableArray *visibleSublayers = [NSMutableArray arrayWithCapacity:sublayers.count]; + [sublayers enumerateObjectsUsingBlock:^(__kindof CALayer * _Nonnull sublayer, NSUInteger idx, BOOL * _Nonnull stop) { + if (!sublayer.hidden) { + sublayer.hidden = YES; + [visibleSublayers addObject:sublayer]; + } + }]; + + CGSize contextSize = self.frame.size; + if (contextSize.width <= 0 || contextSize.height <= 0 || contextSize.width > 20000 || contextSize.height > 20000) { + NSLog(@"LookinServer - Failed to capture screenshot. Invalid context size: %@ x %@", @(contextSize.width), @(contextSize.height)); + return nil; + } + + UIGraphicsBeginImageContextWithOptions(contextSize, NO, renderScale); + CGContextRef context = UIGraphicsGetCurrentContext(); + if (self.lks_hostView && !self.lks_hostView.lks_isChildrenViewOfTabBar) { + [self.lks_hostView drawViewHierarchyInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height) afterScreenUpdates:YES]; + } else { + [self renderInContext:context]; + } + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + [visibleSublayers enumerateObjectsUsingBlock:^(CALayer * _Nonnull sublayer, NSUInteger idx, BOOL * _Nonnull stop) { + sublayer.hidden = NO; + }]; + + return image; + } + return nil; +} + +- (NSArray *> *)lks_relatedClassChainList { + NSMutableArray *array = [NSMutableArray arrayWithCapacity:2]; + if (self.lks_hostView) { + [array addObject:[CALayer lks_getClassListOfObject:self.lks_hostView endingClass:@"UIView"]]; + UIViewController* vc = [self.lks_hostView lks_findHostViewController]; + if (vc) { + [array addObject:[CALayer lks_getClassListOfObject:vc endingClass:@"UIViewController"]]; + } + } else { + [array addObject:[CALayer lks_getClassListOfObject:self endingClass:@"CALayer"]]; + } + return array.copy; +} + ++ (NSArray *)lks_getClassListOfObject:(id)object endingClass:(NSString *)endingClass { + NSArray *completedList = [object lks_classChainList]; + NSUInteger endingIdx = [completedList indexOfObject:endingClass]; + if (endingIdx != NSNotFound) { + completedList = [completedList subarrayWithRange:NSMakeRange(0, endingIdx + 1)]; + } + return completedList; +} + +- (NSArray *)lks_selfRelation { + NSMutableArray *array = [NSMutableArray array]; + NSMutableArray *ivarTraces = [NSMutableArray array]; + if (self.lks_hostView) { + UIViewController* vc = [self.lks_hostView lks_findHostViewController]; + if (vc) { + [array addObject:[NSString stringWithFormat:@"(%@ *).view", NSStringFromClass(vc.class)]]; + + [ivarTraces addObjectsFromArray:vc.lks_ivarTraces]; + } + [ivarTraces addObjectsFromArray:self.lks_hostView.lks_ivarTraces]; + } else { + [ivarTraces addObjectsFromArray:self.lks_ivarTraces]; + } + if (ivarTraces.count) { + [array addObjectsFromArray:[ivarTraces lookin_map:^id(NSUInteger idx, LookinIvarTrace *value) { + return [NSString stringWithFormat:@"(%@ *) -> %@", value.hostClassName, value.ivarName]; + }]]; + } + return array.count ? array.copy : nil; +} + +- (UIColor *)lks_backgroundColor { + return [UIColor lks_colorWithCGColor:self.backgroundColor]; +} +- (void)setLks_backgroundColor:(UIColor *)lks_backgroundColor { + self.backgroundColor = lks_backgroundColor.CGColor; +} + +- (UIColor *)lks_borderColor { + return [UIColor lks_colorWithCGColor:self.borderColor]; +} +- (void)setLks_borderColor:(UIColor *)lks_borderColor { + self.borderColor = lks_borderColor.CGColor; +} + +- (UIColor *)lks_shadowColor { + return [UIColor lks_colorWithCGColor:self.shadowColor]; +} +- (void)setLks_shadowColor:(UIColor *)lks_shadowColor { + self.shadowColor = lks_shadowColor.CGColor; +} + +- (CGFloat)lks_shadowOffsetWidth { + return self.shadowOffset.width; +} +- (void)setLks_shadowOffsetWidth:(CGFloat)lks_shadowOffsetWidth { + self.shadowOffset = CGSizeMake(lks_shadowOffsetWidth, self.shadowOffset.height); +} + +- (CGFloat)lks_shadowOffsetHeight { + return self.shadowOffset.height; +} +- (void)setLks_shadowOffsetHeight:(CGFloat)lks_shadowOffsetHeight { + self.shadowOffset = CGSizeMake(self.shadowOffset.width, lks_shadowOffsetHeight); +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Category/NSObject+LookinServer.h b/Pods/LookinServer/Src/Main/Server/Category/NSObject+LookinServer.h new file mode 100644 index 0000000..94d40f5 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Category/NSObject+LookinServer.h @@ -0,0 +1,41 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// NSObject+LookinServer.h +// LookinServer +// +// Created by Li Kai on 2019/4/21. +// https://lookin.work +// + +#import "LookinDefines.h" +#import + +@class LookinIvarTrace; + +@interface NSObject (LookinServer) + +#pragma mark - oid + +/// 如果 oid 不存在则会创建新的 oid +- (unsigned long)lks_registerOid; + +/// 0 表示不存在 +@property(nonatomic, assign) unsigned long lks_oid; + ++ (NSObject *)lks_objectWithOid:(unsigned long)oid; + +#pragma mark - trace + +@property(nonatomic, copy) NSString *lks_specialTrace; + ++ (void)lks_clearAllObjectsTraces; + +/** + 获取当前对象的 Class 层级树,如 @[@"UIView", @"UIResponder", @"NSObject"]。未 demangle,有 Swift Module Name + */ +- (NSArray *)lks_classChainList; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Category/NSObject+LookinServer.m b/Pods/LookinServer/Src/Main/Server/Category/NSObject+LookinServer.m new file mode 100644 index 0000000..c8e170b --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Category/NSObject+LookinServer.m @@ -0,0 +1,99 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// NSObject+LookinServer.m +// LookinServer +// +// Created by Li Kai on 2019/4/21. +// https://lookin.work +// + +#import "NSObject+Lookin.h" +#import "NSObject+LookinServer.h" +#import "LookinServerDefines.h" +#import "LKS_ObjectRegistry.h" +#import + +@implementation NSObject (LookinServer) + +#pragma mark - oid + +- (unsigned long)lks_registerOid { + if (!self.lks_oid) { + unsigned long oid = [[LKS_ObjectRegistry sharedInstance] addObject:self]; + self.lks_oid = oid; + } + return self.lks_oid; +} + +- (void)setLks_oid:(unsigned long)lks_oid { + [self lookin_bindObject:@(lks_oid) forKey:@"lks_oid"]; +} + +- (unsigned long)lks_oid { + NSNumber *number = [self lookin_getBindObjectForKey:@"lks_oid"]; + return [number unsignedLongValue]; +} + ++ (NSObject *)lks_objectWithOid:(unsigned long)oid { + return [[LKS_ObjectRegistry sharedInstance] objectWithOid:oid]; +} + +#pragma mark - trace + +- (void)setLks_ivarTraces:(NSArray *)lks_ivarTraces { + [self lookin_bindObject:lks_ivarTraces.copy forKey:@"lks_ivarTraces"]; + + if (lks_ivarTraces) { + [[NSObject lks_allObjectsWithTraces] addPointer:(void *)self]; + } +} + +- (NSArray *)lks_ivarTraces { + return [self lookin_getBindObjectForKey:@"lks_ivarTraces"]; +} + +- (void)setLks_specialTrace:(NSString *)lks_specialTrace { + [self lookin_bindObject:lks_specialTrace forKey:@"lks_specialTrace"]; + if (lks_specialTrace) { + [[NSObject lks_allObjectsWithTraces] addPointer:(void *)self]; + } +} +- (NSString *)lks_specialTrace { + return [self lookin_getBindObjectForKey:@"lks_specialTrace"]; +} + ++ (void)lks_clearAllObjectsTraces { + [[[NSObject lks_allObjectsWithTraces] allObjects] enumerateObjectsUsingBlock:^(NSObject * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + obj.lks_ivarTraces = nil; + obj.lks_specialTrace = nil; + }]; + [NSObject lks_allObjectsWithTraces].count = 0; +} + ++ (NSPointerArray *)lks_allObjectsWithTraces { + static dispatch_once_t onceToken; + static NSPointerArray *lks_allObjectsWithTraces = nil; + dispatch_once(&onceToken,^{ + lks_allObjectsWithTraces = [NSPointerArray weakObjectsPointerArray]; + }); + return lks_allObjectsWithTraces; +} + +- (NSArray *)lks_classChainList { + NSMutableArray *classChainList = [NSMutableArray array]; + Class currentClass = self.class; + + while (currentClass) { + NSString *currentClassName = NSStringFromClass(currentClass); + if (currentClassName) { + [classChainList addObject:currentClassName]; + } + currentClass = [currentClass superclass]; + } + return classChainList.copy; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Category/UIBlurEffect+LookinServer.h b/Pods/LookinServer/Src/Main/Server/Category/UIBlurEffect+LookinServer.h new file mode 100644 index 0000000..1623a8d --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Category/UIBlurEffect+LookinServer.h @@ -0,0 +1,21 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// UIBlurEffect+LookinServer.h +// LookinServer +// +// Created by Li Kai on 2019/10/8. +// https://lookin.work +// + +#import + +@interface UIBlurEffect (LookinServer) + +/// 该 number 包装的对象是 UIBlurEffectStyle,之所以用 NSNumber 是因为想把 0 和 nil 区分开,毕竟这里是在 hook 系统,稳一点好。 +/// 该方法的实现需要 Hook,因此若定义了 LOOKIN_SERVER_DISABLE_HOOK 宏,则属性会返回 nil +@property(nonatomic, strong) NSNumber *lks_effectStyleNumber; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Category/UIBlurEffect+LookinServer.m b/Pods/LookinServer/Src/Main/Server/Category/UIBlurEffect+LookinServer.m new file mode 100644 index 0000000..ddc36ac --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Category/UIBlurEffect+LookinServer.m @@ -0,0 +1,57 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// UIBlurEffect+LookinServer.m +// LookinServer +// +// Created by Li Kai on 2019/10/8. +// https://lookin.work +// + +#import "UIBlurEffect+LookinServer.h" +#import "NSObject+Lookin.h" +#import + +@implementation UIBlurEffect (LookinServer) + +#ifdef LOOKIN_SERVER_DISABLE_HOOK + +- (void)setLks_effectStyleNumber:(NSNumber *)lks_effectStyleNumber { +} + +- (NSNumber *)lks_effectStyleNumber { + return nil; +} + +#else + ++ (void)load { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + Method oriMethod = class_getClassMethod([self class], @selector(effectWithStyle:)); + Method newMethod = class_getClassMethod([self class], @selector(lks_effectWithStyle:)); + method_exchangeImplementations(oriMethod, newMethod); + }); +} + ++ (UIBlurEffect *)lks_effectWithStyle:(UIBlurEffectStyle)style { + id effect = [self lks_effectWithStyle:style]; + if ([effect respondsToSelector:@selector(setLks_effectStyleNumber:)]) { + [effect setLks_effectStyleNumber:@(style)]; + } + return effect; +} + +- (void)setLks_effectStyleNumber:(NSNumber *)lks_effectStyleNumber { + [self lookin_bindObject:lks_effectStyleNumber forKey:@"lks_effectStyleNumber"]; +} + +- (NSNumber *)lks_effectStyleNumber { + return [self lookin_getBindObjectForKey:@"lks_effectStyleNumber"]; +} + +#endif /* LOOKIN_SERVER_DISABLE_HOOK */ + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Category/UIColor+LookinServer.h b/Pods/LookinServer/Src/Main/Server/Category/UIColor+LookinServer.h new file mode 100644 index 0000000..9b4133f --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Category/UIColor+LookinServer.h @@ -0,0 +1,26 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// UIColor+LookinServer.h +// LookinServer +// +// Created by Li Kai on 2019/6/5. +// https://lookin.work +// + +#import + +@interface UIColor (LookinServer) + +- (NSArray *)lks_rgbaComponents; ++ (instancetype)lks_colorFromRGBAComponents:(NSArray *)components; + +- (NSString *)lks_rgbaString; +- (NSString *)lks_hexString; + +/// will check if the argument is a real CGColor ++ (UIColor *)lks_colorWithCGColor:(CGColorRef)cgColor; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Category/UIColor+LookinServer.m b/Pods/LookinServer/Src/Main/Server/Category/UIColor+LookinServer.m new file mode 100644 index 0000000..ce1aea9 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Category/UIColor+LookinServer.m @@ -0,0 +1,183 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// UIColor+LookinServer.m +// LookinServer +// +// Created by Li Kai on 2019/6/5. +// https://lookin.work +// + +#import "UIColor+LookinServer.h" + +@implementation UIColor (LookinServer) + +- (NSArray *)lks_rgbaComponents { + CGFloat r, g, b, a; + CGColorRef cgColor = [self CGColor]; + const CGFloat *components = CGColorGetComponents(cgColor); + if (CGColorGetNumberOfComponents(cgColor) == 4) { + r = components[0]; + g = components[1]; + b = components[2]; + a = components[3]; + } else if (CGColorGetNumberOfComponents(cgColor) == 2) { + r = components[0]; + g = components[0]; + b = components[0]; + a = components[1]; + } else if (CGColorGetNumberOfComponents(cgColor) == 1) { + r = components[0]; + g = components[0]; + b = components[0]; + a = components[0]; + } else { + r = 0; + g = 0; + b = 0; + a = 0; + NSAssert(NO, @""); + } + NSArray *rgba = @[@(r), @(g), @(b), @(a)]; + return rgba; +} + ++ (instancetype)lks_colorFromRGBAComponents:(NSArray *)components { + if (!components) { + return nil; + } + if (components.count != 4) { + NSAssert(NO, @""); + return nil; + } + UIColor *color = [UIColor colorWithRed:components[0].doubleValue green:components[1].doubleValue blue:components[2].doubleValue alpha:components[3].doubleValue]; + return color; +} + +- (NSString *)lks_rgbaString { + CGFloat r, g, b, a; + CGColorRef cgColor = [self CGColor]; + const CGFloat *components = CGColorGetComponents(cgColor); + if (CGColorGetNumberOfComponents(cgColor) == 4) { + r = components[0]; + g = components[1]; + b = components[2]; + a = components[3]; + } else if (CGColorGetNumberOfComponents(cgColor) == 2) { + r = components[0]; + g = components[0]; + b = components[0]; + a = components[1]; + } else { + r = 0; + g = 0; + b = 0; + a = 0; + NSAssert(NO, @""); + } + + if (a >= 1) { + return [NSString stringWithFormat:@"(%.0f, %.0f, %.0f)", r * 255, g * 255, b * 255]; + } else { + return [NSString stringWithFormat:@"(%.0f, %.0f, %.0f, %.2f)", r * 255, g * 255, b * 255, a]; + } +} + +- (NSString *)lks_hexString { + CGFloat r, g, b, a; + CGColorRef cgColor = [self CGColor]; + const CGFloat *components = CGColorGetComponents(cgColor); + if (CGColorGetNumberOfComponents(cgColor) == 4) { + r = components[0]; + g = components[1]; + b = components[2]; + a = components[3]; + } else if (CGColorGetNumberOfComponents(cgColor) == 2) { + r = components[0]; + g = components[0]; + b = components[0]; + a = components[1]; + } else { + r = 0; + g = 0; + b = 0; + a = 0; + NSAssert(NO, @""); + } + + NSInteger red = r * 255; + NSInteger green = g * 255; + NSInteger blue = b * 255; + NSInteger alpha = a * 255; + + return [[NSString stringWithFormat:@"#%@%@%@%@", + [UIColor _alignColorHexStringLength:[UIColor _hexStringWithInteger:alpha]], + [UIColor _alignColorHexStringLength:[UIColor _hexStringWithInteger:red]], + [UIColor _alignColorHexStringLength:[UIColor _hexStringWithInteger:green]], + [UIColor _alignColorHexStringLength:[UIColor _hexStringWithInteger:blue]]] lowercaseString]; +} + +// 对于色值只有单位数的,在前面补一个0,例如“F”会补齐为“0F” ++ (NSString *)_alignColorHexStringLength:(NSString *)hexString { + return hexString.length < 2 ? [@"0" stringByAppendingString:hexString] : hexString; +} + ++ (NSString *)_hexStringWithInteger:(NSInteger)integer { + NSString *hexString = @""; + NSInteger remainder = 0; + for (NSInteger i = 0; i < 9; i++) { + remainder = integer % 16; + integer = integer / 16; + NSString *letter = [self _hexLetterStringWithInteger:remainder]; + hexString = [letter stringByAppendingString:hexString]; + if (integer == 0) { + break; + } + + } + return hexString; +} + ++ (NSString *)_hexLetterStringWithInteger:(NSInteger)integer { + NSAssert(integer < 16, @"要转换的数必须是16进制里的个位数,也即小于16,但你传给我是%@", @(integer)); + + NSString *letter = nil; + switch (integer) { + case 10: + letter = @"A"; + break; + case 11: + letter = @"B"; + break; + case 12: + letter = @"C"; + break; + case 13: + letter = @"D"; + break; + case 14: + letter = @"E"; + break; + case 15: + letter = @"F"; + break; + default: + letter = [[NSString alloc]initWithFormat:@"%@", @(integer)]; + break; + } + return letter; +} + ++ (UIColor *)lks_colorWithCGColor:(CGColorRef)cgColor { + if (!cgColor) { + return nil; + } + if (CFGetTypeID(cgColor) != CGColorGetTypeID()) { + return nil; + } + return [UIColor colorWithCGColor:cgColor]; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Category/UIImage+LookinServer.h b/Pods/LookinServer/Src/Main/Server/Category/UIImage+LookinServer.h new file mode 100644 index 0000000..cf7f6ff --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Category/UIImage+LookinServer.h @@ -0,0 +1,22 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// UIImage+LookinServer.h +// LookinServer +// +// Created by Li Kai on 2019/5/14. +// https://lookin.work +// + +#import + +@interface UIImage (LookinServer) + +/// 该方法的实现需要 Hook,因此若定义了 LOOKIN_SERVER_DISABLE_HOOK 宏,则属性会返回 nil +@property(nonatomic, copy) NSString *lks_imageSourceName; + +- (NSData *)lookin_data; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Category/UIImage+LookinServer.m b/Pods/LookinServer/Src/Main/Server/Category/UIImage+LookinServer.m new file mode 100644 index 0000000..97f8264 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Category/UIImage+LookinServer.m @@ -0,0 +1,95 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// UIImage+LookinServer.m +// LookinServer +// +// Created by Li Kai on 2019/5/14. +// https://lookin.work +// + +#import +#import "UIImage+LookinServer.h" +#import "LookinServerDefines.h" + +@implementation UIImage (LookinServer) + +#ifdef LOOKIN_SERVER_DISABLE_HOOK + +- (void)setLks_imageSourceName:(NSString *)lks_imageSourceName { +} + +- (NSString *)lks_imageSourceName { + return nil; +} + +#else + ++ (void)load { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + Method oriMethod = class_getClassMethod([self class], @selector(imageNamed:)); + Method newMethod = class_getClassMethod([self class], @selector(lks_imageNamed:)); + method_exchangeImplementations(oriMethod, newMethod); + + oriMethod = class_getClassMethod([self class], @selector(imageWithContentsOfFile:)); + newMethod = class_getClassMethod([self class], @selector(lks_imageWithContentsOfFile:)); + method_exchangeImplementations(oriMethod, newMethod); + + oriMethod = class_getClassMethod([self class], @selector(imageNamed:inBundle:compatibleWithTraitCollection:)); + newMethod = class_getClassMethod([self class], @selector(lks_imageNamed:inBundle:compatibleWithTraitCollection:)); + method_exchangeImplementations(oriMethod, newMethod); + + if (@available(iOS 13.0, tvOS 13.0, watchOS 6.0, *)) { + oriMethod = class_getClassMethod([self class], @selector(imageNamed:inBundle:withConfiguration:)); + newMethod = class_getClassMethod([self class], @selector(lks_imageNamed:inBundle:withConfiguration:)); + method_exchangeImplementations(oriMethod, newMethod); + } + }); +} + ++ (nullable UIImage *)lks_imageNamed:(NSString *)name inBundle:(nullable NSBundle *)bundle withConfiguration:(nullable UIImageConfiguration *)configuration API_AVAILABLE(ios(13.0),tvos(13.0),watchos(6.0)) +{ + UIImage *image = [self lks_imageNamed:name inBundle:bundle withConfiguration:configuration]; + image.lks_imageSourceName = name; + return image; +} + ++ (nullable UIImage *)lks_imageNamed:(NSString *)name inBundle:(nullable NSBundle *)bundle compatibleWithTraitCollection:(nullable UITraitCollection *)traitCollection API_AVAILABLE(ios(8.0)) +{ + UIImage *image = [self lks_imageNamed:name inBundle:bundle compatibleWithTraitCollection:traitCollection]; + image.lks_imageSourceName = name; + return image; +} + ++ (UIImage *)lks_imageNamed:(NSString *)name { + UIImage *image = [self lks_imageNamed:name]; + image.lks_imageSourceName = name; + return image; +} + ++ (UIImage *)lks_imageWithContentsOfFile:(NSString *)path { + UIImage *image = [self lks_imageWithContentsOfFile:path]; + + NSString *fileName = [[path componentsSeparatedByString:@"/"].lastObject componentsSeparatedByString:@"."].firstObject; + image.lks_imageSourceName = fileName; + return image; +} + +- (void)setLks_imageSourceName:(NSString *)lks_imageSourceName { + [self lookin_bindObject:lks_imageSourceName.copy forKey:@"lks_imageSourceName"]; +} + +- (NSString *)lks_imageSourceName { + return [self lookin_getBindObjectForKey:@"lks_imageSourceName"]; +} + +#endif /* LOOKIN_SERVER_DISABLE_HOOK */ + +- (NSData *)lookin_data { + return UIImagePNGRepresentation(self); +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Category/UIImageView+LookinServer.h b/Pods/LookinServer/Src/Main/Server/Category/UIImageView+LookinServer.h new file mode 100644 index 0000000..6da9028 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Category/UIImageView+LookinServer.h @@ -0,0 +1,20 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// UIImageView+LookinServer.h +// LookinServer +// +// Created by Li Kai on 2019/9/18. +// https://lookin.work +// + +#import + +@interface UIImageView (LookinServer) + +- (NSString *)lks_imageSourceName; +- (NSNumber *)lks_imageViewOidIfHasImage; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Category/UIImageView+LookinServer.m b/Pods/LookinServer/Src/Main/Server/Category/UIImageView+LookinServer.m new file mode 100644 index 0000000..76e83cf --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Category/UIImageView+LookinServer.m @@ -0,0 +1,31 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// UIImageView+LookinServer.m +// LookinServer +// +// Created by Li Kai on 2019/9/18. +// https://lookin.work +// + +#import "UIImageView+LookinServer.h" +#import "UIImage+LookinServer.h" +#import "NSObject+LookinServer.h" + +@implementation UIImageView (LookinServer) + +- (NSString *)lks_imageSourceName { + return self.image.lks_imageSourceName; +} + +- (NSNumber *)lks_imageViewOidIfHasImage { + if (!self.image) { + return nil; + } + unsigned long oid = [self lks_registerOid]; + return @(oid); +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Category/UILabel+LookinServer.h b/Pods/LookinServer/Src/Main/Server/Category/UILabel+LookinServer.h new file mode 100644 index 0000000..92c9294 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Category/UILabel+LookinServer.h @@ -0,0 +1,21 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// UILabel+LookinServer.h +// LookinServer +// +// Created by Li Kai on 2019/2/26. +// https://lookin.work +// + +#import + +@interface UILabel (LookinServer) + +@property(nonatomic, assign) CGFloat lks_fontSize; + +- (NSString *)lks_fontName; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Category/UILabel+LookinServer.m b/Pods/LookinServer/Src/Main/Server/Category/UILabel+LookinServer.m new file mode 100644 index 0000000..b7b9f70 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Category/UILabel+LookinServer.m @@ -0,0 +1,29 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// UILabel+LookinServer.m +// LookinServer +// +// Created by Li Kai on 2019/2/26. +// https://lookin.work +// + +#import "UILabel+LookinServer.h" + +@implementation UILabel (LookinServer) + +- (CGFloat)lks_fontSize { + return self.font.pointSize; +} +- (void)setLks_fontSize:(CGFloat)lks_fontSize { + UIFont *font = [self.font fontWithSize:lks_fontSize]; + self.font = font; +} + +- (NSString *)lks_fontName { + return self.font.fontName; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Category/UITableView+LookinServer.h b/Pods/LookinServer/Src/Main/Server/Category/UITableView+LookinServer.h new file mode 100644 index 0000000..881fa36 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Category/UITableView+LookinServer.h @@ -0,0 +1,19 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// UITableView+LookinServer.h +// LookinServer +// +// Created by Li Kai on 2019/9/5. +// https://lookin.work +// + +#import + +@interface UITableView (LookinServer) + +- (NSArray *)lks_numberOfRows; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Category/UITableView+LookinServer.m b/Pods/LookinServer/Src/Main/Server/Category/UITableView+LookinServer.m new file mode 100644 index 0000000..3788e3f --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Category/UITableView+LookinServer.m @@ -0,0 +1,29 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// UITableView+LookinServer.m +// LookinServer +// +// Created by Li Kai on 2019/9/5. +// https://lookin.work +// + +#import "UITableView+LookinServer.h" +#import "LookinServerDefines.h" + +@implementation UITableView (LookinServer) + +- (NSArray *)lks_numberOfRows { + NSUInteger sectionsCount = MIN(self.numberOfSections, 10); + NSArray *rowsCount = [NSArray lookin_arrayWithCount:sectionsCount block:^id(NSUInteger idx) { + return @([self numberOfRowsInSection:idx]); + }]; + if (rowsCount.count == 0) { + return nil; + } + return rowsCount; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Category/UITextField+LookinServer.h b/Pods/LookinServer/Src/Main/Server/Category/UITextField+LookinServer.h new file mode 100644 index 0000000..429c30b --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Category/UITextField+LookinServer.h @@ -0,0 +1,21 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// UITextField+LookinServer.h +// LookinServer +// +// Created by Li Kai on 2019/2/26. +// https://lookin.work +// + +#import + +@interface UITextField (LookinServer) + +@property(nonatomic, assign) CGFloat lks_fontSize; + +- (NSString *)lks_fontName; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Category/UITextField+LookinServer.m b/Pods/LookinServer/Src/Main/Server/Category/UITextField+LookinServer.m new file mode 100644 index 0000000..9e07a76 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Category/UITextField+LookinServer.m @@ -0,0 +1,29 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// UITextField+LookinServer.m +// LookinServer +// +// Created by Li Kai on 2019/2/26. +// https://lookin.work +// + +#import "UITextField+LookinServer.h" + +@implementation UITextField (LookinServer) + +- (CGFloat)lks_fontSize { + return self.font.pointSize; +} +- (void)setLks_fontSize:(CGFloat)lks_fontSize { + UIFont *font = [self.font fontWithSize:lks_fontSize]; + self.font = font; +} + +- (NSString *)lks_fontName { + return self.font.fontName; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Category/UITextView+LookinServer.h b/Pods/LookinServer/Src/Main/Server/Category/UITextView+LookinServer.h new file mode 100644 index 0000000..e36b2ab --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Category/UITextView+LookinServer.h @@ -0,0 +1,21 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// UITextView+LookinServer.h +// LookinServer +// +// Created by Li Kai on 2019/2/26. +// https://lookin.work +// + +#import + +@interface UITextView (LookinServer) + +@property(nonatomic, assign) CGFloat lks_fontSize; + +- (NSString *)lks_fontName; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Category/UITextView+LookinServer.m b/Pods/LookinServer/Src/Main/Server/Category/UITextView+LookinServer.m new file mode 100644 index 0000000..bd81a8b --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Category/UITextView+LookinServer.m @@ -0,0 +1,29 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// UITextView+LookinServer.m +// LookinServer +// +// Created by Li Kai on 2019/2/26. +// https://lookin.work +// + +#import "UITextView+LookinServer.h" + +@implementation UITextView (LookinServer) + +- (CGFloat)lks_fontSize { + return self.font.pointSize; +} +- (void)setLks_fontSize:(CGFloat)lks_fontSize { + UIFont *font = [self.font fontWithSize:lks_fontSize]; + self.font = font; +} + +- (NSString *)lks_fontName { + return self.font.fontName; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Category/UIView+LookinServer.h b/Pods/LookinServer/Src/Main/Server/Category/UIView+LookinServer.h new file mode 100644 index 0000000..eca36a1 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Category/UIView+LookinServer.h @@ -0,0 +1,44 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// UIView+LookinServer.h +// LookinServer +// +// Created by Li Kai on 2019/3/19. +// https://lookin.work +// + +#import "LookinDefines.h" +#import + +@interface UIView (LookinServer) + +/// 如果 myViewController.view = myView,则可以通过 myView 的 lks_findHostViewController 方法找到 myViewController +- (UIViewController *)lks_findHostViewController; + +/// 是否是 UITabBar 的 childrenView,如果是的话,则截图时需要强制使用 renderInContext: 的方式而非 drawViewHierarchyInRect:afterScreenUpdates: 否则在 iOS 13 上获取到的图像是空的不知道为什么 +@property(nonatomic, assign) BOOL lks_isChildrenViewOfTabBar; + +/// point 是相对于 receiver 自身的坐标系 +- (UIView *)lks_subviewAtPoint:(CGPoint)point preferredClasses:(NSArray *)preferredClasses; + +- (CGFloat)lks_bestWidth; +- (CGFloat)lks_bestHeight; +- (CGSize)lks_bestSize; + +@property(nonatomic, assign) float lks_horizontalContentHuggingPriority; +@property(nonatomic, assign) float lks_verticalContentHuggingPriority; + +@property(nonatomic, assign) float lks_horizontalContentCompressionResistancePriority; +@property(nonatomic, assign) float lks_verticalContentCompressionResistancePriority; + +/// 遍历全局的 view 并给他们设置 lks_involvedRawConstraints 属性 ++ (void)lks_rebuildGlobalInvolvedRawConstraints; +/// 该属性保存了牵扯到当前 view 的所有 constraints,包括那些没有生效的 +@property(nonatomic, strong) NSMutableArray *lks_involvedRawConstraints; + +- (NSArray *> *)lks_constraints; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Category/UIView+LookinServer.m b/Pods/LookinServer/Src/Main/Server/Category/UIView+LookinServer.m new file mode 100644 index 0000000..9cfa5f3 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Category/UIView+LookinServer.m @@ -0,0 +1,215 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// UIView+LookinServer.m +// LookinServer +// +// Created by Li Kai on 2019/3/19. +// https://lookin.work +// + +#import "UIView+LookinServer.h" +#import +#import "LookinObject.h" +#import "LookinAutoLayoutConstraint.h" +#import "LookinServerDefines.h" +#import "LKS_MultiplatformAdapter.h" + +@implementation UIView (LookinServer) + +- (UIViewController *)lks_findHostViewController { + UIResponder *responder = [self nextResponder]; + if (!responder) { + return nil; + } + if (![responder isKindOfClass:[UIViewController class]]) { + return nil; + } + UIViewController *viewController = (UIViewController *)responder; + if (viewController.view != self) { + return nil; + } + return viewController; +} + +- (UIView *)lks_subviewAtPoint:(CGPoint)point preferredClasses:(NSArray *)preferredClasses { + BOOL isPreferredClassForSelf = [preferredClasses lookin_any:^BOOL(Class obj) { + return [self isKindOfClass:obj]; + }]; + if (isPreferredClassForSelf) { + return self; + } + + UIView *targetView = [self.subviews lookin_lastFiltered:^BOOL(__kindof UIView *obj) { + if (obj.hidden || obj.alpha <= 0.01) { + return NO; + } + BOOL contains = CGRectContainsPoint(obj.frame, point); + return contains; + }]; + + if (!targetView) { + return self; + } + + CGPoint newPoint = [targetView convertPoint:point fromView:self]; + targetView = [targetView lks_subviewAtPoint:newPoint preferredClasses:preferredClasses]; + return targetView; +} + +- (CGSize)lks_bestSize { + return [self sizeThatFits:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)]; +} + +- (CGFloat)lks_bestWidth { + return self.lks_bestSize.width; +} + +- (CGFloat)lks_bestHeight { + return self.lks_bestSize.height; +} + +- (void)setLks_isChildrenViewOfTabBar:(BOOL)lks_isChildrenViewOfTabBar { + [self lookin_bindBOOL:lks_isChildrenViewOfTabBar forKey:@"lks_isChildrenViewOfTabBar"]; +} +- (BOOL)lks_isChildrenViewOfTabBar { + return [self lookin_getBindBOOLForKey:@"lks_isChildrenViewOfTabBar"]; +} + +- (void)setLks_verticalContentHuggingPriority:(float)lks_verticalContentHuggingPriority { + [self setContentHuggingPriority:lks_verticalContentHuggingPriority forAxis:UILayoutConstraintAxisVertical]; +} +- (float)lks_verticalContentHuggingPriority { + return [self contentHuggingPriorityForAxis:UILayoutConstraintAxisVertical]; +} + +- (void)setLks_horizontalContentHuggingPriority:(float)lks_horizontalContentHuggingPriority { + [self setContentHuggingPriority:lks_horizontalContentHuggingPriority forAxis:UILayoutConstraintAxisHorizontal]; +} +- (float)lks_horizontalContentHuggingPriority { + return [self contentHuggingPriorityForAxis:UILayoutConstraintAxisHorizontal]; +} + +- (void)setLks_verticalContentCompressionResistancePriority:(float)lks_verticalContentCompressionResistancePriority { + [self setContentCompressionResistancePriority:lks_verticalContentCompressionResistancePriority forAxis:UILayoutConstraintAxisVertical]; +} +- (float)lks_verticalContentCompressionResistancePriority { + return [self contentCompressionResistancePriorityForAxis:UILayoutConstraintAxisVertical]; +} + +- (void)setLks_horizontalContentCompressionResistancePriority:(float)lks_horizontalContentCompressionResistancePriority { + [self setContentCompressionResistancePriority:lks_horizontalContentCompressionResistancePriority forAxis:UILayoutConstraintAxisHorizontal]; +} +- (float)lks_horizontalContentCompressionResistancePriority { + return [self contentCompressionResistancePriorityForAxis:UILayoutConstraintAxisHorizontal]; +} + ++ (void)lks_rebuildGlobalInvolvedRawConstraints { + [[LKS_MultiplatformAdapter allWindows] enumerateObjectsUsingBlock:^(__kindof UIWindow * _Nonnull window, NSUInteger idx, BOOL * _Nonnull stop) { + [self lks_removeInvolvedRawConstraintsForViewsRootedByView:window]; + }]; + [[LKS_MultiplatformAdapter allWindows] enumerateObjectsUsingBlock:^(__kindof UIWindow * _Nonnull window, NSUInteger idx, BOOL * _Nonnull stop) { + [self lks_addInvolvedRawConstraintsForViewsRootedByView:window]; + }]; +} + ++ (void)lks_addInvolvedRawConstraintsForViewsRootedByView:(UIView *)rootView { + [rootView.constraints enumerateObjectsUsingBlock:^(__kindof NSLayoutConstraint * _Nonnull constraint, NSUInteger idx, BOOL * _Nonnull stop) { + UIView *firstView = constraint.firstItem; + if ([firstView isKindOfClass:[UIView class]] && ![firstView.lks_involvedRawConstraints containsObject:constraint]) { + if (!firstView.lks_involvedRawConstraints) { + firstView.lks_involvedRawConstraints = [NSMutableArray array]; + } + [firstView.lks_involvedRawConstraints addObject:constraint]; + } + + UIView *secondView = constraint.secondItem; + if ([secondView isKindOfClass:[UIView class]] && ![secondView.lks_involvedRawConstraints containsObject:constraint]) { + if (!secondView.lks_involvedRawConstraints) { + secondView.lks_involvedRawConstraints = [NSMutableArray array]; + } + [secondView.lks_involvedRawConstraints addObject:constraint]; + } + }]; + + [rootView.subviews enumerateObjectsUsingBlock:^(__kindof UIView * _Nonnull subview, NSUInteger idx, BOOL * _Nonnull stop) { + [self lks_addInvolvedRawConstraintsForViewsRootedByView:subview]; + }]; +} + ++ (void)lks_removeInvolvedRawConstraintsForViewsRootedByView:(UIView *)rootView { + [rootView.lks_involvedRawConstraints removeAllObjects]; + [rootView.subviews enumerateObjectsUsingBlock:^(__kindof UIView * _Nonnull subview, NSUInteger idx, BOOL * _Nonnull stop) { + [self lks_removeInvolvedRawConstraintsForViewsRootedByView:subview]; + }]; +} + +- (void)setLks_involvedRawConstraints:(NSMutableArray *)lks_involvedRawConstraints { + [self lookin_bindObject:lks_involvedRawConstraints forKey:@"lks_involvedRawConstraints"]; +} + +- (NSMutableArray *)lks_involvedRawConstraints { + return [self lookin_getBindObjectForKey:@"lks_involvedRawConstraints"]; +} + +- (NSArray *)lks_constraints { + /** + - lks_involvedRawConstraints 保存了牵扯到了 self 的所有的 constraints(包括未生效的,但不包括 inactive 的,整个产品逻辑都是直接忽略 inactive 的 constraints) + - 通过 constraintsAffectingLayoutForAxis 可以拿到会影响 self 布局的所有已生效的 constraints(这里称之为 effectiveConstraints) + - 很多情况下,一条 constraint 会出现在 effectiveConstraints 里但不会出现在 lks_involvedRawConstraints 里,比如: + · UIWindow 拥有 minX, minY, width, height 四个 effectiveConstraints,但 lks_involvedRawConstraints 为空,因为它的 constraints 属性为空(这一点不知道为啥,但 Xcode Inspector 和 Reveal 确实也不会显示这四个 constraints) + · 如果设置了 View1 的 center 和 superview 的 center 保持一致,则 superview 的 width 和 height 也会出现在 effectiveConstraints 里,但不会出现在 lks_involvedRawConstraints 里(这点可以理解,毕竟这种场景下 superview 的 width 和 height 确实会影响到 View1) + */ + NSMutableArray *effectiveConstraints = [NSMutableArray array]; + [effectiveConstraints addObjectsFromArray:[self constraintsAffectingLayoutForAxis:UILayoutConstraintAxisHorizontal]]; + [effectiveConstraints addObjectsFromArray:[self constraintsAffectingLayoutForAxis:UILayoutConstraintAxisVertical]]; + + NSArray *lookinConstraints = [self.lks_involvedRawConstraints lookin_map:^id(NSUInteger idx, __kindof NSLayoutConstraint *constraint) { + BOOL isEffective = [effectiveConstraints containsObject:constraint]; + if ([constraint isActive]) { + // trying to get firstItem or secondItem of an inactive constraint may cause dangling-pointer crash + // https://github.com/QMUI/LookinServer/issues/86 + LookinConstraintItemType firstItemType = [self _lks_constraintItemTypeForItem:constraint.firstItem]; + LookinConstraintItemType secondItemType = [self _lks_constraintItemTypeForItem:constraint.secondItem]; + LookinAutoLayoutConstraint *lookinConstraint = [LookinAutoLayoutConstraint instanceFromNSConstraint:constraint isEffective:isEffective firstItemType:firstItemType secondItemType:secondItemType]; + return lookinConstraint; + } + return nil; + }]; + return lookinConstraints.count ? lookinConstraints : nil; +} + +- (LookinConstraintItemType)_lks_constraintItemTypeForItem:(id)item { + if (!item) { + return LookinConstraintItemTypeNil; + } + if (item == self) { + return LookinConstraintItemTypeSelf; + } + if (item == self.superview) { + return LookinConstraintItemTypeSuper; + } + + // 在 runtime 时,这里会遇到的 UILayoutGuide 和 _UILayoutGuide 居然是 UIView 的子类,不知道是看错了还是有什么玄机,所以在判断是否是 UIView 之前要先判断这个 + if (@available(iOS 9.0, *)) { + if ([item isKindOfClass:[UILayoutGuide class]]) { + return LookinConstraintItemTypeLayoutGuide; + } + } + + NSString *className = NSStringFromClass([item class]); + if ([className hasSuffix:@"_UILayoutGuide"]) { + return LookinConstraintItemTypeLayoutGuide; + } + + if ([item isKindOfClass:[UIView class]]) { + return LookinConstraintItemTypeView; + } + + NSAssert(NO, @""); + return LookinConstraintItemTypeUnknown; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Category/UIViewController+LookinServer.h b/Pods/LookinServer/Src/Main/Server/Category/UIViewController+LookinServer.h new file mode 100644 index 0000000..1cab2a6 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Category/UIViewController+LookinServer.h @@ -0,0 +1,19 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// UIViewController+LookinServer.h +// LookinServer +// +// Created by Li Kai on 2019/4/22. +// https://lookin.work +// + +#import + +@interface UIViewController (LookinServer) + ++ (UIViewController *)lks_visibleViewController; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Category/UIViewController+LookinServer.m b/Pods/LookinServer/Src/Main/Server/Category/UIViewController+LookinServer.m new file mode 100644 index 0000000..2833eab --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Category/UIViewController+LookinServer.m @@ -0,0 +1,48 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// UIViewController+LookinServer.m +// LookinServer +// +// Created by Li Kai on 2019/4/22. +// https://lookin.work +// + +#import "UIViewController+LookinServer.h" +#import "UIView+LookinServer.h" +#import +#import "LKS_MultiplatformAdapter.h" + +@implementation UIViewController (LookinServer) + ++ (nullable UIViewController *)lks_visibleViewController { + + UIViewController *rootViewController = [LKS_MultiplatformAdapter keyWindow].rootViewController; + UIViewController *visibleViewController = [rootViewController lks_visibleViewControllerIfExist]; + return visibleViewController; +} + +- (UIViewController *)lks_visibleViewControllerIfExist { + + if (self.presentedViewController) { + return [self.presentedViewController lks_visibleViewControllerIfExist]; + } + + if ([self isKindOfClass:[UINavigationController class]]) { + return [((UINavigationController *)self).visibleViewController lks_visibleViewControllerIfExist]; + } + + if ([self isKindOfClass:[UITabBarController class]]) { + return [((UITabBarController *)self).selectedViewController lks_visibleViewControllerIfExist]; + } + + if (self.isViewLoaded && !self.view.hidden && self.view.alpha > 0.01) { + return self; + } else { + return nil; + } +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Category/UIVisualEffectView+LookinServer.h b/Pods/LookinServer/Src/Main/Server/Category/UIVisualEffectView+LookinServer.h new file mode 100644 index 0000000..697d840 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Category/UIVisualEffectView+LookinServer.h @@ -0,0 +1,21 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// UIVisualEffectView+LookinServer.h +// LookinServer +// +// Created by Li Kai on 2019/10/8. +// https://lookin.work +// + +#import + +@interface UIVisualEffectView (LookinServer) + +- (void)setLks_blurEffectStyleNumber:(NSNumber *)lks_blurEffectStyleNumber; + +- (NSNumber *)lks_blurEffectStyleNumber; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Category/UIVisualEffectView+LookinServer.m b/Pods/LookinServer/Src/Main/Server/Category/UIVisualEffectView+LookinServer.m new file mode 100644 index 0000000..df06b10 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Category/UIVisualEffectView+LookinServer.m @@ -0,0 +1,33 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// UIVisualEffectView+LookinServer.m +// LookinServer +// +// Created by Li Kai on 2019/10/8. +// https://lookin.work +// + +#import "UIVisualEffectView+LookinServer.h" +#import "UIBlurEffect+LookinServer.h" + +@implementation UIVisualEffectView (LookinServer) + +- (void)setLks_blurEffectStyleNumber:(NSNumber *)lks_blurEffectStyleNumber { + UIBlurEffectStyle style = [lks_blurEffectStyleNumber integerValue]; + UIBlurEffect *effect = [UIBlurEffect effectWithStyle:style]; + self.effect = effect; +} + +- (NSNumber *)lks_blurEffectStyleNumber { + UIVisualEffect *effect = self.effect; + if (![effect isKindOfClass:[UIBlurEffect class]]) { + return nil; + } + UIBlurEffect *blurEffect = (UIBlurEffect *)effect; + return blurEffect.lks_effectStyleNumber; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Connection/LKS_ConnectionManager.h b/Pods/LookinServer/Src/Main/Server/Connection/LKS_ConnectionManager.h new file mode 100644 index 0000000..684127b --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Connection/LKS_ConnectionManager.h @@ -0,0 +1,29 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// Lookin.h +// Lookin +// +// Created by Li Kai on 2018/8/5. +// https://lookin.work +// + +#import + +extern NSString *const LKS_ConnectionDidEndNotificationName; + +@class LookinConnectionResponseAttachment; + +@interface LKS_ConnectionManager : NSObject + ++ (instancetype)sharedInstance; + +@property(nonatomic, assign) BOOL applicationIsActive; + +- (void)respond:(LookinConnectionResponseAttachment *)data requestType:(uint32_t)requestType tag:(uint32_t)tag; + +- (void)pushData:(NSObject *)data type:(uint32_t)type; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Connection/LKS_ConnectionManager.m b/Pods/LookinServer/Src/Main/Server/Connection/LKS_ConnectionManager.m new file mode 100644 index 0000000..c992c7f --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Connection/LKS_ConnectionManager.m @@ -0,0 +1,268 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinServer.m +// LookinServer +// +// Created by Li Kai on 2018/8/5. +// https://lookin.work +// + +#import "LKS_ConnectionManager.h" +#import "Lookin_PTChannel.h" +#import "LKS_RequestHandler.h" +#import "LookinConnectionResponseAttachment.h" +#import "LKS_ExportManager.h" +#import "LookinServerDefines.h" +#import "LKS_TraceManager.h" +#import "LKS_MultiplatformAdapter.h" + +NSString *const LKS_ConnectionDidEndNotificationName = @"LKS_ConnectionDidEndNotificationName"; + +@interface LKS_ConnectionManager () + +@property(nonatomic, weak) Lookin_PTChannel *peerChannel_; + +@property(nonatomic, strong) LKS_RequestHandler *requestHandler; + +@end + +@implementation LKS_ConnectionManager + ++ (instancetype)sharedInstance { + static LKS_ConnectionManager *sharedInstance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[LKS_ConnectionManager alloc] init]; + }); + return sharedInstance; +} + ++ (void)load { + // 触发 init 方法 + [LKS_ConnectionManager sharedInstance]; +} + +- (instancetype)init { + if (self = [super init]) { + NSLog(@"LookinServer - Will launch. Framework version: %@", LOOKIN_SERVER_READABLE_VERSION); + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_handleApplicationDidBecomeActive) name:UIApplicationDidBecomeActiveNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_handleWillResignActiveNotification) name:UIApplicationWillResignActiveNotification object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_handleLocalInspect:) name:@"Lookin_2D" object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_handleLocalInspect:) name:@"Lookin_3D" object:nil]; + [[NSNotificationCenter defaultCenter] addObserverForName:@"Lookin_Export" object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) { + [[LKS_ExportManager sharedInstance] exportAndShare]; + }]; + [[NSNotificationCenter defaultCenter] addObserverForName:@"Lookin_RelationSearch" object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) { + [[LKS_TraceManager sharedInstance] addSearchTarger:note.object]; + }]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleGetLookinInfo:) name:@"GetLookinInfo" object:nil]; + + self.requestHandler = [LKS_RequestHandler new]; + } + return self; +} + +- (void)_handleWillResignActiveNotification { + self.applicationIsActive = NO; + + if (self.peerChannel_ && ![self.peerChannel_ isConnected]) { + [self.peerChannel_ close]; + self.peerChannel_ = nil; + } +} + +- (void)_handleApplicationDidBecomeActive { + self.applicationIsActive = YES; + [self searchPortToListenIfNoConnection]; +} + +- (void)searchPortToListenIfNoConnection { + if ([self.peerChannel_ isConnected]) { + NSLog(@"LookinServer - Abort to search ports. Already has connected channel."); + return; + } + NSLog(@"LookinServer - Searching port to listen..."); + [self.peerChannel_ close]; + self.peerChannel_ = nil; + + if ([self isiOSAppOnMac]) { + [self _tryToListenOnPortFrom:LookinSimulatorIPv4PortNumberStart to:LookinSimulatorIPv4PortNumberEnd current:LookinSimulatorIPv4PortNumberStart]; + } else { + [self _tryToListenOnPortFrom:LookinUSBDeviceIPv4PortNumberStart to:LookinUSBDeviceIPv4PortNumberEnd current:LookinUSBDeviceIPv4PortNumberStart]; + } +} + +- (BOOL)isiOSAppOnMac { +#if TARGET_OS_SIMULATOR + return YES; +#else + if (@available(iOS 14.0, *)) { + // isiOSAppOnMac 这个 API 看似在 iOS 14.0 上可用,但其实在 iOS 14 beta 上是不存在的、有 unrecognized selector 问题,因此这里要用 respondsToSelector 做一下保护 + NSProcessInfo *info = [NSProcessInfo processInfo]; + if ([info respondsToSelector:@selector(isiOSAppOnMac)]) { + return [info isiOSAppOnMac]; + } else if ([info respondsToSelector:@selector(isMacCatalystApp)]) { + return [info isMacCatalystApp]; + } else { + return NO; + } + } + if (@available(iOS 13.0, tvOS 13.0, *)) { + return [NSProcessInfo processInfo].isMacCatalystApp; + } + return NO; +#endif +} + +- (void)_tryToListenOnPortFrom:(int)fromPort to:(int)toPort current:(int)currentPort { + Lookin_PTChannel *channel = [Lookin_PTChannel channelWithDelegate:self]; + channel.targetPort = currentPort; + [channel listenOnPort:currentPort IPv4Address:INADDR_LOOPBACK callback:^(NSError *error) { + if (error) { + if (error.code == 48) { + // 该地址已被占用 + } else { + // 未知失败 + } + + if (currentPort < toPort) { + // 尝试下一个端口 + NSLog(@"LookinServer - 127.0.0.1:%d is unavailable(%@). Will try anothor address ...", currentPort, error); + [self _tryToListenOnPortFrom:fromPort to:toPort current:(currentPort + 1)]; + } else { + // 所有端口都尝试完毕,全部失败 + NSLog(@"LookinServer - 127.0.0.1:%d is unavailable(%@).", currentPort, error); + NSLog(@"LookinServer - Connect failed in the end."); + } + + } else { + // 成功 + NSLog(@"LookinServer - Connected successfully on 127.0.0.1:%d", currentPort); + // 此时 peerChannel_ 状态为 listening + self.peerChannel_ = channel; + } + }]; +} + +- (void)dealloc { + if (self.peerChannel_) { + [self.peerChannel_ close]; + } + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (void)respond:(LookinConnectionResponseAttachment *)data requestType:(uint32_t)requestType tag:(uint32_t)tag { + [self _sendData:data frameOfType:requestType tag:tag]; +} + +- (void)pushData:(NSObject *)data type:(uint32_t)type { + [self _sendData:data frameOfType:type tag:0]; +} + +- (void)_sendData:(NSObject *)data frameOfType:(uint32_t)frameOfType tag:(uint32_t)tag { + if (self.peerChannel_) { + NSData *archivedData = [NSKeyedArchiver archivedDataWithRootObject:data]; + dispatch_data_t payload = [archivedData createReferencingDispatchData]; + + [self.peerChannel_ sendFrameOfType:frameOfType tag:tag withPayload:payload callback:^(NSError *error) { + if (error) { + } + }]; + } +} + +#pragma mark - Lookin_PTChannelDelegate + +- (BOOL)ioFrameChannel:(Lookin_PTChannel*)channel shouldAcceptFrameOfType:(uint32_t)type tag:(uint32_t)tag payloadSize:(uint32_t)payloadSize { + if (channel != self.peerChannel_) { + return NO; + } else if ([self.requestHandler canHandleRequestType:type]) { + return YES; + } else { + [channel close]; + return NO; + } +} + +- (void)ioFrameChannel:(Lookin_PTChannel*)channel didReceiveFrameOfType:(uint32_t)type tag:(uint32_t)tag payload:(Lookin_PTData*)payload { + id object = nil; + if (payload) { + id unarchivedObject = [NSKeyedUnarchiver unarchiveObjectWithData:[NSData dataWithContentsOfDispatchData:payload.dispatchData]]; + if ([unarchivedObject isKindOfClass:[LookinConnectionAttachment class]]) { + LookinConnectionAttachment *attachment = (LookinConnectionAttachment *)unarchivedObject; + object = attachment.data; + } else { + object = unarchivedObject; + } + } + [self.requestHandler handleRequestType:type tag:tag object:object]; +} + +/// 当 Client 端链接成功时,该方法会被调用,然后 channel 的状态会变成 connected +- (void)ioFrameChannel:(Lookin_PTChannel*)channel didAcceptConnection:(Lookin_PTChannel*)otherChannel fromAddress:(Lookin_PTAddress*)address { + NSLog(@"LookinServer - channel:%@, acceptConnection:%@", channel.debugTag, otherChannel.debugTag); + + Lookin_PTChannel *previousChannel = self.peerChannel_; + + otherChannel.targetPort = address.port; + self.peerChannel_ = otherChannel; + + [previousChannel cancel]; +} + +/// 当连接过 Lookin 客户端,然后 Lookin 客户端又被关闭时,会走到这里 +- (void)ioFrameChannel:(Lookin_PTChannel*)channel didEndWithError:(NSError*)error { + if (self.peerChannel_ != channel) { + // Client 端第一次连接上时,之前 listen 的 port 会被 Peertalk 内部 cancel(并在 didAcceptConnection 方法里给业务抛一个新建的 connected 状态的 channel),那个被 cancel 的 channel 会走到这里 + NSLog(@"LookinServer - Ignore channel%@ end.", channel.debugTag); + return; + } + // Client 端关闭时,会走到这里 + NSLog(@"LookinServer - channel%@ DidEndWithError:%@", channel.debugTag, error); + + [[NSNotificationCenter defaultCenter] postNotificationName:LKS_ConnectionDidEndNotificationName object:self]; + [self searchPortToListenIfNoConnection]; +} + +#pragma mark - Handler + +- (void)_handleLocalInspect:(NSNotification *)note { + UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Lookin" message:@"Failed to run local inspection. The feature has been removed. Please use the computer version of Lookin or consider SDKs like FLEX for similar functionality." preferredStyle:UIAlertControllerStyleAlert]; + UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]; + [alertController addAction:okAction]; + UIWindow *keyWindow = [LKS_MultiplatformAdapter keyWindow]; + UIViewController *rootViewController = [keyWindow rootViewController]; + [rootViewController presentViewController:alertController animated:YES completion:nil]; + + NSLog(@"LookinServer - Failed to run local inspection. The feature has been removed. Please use the computer version of Lookin or consider SDKs like FLEX for similar functionality."); +} + +- (void)handleGetLookinInfo:(NSNotification *)note { + NSDictionary* userInfo = note.userInfo; + if (!userInfo) { + return; + } + NSMutableDictionary* infoWrapper = userInfo[@"infos"]; + if (![infoWrapper isKindOfClass:[NSMutableDictionary class]]) { + NSLog(@"LookinServer - GetLookinInfo failed. Params invalid."); + return; + } + infoWrapper[@"lookinServerVersion"] = LOOKIN_SERVER_READABLE_VERSION; +} + +@end + +/// 这个类使得用户可以通过 NSClassFromString(@"Lookin") 来判断 LookinServer 是否被编译进了项目里 + +@interface Lookin : NSObject + +@end + +@implementation Lookin + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Connection/LKS_RequestHandler.h b/Pods/LookinServer/Src/Main/Server/Connection/LKS_RequestHandler.h new file mode 100644 index 0000000..52ebe71 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Connection/LKS_RequestHandler.h @@ -0,0 +1,21 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LKS_RequestHandler.h +// LookinServer +// +// Created by Li Kai on 2019/1/15. +// https://lookin.work +// + +#import + +@interface LKS_RequestHandler : NSObject + +- (BOOL)canHandleRequestType:(uint32_t)requestType; + +- (void)handleRequestType:(uint32_t)requestType tag:(uint32_t)tag object:(id)object; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Connection/LKS_RequestHandler.m b/Pods/LookinServer/Src/Main/Server/Connection/LKS_RequestHandler.m new file mode 100644 index 0000000..c9d1572 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Connection/LKS_RequestHandler.m @@ -0,0 +1,558 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LKS_RequestHandler.m +// LookinServer +// +// Created by Li Kai on 2019/1/15. +// https://lookin.work +// + +#import "LKS_RequestHandler.h" +#import "NSObject+LookinServer.h" +#import "UIImage+LookinServer.h" +#import "LKS_ConnectionManager.h" +#import "LookinConnectionResponseAttachment.h" +#import "LookinAttributeModification.h" +#import "LookinDisplayItemDetail.h" +#import "LookinHierarchyInfo.h" +#import "LookinServerDefines.h" +#import +#import "LookinObject.h" +#import "LookinAppInfo.h" +#import "LKS_AttrGroupsMaker.h" +#import "LKS_InbuiltAttrModificationHandler.h" +#import "LKS_CustomAttrModificationHandler.h" +#import "LKS_AttrModificationPatchHandler.h" +#import "LKS_HierarchyDetailsHandler.h" +#import "LookinStaticAsyncUpdateTask.h" + +@interface LKS_RequestHandler () + +@property(nonatomic, strong) NSMutableSet *activeDetailHandlers; + +@end + +@implementation LKS_RequestHandler { + NSSet *_validRequestTypes; +} + +- (instancetype)init { + if (self = [super init]) { + _validRequestTypes = [NSSet setWithObjects:@(LookinRequestTypePing), + @(LookinRequestTypeApp), + @(LookinRequestTypeHierarchy), + @(LookinRequestTypeInbuiltAttrModification), + @(LookinRequestTypeCustomAttrModification), + @(LookinRequestTypeAttrModificationPatch), + @(LookinRequestTypeHierarchyDetails), + @(LookinRequestTypeFetchObject), + @(LookinRequestTypeAllAttrGroups), + @(LookinRequestTypeAllSelectorNames), + @(LookinRequestTypeInvokeMethod), + @(LookinRequestTypeFetchImageViewImage), + @(LookinRequestTypeModifyRecognizerEnable), + @(LookinPush_CanceHierarchyDetails), + nil]; + + self.activeDetailHandlers = [NSMutableSet set]; + } + return self; +} + +- (BOOL)canHandleRequestType:(uint32_t)requestType { + if ([_validRequestTypes containsObject:@(requestType)]) { + return YES; + } + return NO; +} + +- (void)handleRequestType:(uint32_t)requestType tag:(uint32_t)tag object:(id)object { + if (requestType == LookinRequestTypePing) { + LookinConnectionResponseAttachment *responseAttachment = [LookinConnectionResponseAttachment new]; + // 当 app 处于后台时,可能可以执行代码也可能不能执行代码,如果运气好了可以执行代码,则这里直接主动使用 appIsInBackground 标识 app 处于后台,不要让 Lookin 客户端傻傻地等待超时了 + if (![LKS_ConnectionManager sharedInstance].applicationIsActive) { + responseAttachment.appIsInBackground = YES; + } + [[LKS_ConnectionManager sharedInstance] respond:responseAttachment requestType:requestType tag:tag]; + + } else if (requestType == LookinRequestTypeApp) { + // 请求可用设备信息 + if (![object isKindOfClass:[NSDictionary class]]) { + [self _submitResponseWithError:LookinErr_Inner requestType:requestType tag:tag]; + return; + } + NSDictionary *params = object; + BOOL needImages = ((NSNumber *)params[@"needImages"]).boolValue; + NSArray *localIdentifiers = params[@"local"]; + + LookinAppInfo *appInfo = [LookinAppInfo currentInfoWithScreenshot:needImages icon:needImages localIdentifiers:localIdentifiers]; + + LookinConnectionResponseAttachment *responseAttachment = [LookinConnectionResponseAttachment new]; + responseAttachment.data = appInfo; + [[LKS_ConnectionManager sharedInstance] respond:responseAttachment requestType:requestType tag:tag]; + + } else if (requestType == LookinRequestTypeHierarchy) { + // 从 LookinClient 1.0.4 开始有这个参数,之前是 nil + NSString *clientVersion = nil; + if ([object isKindOfClass:[NSDictionary class]]) { + NSDictionary *params = object; + NSString *version = params[@"clientVersion"]; + if ([version isKindOfClass:[NSString class]]) { + clientVersion = version; + } + } + + LookinConnectionResponseAttachment *responseAttachment = [LookinConnectionResponseAttachment new]; + responseAttachment.data = [LookinHierarchyInfo staticInfoWithLookinVersion:clientVersion]; + [[LKS_ConnectionManager sharedInstance] respond:responseAttachment requestType:requestType tag:tag]; + + } else if (requestType == LookinRequestTypeInbuiltAttrModification) { + // 请求修改某个属性 + [LKS_InbuiltAttrModificationHandler handleModification:object completion:^(LookinDisplayItemDetail *data, NSError *error) { + LookinConnectionResponseAttachment *attachment = [LookinConnectionResponseAttachment new]; + if (error) { + attachment.error = error; + } else { + attachment.data = data; + } + [[LKS_ConnectionManager sharedInstance] respond:attachment requestType:requestType tag:tag]; + }]; + + } else if (requestType == LookinRequestTypeCustomAttrModification) { + BOOL succ = [LKS_CustomAttrModificationHandler handleModification:object]; + if (succ) { + [self _submitResponseWithData:nil requestType:requestType tag:tag]; + } else { + [self _submitResponseWithError:LookinErr_Inner requestType:requestType tag:tag]; + } + + } else if (requestType == LookinRequestTypeAttrModificationPatch) { + NSArray *tasks = object; + NSUInteger dataTotalCount = tasks.count; + [LKS_InbuiltAttrModificationHandler handlePatchWithTasks:tasks block:^(LookinDisplayItemDetail *data) { + LookinConnectionResponseAttachment *attrAttachment = [LookinConnectionResponseAttachment new]; + attrAttachment.data = data; + attrAttachment.dataTotalCount = dataTotalCount; + attrAttachment.currentDataCount = 1; + [[LKS_ConnectionManager sharedInstance] respond:attrAttachment requestType:LookinRequestTypeAttrModificationPatch tag:tag]; + }]; + + } else if (requestType == LookinRequestTypeHierarchyDetails) { + NSArray *packages = object; + NSUInteger responsesDataTotalCount = [packages lookin_reduceInteger:^NSInteger(NSInteger accumulator, NSUInteger idx, LookinStaticAsyncUpdateTasksPackage *package) { + accumulator += package.tasks.count; + return accumulator; + } initialAccumlator:0]; + + LKS_HierarchyDetailsHandler *handler = [LKS_HierarchyDetailsHandler new]; + [self.activeDetailHandlers addObject:handler]; + + [handler startWithPackages:packages block:^(NSArray *details) { + LookinConnectionResponseAttachment *attachment = [LookinConnectionResponseAttachment new]; + attachment.data = details; + attachment.dataTotalCount = responsesDataTotalCount; + attachment.currentDataCount = details.count; + [[LKS_ConnectionManager sharedInstance] respond:attachment requestType:LookinRequestTypeHierarchyDetails tag:tag]; + + } finishedBlock:^{ + [self.activeDetailHandlers removeObject:handler]; + }]; + + } else if (requestType == LookinRequestTypeFetchObject) { + unsigned long oid = ((NSNumber *)object).unsignedLongValue; + NSObject *object = [NSObject lks_objectWithOid:oid]; + LookinObject *lookinObj = [LookinObject instanceWithObject:object]; + + LookinConnectionResponseAttachment *attach = [LookinConnectionResponseAttachment new]; + attach.data = lookinObj; + [[LKS_ConnectionManager sharedInstance] respond:attach requestType:requestType tag:tag]; + + } else if (requestType == LookinRequestTypeAllAttrGroups) { + unsigned long oid = ((NSNumber *)object).unsignedLongValue; + CALayer *layer = (CALayer *)[NSObject lks_objectWithOid:oid]; + if (![layer isKindOfClass:[CALayer class]]) { + [self _submitResponseWithError:LookinErr_ObjNotFound requestType:LookinRequestTypeAllAttrGroups tag:tag]; + return; + } + + NSArray *list = [LKS_AttrGroupsMaker attrGroupsForLayer:layer]; + [self _submitResponseWithData:list requestType:LookinRequestTypeAllAttrGroups tag:tag]; + + } else if (requestType == LookinRequestTypeAllSelectorNames) { + if (![object isKindOfClass:[NSDictionary class]]) { + [self _submitResponseWithError:LookinErr_Inner requestType:requestType tag:tag]; + return; + } + NSDictionary *params = object; + Class targetClass = NSClassFromString(params[@"className"]); + BOOL hasArg = [(NSNumber *)params[@"hasArg"] boolValue]; + if (!targetClass) { + NSString *errorMsg = [NSString stringWithFormat:LKS_Localized(@"Didn't find the class named \"%@\". Please input another class and try again."), object]; + [self _submitResponseWithError:LookinErrorMake(errorMsg, @"") requestType:requestType tag:tag]; + return; + } + + NSArray *selNames = [self _methodNameListForClass:targetClass hasArg:hasArg]; + [self _submitResponseWithData:selNames requestType:requestType tag:tag]; + + } else if (requestType == LookinRequestTypeInvokeMethod) { + if (![object isKindOfClass:[NSDictionary class]]) { + [self _submitResponseWithError:LookinErr_Inner requestType:requestType tag:tag]; + return; + } + NSDictionary *param = object; + unsigned long oid = [param[@"oid"] unsignedLongValue]; + NSString *text = param[@"text"]; + if (!text.length) { + [self _submitResponseWithError:LookinErr_Inner requestType:requestType tag:tag]; + return; + } + NSObject *targerObj = [NSObject lks_objectWithOid:oid]; + if (!targerObj) { + [self _submitResponseWithError:LookinErr_ObjNotFound requestType:requestType tag:tag]; + return; + } + + SEL targetSelector = NSSelectorFromString(text); + if (targetSelector && [targerObj respondsToSelector:targetSelector]) { + NSString *resultDescription; + NSObject *resultObject; + NSError *error; + [self _handleInvokeWithObject:targerObj selector:targetSelector resultDescription:&resultDescription resultObject:&resultObject error:&error]; + if (error) { + [self _submitResponseWithError:error requestType:requestType tag:tag]; + return; + } + NSMutableDictionary *responseData = [NSMutableDictionary dictionaryWithCapacity:2]; + if (resultDescription) { + responseData[@"description"] = resultDescription; + } + if (resultObject) { + responseData[@"object"] = resultObject; + } + [self _submitResponseWithData:responseData requestType:requestType tag:tag]; + } else { + NSString *errMsg = [NSString stringWithFormat:LKS_Localized(@"%@ doesn't have an instance method called \"%@\"."), NSStringFromClass(targerObj.class), text]; + [self _submitResponseWithError:LookinErrorMake(errMsg, @"") requestType:requestType tag:tag]; + } + + } else if (requestType == LookinPush_CanceHierarchyDetails) { + [self.activeDetailHandlers enumerateObjectsUsingBlock:^(LKS_HierarchyDetailsHandler * _Nonnull handler, BOOL * _Nonnull stop) { + [handler cancel]; + }]; + [self.activeDetailHandlers removeAllObjects]; + + } else if (requestType == LookinRequestTypeFetchImageViewImage) { + if (![object isKindOfClass:[NSNumber class]]) { + [self _submitResponseWithError:LookinErr_Inner requestType:requestType tag:tag]; + return; + } + unsigned long imageViewOid = [(NSNumber *)object unsignedLongValue]; + UIImageView *imageView = (UIImageView *)[NSObject lks_objectWithOid:imageViewOid]; + if (!imageView) { + [self _submitResponseWithError:LookinErr_ObjNotFound requestType:requestType tag:tag]; + return; + } + if (![imageView isKindOfClass:[UIImageView class]]) { + [self _submitResponseWithError:LookinErr_Inner requestType:requestType tag:tag]; + return; + } + UIImage *image = imageView.image; + NSData *imageData = [image lookin_data]; + [self _submitResponseWithData:imageData requestType:requestType tag:tag]; + + } else if (requestType == LookinRequestTypeModifyRecognizerEnable) { + if (![object isKindOfClass:[NSDictionary class]]) { + [self _submitResponseWithError:LookinErr_Inner requestType:requestType tag:tag]; + return; + } + NSDictionary *params = object; + unsigned long recognizerOid = ((NSNumber *)params[@"oid"]).unsignedLongValue; + BOOL shouldBeEnabled = ((NSNumber *)params[@"enable"]).boolValue; + + UIGestureRecognizer *recognizer = (UIGestureRecognizer *)[NSObject lks_objectWithOid:recognizerOid]; + if (!recognizer) { + [self _submitResponseWithError:LookinErr_ObjNotFound requestType:requestType tag:tag]; + return; + } + if (![recognizer isKindOfClass:[UIGestureRecognizer class]]) { + [self _submitResponseWithError:LookinErr_Inner requestType:requestType tag:tag]; + return; + } + recognizer.enabled = shouldBeEnabled; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + // dispatch 以确保拿到的 enabled 是比较新的 + [self _submitResponseWithData:@(recognizer.enabled) requestType:requestType tag:tag]; + }); + } +} + +- (NSArray *)_methodNameListForClass:(Class)aClass hasArg:(BOOL)hasArg { + NSSet *prefixesToVoid = [NSSet setWithObjects:@"_", @"CA_", @"cpl", @"mf_", @"vs_", @"pep_", @"isNS", @"avkit_", @"PG_", @"px_", @"pl_", @"nsli_", @"pu_", @"pxg_", nil]; + NSMutableArray *array = [NSMutableArray array]; + + Class currentClass = aClass; + while (currentClass) { + NSString *className = NSStringFromClass(currentClass); + BOOL isSystemClass = ([className hasPrefix:@"UI"] || [className hasPrefix:@"CA"] || [className hasPrefix:@"NS"]); + + unsigned int methodCount = 0; + Method *methods = class_copyMethodList(currentClass, &methodCount); + for (unsigned int i = 0; i < methodCount; i++) { + NSString *selName = NSStringFromSelector(method_getName(methods[i])); + + if (!hasArg && [selName containsString:@":"]) { + continue; + } + + if (isSystemClass) { + BOOL invalid = [prefixesToVoid lookin_any:^BOOL(NSString *prefix) { + return [selName hasPrefix:prefix]; + }]; + if (invalid) { + continue; + } + } + if (selName.length && ![array containsObject:selName]) { + [array addObject:selName]; + } + } + if (methods) free(methods); + currentClass = [currentClass superclass]; + } + + return [array lookin_sortedArrayByStringLength]; +} + +- (void)_handleInvokeWithObject:(NSObject *)obj selector:(SEL)selector resultDescription:(NSString **)description resultObject:(LookinObject **)resultObject error:(NSError **)error { + NSMethodSignature *signature = [obj methodSignatureForSelector:selector]; + if (signature.numberOfArguments > 2) { + *error = LookinErrorMake(LKS_Localized(@"Lookin doesn't support invoking methods with arguments yet."), @""); + return; + } + + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; + [invocation setTarget:obj]; + [invocation setSelector:selector]; + [invocation invoke]; + + const char *returnType = [signature methodReturnType]; + + + if (strcmp(returnType, @encode(void)) == 0) { + //void, do nothing + *description = LookinStringFlag_VoidReturn; + + } else if (strcmp(returnType, @encode(char)) == 0) { + char charValue; + [invocation getReturnValue:&charValue]; + *description = [NSString stringWithFormat:@"%@", @(charValue)]; + + } else if (strcmp(returnType, @encode(int)) == 0) { + int intValue; + [invocation getReturnValue:&intValue]; + if (intValue == INT_MAX) { + *description = @"INT_MAX"; + } else if (intValue == INT_MIN) { + *description = @"INT_MIN"; + } else { + *description = [NSString stringWithFormat:@"%@", @(intValue)]; + } + + } else if (strcmp(returnType, @encode(short)) == 0) { + short shortValue; + [invocation getReturnValue:&shortValue]; + if (shortValue == SHRT_MAX) { + *description = @"SHRT_MAX"; + } else if (shortValue == SHRT_MIN) { + *description = @"SHRT_MIN"; + } else { + *description = [NSString stringWithFormat:@"%@", @(shortValue)]; + } + + } else if (strcmp(returnType, @encode(long)) == 0) { + long longValue; + [invocation getReturnValue:&longValue]; + if (longValue == NSNotFound) { + *description = @"NSNotFound"; + } else if (longValue == LONG_MAX) { + *description = @"LONG_MAX"; + } else if (longValue == LONG_MIN) { + *description = @"LONG_MAX"; + } else { + *description = [NSString stringWithFormat:@"%@", @(longValue)]; + } + + } else if (strcmp(returnType, @encode(long long)) == 0) { + long long longLongValue; + [invocation getReturnValue:&longLongValue]; + if (longLongValue == LLONG_MAX) { + *description = @"LLONG_MAX"; + } else if (longLongValue == LLONG_MIN) { + *description = @"LLONG_MIN"; + } else { + *description = [NSString stringWithFormat:@"%@", @(longLongValue)]; + } + + } else if (strcmp(returnType, @encode(unsigned char)) == 0) { + unsigned char ucharValue; + [invocation getReturnValue:&ucharValue]; + if (ucharValue == UCHAR_MAX) { + *description = @"UCHAR_MAX"; + } else { + *description = [NSString stringWithFormat:@"%@", @(ucharValue)]; + } + + } else if (strcmp(returnType, @encode(unsigned int)) == 0) { + unsigned int uintValue; + [invocation getReturnValue:&uintValue]; + if (uintValue == UINT_MAX) { + *description = @"UINT_MAX"; + } else { + *description = [NSString stringWithFormat:@"%@", @(uintValue)]; + } + + } else if (strcmp(returnType, @encode(unsigned short)) == 0) { + unsigned short ushortValue; + [invocation getReturnValue:&ushortValue]; + if (ushortValue == USHRT_MAX) { + *description = @"USHRT_MAX"; + } else { + *description = [NSString stringWithFormat:@"%@", @(ushortValue)]; + } + + } else if (strcmp(returnType, @encode(unsigned long)) == 0) { + unsigned long ulongValue; + [invocation getReturnValue:&ulongValue]; + if (ulongValue == ULONG_MAX) { + *description = @"ULONG_MAX"; + } else { + *description = [NSString stringWithFormat:@"%@", @(ulongValue)]; + } + + } else if (strcmp(returnType, @encode(unsigned long long)) == 0) { + unsigned long long ulongLongValue; + [invocation getReturnValue:&ulongLongValue]; + if (ulongLongValue == ULONG_LONG_MAX) { + *description = @"ULONG_LONG_MAX"; + } else { + *description = [NSString stringWithFormat:@"%@", @(ulongLongValue)]; + } + + } else if (strcmp(returnType, @encode(float)) == 0) { + float floatValue; + [invocation getReturnValue:&floatValue]; + if (floatValue == FLT_MAX) { + *description = @"FLT_MAX"; + } else if (floatValue == FLT_MIN) { + *description = @"FLT_MIN"; + } else { + *description = [NSString stringWithFormat:@"%@", @(floatValue)]; + } + + } else if (strcmp(returnType, @encode(double)) == 0) { + double doubleValue; + [invocation getReturnValue:&doubleValue]; + if (doubleValue == DBL_MAX) { + *description = @"DBL_MAX"; + } else if (doubleValue == DBL_MIN) { + *description = @"DBL_MIN"; + } else { + *description = [NSString stringWithFormat:@"%@", @(doubleValue)]; + } + + } else if (strcmp(returnType, @encode(BOOL)) == 0) { + BOOL boolValue; + [invocation getReturnValue:&boolValue]; + *description = boolValue ? @"YES" : @"NO"; + + } else if (strcmp(returnType, @encode(SEL)) == 0) { + SEL selValue; + [invocation getReturnValue:&selValue]; + *description = [NSString stringWithFormat:@"SEL(%@)", NSStringFromSelector(selValue)]; + + } else if (strcmp(returnType, @encode(Class)) == 0) { + Class classValue; + [invocation getReturnValue:&classValue]; + *description = [NSString stringWithFormat:@"<%@>", NSStringFromClass(classValue)]; + + } else if (strcmp(returnType, @encode(CGPoint)) == 0) { + CGPoint targetValue; + [invocation getReturnValue:&targetValue]; + *description = NSStringFromCGPoint(targetValue); + + } else if (strcmp(returnType, @encode(CGVector)) == 0) { + CGVector targetValue; + [invocation getReturnValue:&targetValue]; + *description = NSStringFromCGVector(targetValue); + + } else if (strcmp(returnType, @encode(CGSize)) == 0) { + CGSize targetValue; + [invocation getReturnValue:&targetValue]; + *description = NSStringFromCGSize(targetValue); + + } else if (strcmp(returnType, @encode(CGRect)) == 0) { + CGRect rectValue; + [invocation getReturnValue:&rectValue]; + *description = NSStringFromCGRect(rectValue); + + } else if (strcmp(returnType, @encode(CGAffineTransform)) == 0) { + CGAffineTransform rectValue; + [invocation getReturnValue:&rectValue]; + *description = NSStringFromCGAffineTransform(rectValue); + + } else if (strcmp(returnType, @encode(UIEdgeInsets)) == 0) { + UIEdgeInsets targetValue; + [invocation getReturnValue:&targetValue]; + *description = NSStringFromUIEdgeInsets(targetValue); + + } else if (strcmp(returnType, @encode(UIOffset)) == 0) { + UIOffset targetValue; + [invocation getReturnValue:&targetValue]; + *description = NSStringFromUIOffset(targetValue); + + } else { + if (@available(iOS 11.0, tvOS 11.0, *)) { + if (strcmp(returnType, @encode(NSDirectionalEdgeInsets)) == 0) { + NSDirectionalEdgeInsets targetValue; + [invocation getReturnValue:&targetValue]; + *description = NSStringFromDirectionalEdgeInsets(targetValue); + return; + } + } + + NSString *argType_string = [[NSString alloc] lookin_safeInitWithUTF8String:returnType]; + if ([argType_string hasPrefix:@"@"] || [argType_string hasPrefix:@"^{"]) { + __unsafe_unretained id returnObjValue; + [invocation getReturnValue:&returnObjValue]; + + if (returnObjValue) { + *description = [NSString stringWithFormat:@"%@", returnObjValue]; + + LookinObject *parsedLookinObj = [LookinObject instanceWithObject:returnObjValue]; + *resultObject = parsedLookinObj; + } else { + *description = @"nil"; + } + } else { + *description = [NSString stringWithFormat:LKS_Localized(@"%@ was invoked successfully, but Lookin can't parse the return value:%@"), NSStringFromSelector(selector), argType_string]; + } + } +} + +- (void)_submitResponseWithError:(NSError *)error requestType:(uint32_t)requestType tag:(uint32_t)tag { + LookinConnectionResponseAttachment *attachment = [LookinConnectionResponseAttachment new]; + attachment.error = error; + [[LKS_ConnectionManager sharedInstance] respond:attachment requestType:requestType tag:tag]; +} + +- (void)_submitResponseWithData:(NSObject *)data requestType:(uint32_t)requestType tag:(uint32_t)tag { + LookinConnectionResponseAttachment *attachment = [LookinConnectionResponseAttachment new]; + attachment.data = data; + [[LKS_ConnectionManager sharedInstance] respond:attachment requestType:requestType tag:tag]; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Connection/RequestHandler/LKS_AttrModificationPatchHandler.h b/Pods/LookinServer/Src/Main/Server/Connection/RequestHandler/LKS_AttrModificationPatchHandler.h new file mode 100644 index 0000000..d1b621b --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Connection/RequestHandler/LKS_AttrModificationPatchHandler.h @@ -0,0 +1,26 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LKS_AttrModificationPatchHandler.h +// LookinServer +// +// Created by Li Kai on 2019/6/12. +// https://lookin.work +// + +#import + +@class LookinDisplayItemDetail; + +@interface LKS_AttrModificationPatchHandler : NSObject + +/** + @param oids 数组内 idx 较小的应该为 displayItems 里的 subItem,idx 较大的应该为 superItem + @param lowImageQuality 是否采用低图像质量 + @param block 该 block 会被多次调用,其中 tasksTotalCount 是总的调用次数(即可被用来作为 TotalResponseCount) + */ ++ (void)handleLayerOids:(NSArray *)oids lowImageQuality:(BOOL)lowImageQuality block:(void (^)(LookinDisplayItemDetail *detail, NSUInteger tasksTotalCount, NSError *error))block; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Connection/RequestHandler/LKS_AttrModificationPatchHandler.m b/Pods/LookinServer/Src/Main/Server/Connection/RequestHandler/LKS_AttrModificationPatchHandler.m new file mode 100644 index 0000000..bc1cbcd --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Connection/RequestHandler/LKS_AttrModificationPatchHandler.m @@ -0,0 +1,51 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LKS_AttrModificationPatchHandler.m +// LookinServer +// +// Created by Li Kai on 2019/6/12. +// https://lookin.work +// + +#import "LKS_AttrModificationPatchHandler.h" +#import "LookinDisplayItemDetail.h" +#import "LookinServerDefines.h" + +@implementation LKS_AttrModificationPatchHandler + ++ (void)handleLayerOids:(NSArray *)oids lowImageQuality:(BOOL)lowImageQuality block:(void (^)(LookinDisplayItemDetail *detail, NSUInteger tasksTotalCount, NSError *error))block { + if (!block) { + NSAssert(NO, @""); + return; + } + if (![oids isKindOfClass:[NSArray class]]) { + block(nil, 1, LookinErr_Inner); + return; + } + + [oids enumerateObjectsUsingBlock:^(NSNumber * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + unsigned long oid = [obj unsignedLongValue]; + LookinDisplayItemDetail *detail = [LookinDisplayItemDetail new]; + detail.displayItemOid = oid; + + CALayer *layer = (CALayer *)[NSObject lks_objectWithOid:oid]; + if (![layer isKindOfClass:[CALayer class]]) { + block(nil, idx + 1, LookinErr_ObjNotFound); + *stop = YES; + return; + } + + if (idx == 0) { + detail.soloScreenshot = [layer lks_soloScreenshotWithLowQuality:lowImageQuality]; + detail.groupScreenshot = [layer lks_groupScreenshotWithLowQuality:lowImageQuality]; + } else { + detail.groupScreenshot = [layer lks_groupScreenshotWithLowQuality:lowImageQuality]; + } + block(detail, oids.count, nil); + }]; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Connection/RequestHandler/LKS_CustomAttrModificationHandler.h b/Pods/LookinServer/Src/Main/Server/Connection/RequestHandler/LKS_CustomAttrModificationHandler.h new file mode 100644 index 0000000..a35c899 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Connection/RequestHandler/LKS_CustomAttrModificationHandler.h @@ -0,0 +1,19 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER +// +// LKS_CustomAttrModificationHandler.h +// LookinServer +// +// Created by likaimacbookhome on 2023/11/4. +// + +#import +#import "LookinCustomAttrModification.h" + +@interface LKS_CustomAttrModificationHandler : NSObject + +/// 返回值表示是否修改成功(有成功调用 setter block 就算成功) ++ (BOOL)handleModification:(LookinCustomAttrModification *)modification; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Connection/RequestHandler/LKS_CustomAttrModificationHandler.m b/Pods/LookinServer/Src/Main/Server/Connection/RequestHandler/LKS_CustomAttrModificationHandler.m new file mode 100644 index 0000000..1935ef5 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Connection/RequestHandler/LKS_CustomAttrModificationHandler.m @@ -0,0 +1,155 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER +// +// LKS_CustomAttrModificationHandler.m +// LookinServer +// +// Created by likaimacbookhome on 2023/11/4. +// + +#import "LKS_CustomAttrModificationHandler.h" +#import "LKS_CustomAttrSetterManager.h" +#import "UIColor+LookinServer.h" + +@implementation LKS_CustomAttrModificationHandler + ++ (BOOL)handleModification:(LookinCustomAttrModification *)modification { + if (!modification || modification.customSetterID.length == 0) { + return NO; + } + switch (modification.attrType) { + case LookinAttrTypeNSString: { + NSString *newValue = modification.value; + if (newValue != nil && ![newValue isKindOfClass:[NSString class]]) { + // nil 是合法的 + return NO; + } + LKS_StringSetter setter = [[LKS_CustomAttrSetterManager sharedInstance] getStringSetterWithID:modification.customSetterID]; + if (!setter) { + return NO; + } + setter(newValue); + return YES; + } + + case LookinAttrTypeDouble: { + NSNumber *newValue = modification.value; + if (![newValue isKindOfClass:[NSNumber class]]) { + return NO; + } + LKS_NumberSetter setter = [[LKS_CustomAttrSetterManager sharedInstance] getNumberSetterWithID:modification.customSetterID]; + if (!setter) { + return NO; + } + setter(newValue); + return YES; + } + + case LookinAttrTypeBOOL: { + NSNumber *newValue = modification.value; + if (![newValue isKindOfClass:[NSNumber class]]) { + return NO; + } + LKS_BoolSetter setter = [[LKS_CustomAttrSetterManager sharedInstance] getBoolSetterWithID:modification.customSetterID]; + if (!setter) { + return NO; + } + setter(newValue.boolValue); + return YES; + } + + case LookinAttrTypeUIColor: { + LKS_ColorSetter setter = [[LKS_CustomAttrSetterManager sharedInstance] getColorSetterWithID:modification.customSetterID]; + if (!setter) { + return NO; + } + + NSArray *newValue = modification.value; + if (newValue == nil) { + // nil 是合法的 + setter(nil); + return YES; + } + if (![newValue isKindOfClass:[NSArray class]]) { + return NO; + } + UIColor *color = [UIColor lks_colorFromRGBAComponents:newValue]; + if (!color) { + return NO; + } + setter(color); + return YES; + } + + case LookinAttrTypeEnumString: { + NSString *newValue = modification.value; + if (![newValue isKindOfClass:[NSString class]]) { + return NO; + } + LKS_EnumSetter setter = [[LKS_CustomAttrSetterManager sharedInstance] getEnumSetterWithID:modification.customSetterID]; + if (!setter) { + return NO; + } + setter(newValue); + return YES; + } + + case LookinAttrTypeCGRect: { + NSValue *newValue = modification.value; + if (![newValue isKindOfClass:[NSValue class]]) { + return NO; + } + LKS_RectSetter setter = [[LKS_CustomAttrSetterManager sharedInstance] getRectSetterWithID:modification.customSetterID]; + if (!setter) { + return NO; + } + setter(newValue.CGRectValue); + return YES; + } + + case LookinAttrTypeCGSize: { + NSValue *newValue = modification.value; + if (![newValue isKindOfClass:[NSValue class]]) { + return NO; + } + LKS_SizeSetter setter = [[LKS_CustomAttrSetterManager sharedInstance] getSizeSetterWithID:modification.customSetterID]; + if (!setter) { + return NO; + } + setter(newValue.CGSizeValue); + return YES; + } + + case LookinAttrTypeCGPoint: { + NSValue *newValue = modification.value; + if (![newValue isKindOfClass:[NSValue class]]) { + return NO; + } + LKS_PointSetter setter = [[LKS_CustomAttrSetterManager sharedInstance] getPointSetterWithID:modification.customSetterID]; + if (!setter) { + return NO; + } + setter(newValue.CGPointValue); + return YES; + } + + case LookinAttrTypeUIEdgeInsets: { + NSValue *newValue = modification.value; + if (![newValue isKindOfClass:[NSValue class]]) { + return NO; + } + LKS_InsetsSetter setter = [[LKS_CustomAttrSetterManager sharedInstance] getInsetsSetterWithID:modification.customSetterID]; + if (!setter) { + return NO; + } + setter(newValue.UIEdgeInsetsValue); + return YES; + } + + default: + return NO; + } +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Connection/RequestHandler/LKS_HierarchyDetailsHandler.h b/Pods/LookinServer/Src/Main/Server/Connection/RequestHandler/LKS_HierarchyDetailsHandler.h new file mode 100644 index 0000000..0f2c56f --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Connection/RequestHandler/LKS_HierarchyDetailsHandler.h @@ -0,0 +1,30 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LKS_HierarchyDetailsHandler.h +// LookinServer +// +// Created by Li Kai on 2019/6/20. +// https://lookin.work +// + +#import + +@class LookinDisplayItemDetail, LookinStaticAsyncUpdateTasksPackage; + +typedef void (^LKS_HierarchyDetailsHandler_ProgressBlock)(NSArray *details); +typedef void (^LKS_HierarchyDetailsHandler_FinishBlock)(void); + +@interface LKS_HierarchyDetailsHandler : NSObject + +/// packages 会按照 idx 从小到大的顺序被执行 +/// 全部任务完成时,finishBlock 会被调用 +/// 如果调用了 cancel,则 finishBlock 不会被执行 +- (void)startWithPackages:(NSArray *)packages block:(LKS_HierarchyDetailsHandler_ProgressBlock)progressBlock finishedBlock:(LKS_HierarchyDetailsHandler_FinishBlock)finishBlock; + +/// 取消所有任务 +- (void)cancel; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Connection/RequestHandler/LKS_HierarchyDetailsHandler.m b/Pods/LookinServer/Src/Main/Server/Connection/RequestHandler/LKS_HierarchyDetailsHandler.m new file mode 100644 index 0000000..28999f9 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Connection/RequestHandler/LKS_HierarchyDetailsHandler.m @@ -0,0 +1,148 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LKS_HierarchyDetailsHandler.m +// LookinServer +// +// Created by Li Kai on 2019/6/20. +// https://lookin.work +// + +#import "LKS_HierarchyDetailsHandler.h" +#import "LookinDisplayItemDetail.h" +#import "LKS_AttrGroupsMaker.h" +#import "LookinStaticAsyncUpdateTask.h" +#import "LKS_ConnectionManager.h" +#import "LookinServerDefines.h" +#import "LKS_CustomAttrGroupsMaker.h" +#import "LKS_HierarchyDisplayItemsMaker.h" + +@interface LKS_HierarchyDetailsHandler () + +@property(nonatomic, strong) NSMutableArray *taskPackages; +/// 标识哪些 oid 已经拉取过 attrGroups 了 +@property(nonatomic, strong) NSMutableSet *attrGroupsSyncedOids; + +@property(nonatomic, copy) LKS_HierarchyDetailsHandler_ProgressBlock progressBlock; +@property(nonatomic, copy) LKS_HierarchyDetailsHandler_FinishBlock finishBlock; + +@end + +@implementation LKS_HierarchyDetailsHandler + +- (instancetype)init { + if (self = [super init]) { + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_handleConnectionDidEnd:) name:LKS_ConnectionDidEndNotificationName object:nil]; + + self.attrGroupsSyncedOids = [NSMutableSet set]; + } + return self; +} + +- (void)startWithPackages:(NSArray *)packages block:(LKS_HierarchyDetailsHandler_ProgressBlock)progressBlock finishedBlock:(LKS_HierarchyDetailsHandler_FinishBlock)finishBlock { + if (!progressBlock || !finishBlock) { + NSAssert(NO, @""); + return; + } + if (!packages.count) { + finishBlock(); + return; + } + self.taskPackages = [packages mutableCopy]; + self.progressBlock = progressBlock; + self.finishBlock = finishBlock; + + [UIView lks_rebuildGlobalInvolvedRawConstraints]; + + [self _dequeueAndHandlePackage]; +} + +- (void)cancel { + [self.taskPackages removeAllObjects]; +} + +- (void)_dequeueAndHandlePackage { + dispatch_async(dispatch_get_main_queue(), ^{ + LookinStaticAsyncUpdateTasksPackage *package = self.taskPackages.firstObject; + if (!package) { + self.finishBlock(); + return; + } + // NSLog(@"LookinServer - will handle tasks, count: %@", @(tasks.count)); + NSArray *details = [package.tasks lookin_map:^id(NSUInteger idx, LookinStaticAsyncUpdateTask *task) { + LookinDisplayItemDetail *itemDetail = [LookinDisplayItemDetail new]; + itemDetail.displayItemOid = task.oid; + + id object = [NSObject lks_objectWithOid:task.oid]; + if (!object || ![object isKindOfClass:[CALayer class]]) { + itemDetail.failureCode = -1; + return itemDetail; + } + + CALayer *layer = object; + + if (task.taskType == LookinStaticAsyncUpdateTaskTypeSoloScreenshot) { + UIImage *image = [layer lks_soloScreenshotWithLowQuality:NO]; + itemDetail.soloScreenshot = image; + } else if (task.taskType == LookinStaticAsyncUpdateTaskTypeGroupScreenshot) { + UIImage *image = [layer lks_groupScreenshotWithLowQuality:NO]; + itemDetail.groupScreenshot = image; + } + + BOOL shouldMakeAttr = [self queryIfShouldMakeAttrsFromTask:task]; + if (shouldMakeAttr) { + itemDetail.attributesGroupList = [LKS_AttrGroupsMaker attrGroupsForLayer:layer]; + + NSString *version = task.clientReadableVersion; + if (version.length > 0 && [version lookin_numbericOSVersion] >= 10004) { + LKS_CustomAttrGroupsMaker *maker = [[LKS_CustomAttrGroupsMaker alloc] initWithLayer:layer]; + [maker execute]; + itemDetail.customAttrGroupList = [maker getGroups]; + itemDetail.customDisplayTitle = [maker getCustomDisplayTitle]; + itemDetail.danceUISource = [maker getDanceUISource]; + } + [self.attrGroupsSyncedOids addObject:@(task.oid)]; + } + + if (task.needBasisVisualInfo) { + itemDetail.frameValue = [NSValue valueWithCGRect:layer.frame]; + itemDetail.boundsValue = [NSValue valueWithCGRect:layer.bounds]; + itemDetail.hiddenValue = [NSNumber numberWithBool:layer.isHidden]; + itemDetail.alphaValue = @(layer.opacity); + } + + if (task.needSubitems) { + itemDetail.subitems = [LKS_HierarchyDisplayItemsMaker subitemsOfLayer:layer]; + } + + return itemDetail; + }]; + self.progressBlock(details); + + [self.taskPackages removeObjectAtIndex:0]; + [self _dequeueAndHandlePackage]; + }); +} + +- (BOOL)queryIfShouldMakeAttrsFromTask:(LookinStaticAsyncUpdateTask *)task { + switch (task.attrRequest) { + case LookinDetailUpdateTaskAttrRequest_Automatic: { + BOOL alreadyMadeBefore = [self.attrGroupsSyncedOids containsObject:@(task.oid)]; + return !alreadyMadeBefore; + } + case LookinDetailUpdateTaskAttrRequest_Need: + return YES; + case LookinDetailUpdateTaskAttrRequest_NotNeed: + return NO; + } + NSAssert(NO, @""); + return YES; +} + +- (void)_handleConnectionDidEnd:(id)obj { + [self cancel]; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Connection/RequestHandler/LKS_InbuiltAttrModificationHandler.h b/Pods/LookinServer/Src/Main/Server/Connection/RequestHandler/LKS_InbuiltAttrModificationHandler.h new file mode 100644 index 0000000..481b466 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Connection/RequestHandler/LKS_InbuiltAttrModificationHandler.h @@ -0,0 +1,23 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LKS_InbuiltAttrModificationHandler.h +// LookinServer +// +// Created by Li Kai on 2019/6/12. +// https://lookin.work +// + +#import + +@class LookinAttributeModification, LookinDisplayItemDetail, LookinStaticAsyncUpdateTask; + +@interface LKS_InbuiltAttrModificationHandler : NSObject + ++ (void)handleModification:(LookinAttributeModification *)modification completion:(void (^)(LookinDisplayItemDetail *data, NSError *error))completion; + ++ (void)handlePatchWithTasks:(NSArray *)tasks block:(void (^)(LookinDisplayItemDetail *data))block; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Connection/RequestHandler/LKS_InbuiltAttrModificationHandler.m b/Pods/LookinServer/Src/Main/Server/Connection/RequestHandler/LKS_InbuiltAttrModificationHandler.m new file mode 100644 index 0000000..7911609 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Connection/RequestHandler/LKS_InbuiltAttrModificationHandler.m @@ -0,0 +1,255 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LKS_InbuiltAttrModificationHandler.m +// LookinServer +// +// Created by Li Kai on 2019/6/12. +// https://lookin.work +// + +#import "LKS_InbuiltAttrModificationHandler.h" +#import "UIColor+LookinServer.h" +#import "LookinAttributeModification.h" +#import "LKS_AttrGroupsMaker.h" +#import "LookinDisplayItemDetail.h" +#import "LookinStaticAsyncUpdateTask.h" +#import "LookinServerDefines.h" +#import "LKS_CustomAttrGroupsMaker.h" + +@implementation LKS_InbuiltAttrModificationHandler + ++ (void)handleModification:(LookinAttributeModification *)modification completion:(void (^)(LookinDisplayItemDetail *data, NSError *error))completion { + if (!completion) { + NSAssert(NO, @""); + return; + } + if (!modification || ![modification isKindOfClass:[LookinAttributeModification class]]) { + completion(nil, LookinErr_Inner); + return; + } + + NSObject *receiver = [NSObject lks_objectWithOid:modification.targetOid]; + if (!receiver) { + completion(nil, LookinErr_ObjNotFound); + return; + } + + NSMethodSignature *setterSignature = [receiver methodSignatureForSelector:modification.setterSelector]; + NSInvocation *setterInvocation = [NSInvocation invocationWithMethodSignature:setterSignature]; + setterInvocation.target = receiver; + setterInvocation.selector = modification.setterSelector; + + if (setterSignature.numberOfArguments != 3 || ![receiver respondsToSelector:modification.setterSelector]) { + completion(nil, LookinErr_Inner); + return; + } + + switch (modification.attrType) { + case LookinAttrTypeNone: + case LookinAttrTypeVoid: { + completion(nil, LookinErr_Inner); + return; + } + case LookinAttrTypeChar: { + char expectedValue = [(NSNumber *)modification.value charValue]; + [setterInvocation setArgument:&expectedValue atIndex:2]; + break; + } + case LookinAttrTypeInt: + case LookinAttrTypeEnumInt: { + int expectedValue = [(NSNumber *)modification.value intValue]; + [setterInvocation setArgument:&expectedValue atIndex:2]; + break; + } + case LookinAttrTypeShort: { + short expectedValue = [(NSNumber *)modification.value shortValue]; + [setterInvocation setArgument:&expectedValue atIndex:2]; + break; + } + case LookinAttrTypeLong: + case LookinAttrTypeEnumLong: { + long expectedValue = [(NSNumber *)modification.value longValue]; + [setterInvocation setArgument:&expectedValue atIndex:2]; + break; + } + case LookinAttrTypeLongLong: { + long long expectedValue = [(NSNumber *)modification.value longLongValue]; + [setterInvocation setArgument:&expectedValue atIndex:2]; + break; + } + case LookinAttrTypeUnsignedChar: { + unsigned char expectedValue = [(NSNumber *)modification.value unsignedCharValue]; + [setterInvocation setArgument:&expectedValue atIndex:2]; + break; + } + case LookinAttrTypeUnsignedInt: { + unsigned int expectedValue = [(NSNumber *)modification.value unsignedIntValue]; + [setterInvocation setArgument:&expectedValue atIndex:2]; + break; + } + case LookinAttrTypeUnsignedShort: { + unsigned short expectedValue = [(NSNumber *)modification.value unsignedShortValue]; + [setterInvocation setArgument:&expectedValue atIndex:2]; + break; + } + case LookinAttrTypeUnsignedLong: { + unsigned long expectedValue = [(NSNumber *)modification.value unsignedLongValue]; + [setterInvocation setArgument:&expectedValue atIndex:2]; + break; + } + case LookinAttrTypeUnsignedLongLong: { + unsigned long long expectedValue = [(NSNumber *)modification.value unsignedLongLongValue]; + [setterInvocation setArgument:&expectedValue atIndex:2]; + break; + } + case LookinAttrTypeFloat: { + float expectedValue = [(NSNumber *)modification.value floatValue]; + [setterInvocation setArgument:&expectedValue atIndex:2]; + break; + } + case LookinAttrTypeDouble: { + double expectedValue = [(NSNumber *)modification.value doubleValue]; + [setterInvocation setArgument:&expectedValue atIndex:2]; + break; + } + case LookinAttrTypeBOOL: { + BOOL expectedValue = [(NSNumber *)modification.value boolValue]; + [setterInvocation setArgument:&expectedValue atIndex:2]; + break; + } + case LookinAttrTypeSel: { + SEL expectedValue = NSSelectorFromString(modification.value); + [setterInvocation setArgument:&expectedValue atIndex:2]; + break; + } + case LookinAttrTypeClass: { + Class expectedValue = NSClassFromString(modification.value); + [setterInvocation setArgument:&expectedValue atIndex:2]; + break; + } + case LookinAttrTypeCGPoint: { + CGPoint expectedValue = [(NSValue *)modification.value CGPointValue]; + [setterInvocation setArgument:&expectedValue atIndex:2]; + break; + } + case LookinAttrTypeCGVector: { + CGVector expectedValue = [(NSValue *)modification.value CGVectorValue]; + [setterInvocation setArgument:&expectedValue atIndex:2]; + break; + } + case LookinAttrTypeCGSize: { + CGSize expectedValue = [(NSValue *)modification.value CGSizeValue]; + [setterInvocation setArgument:&expectedValue atIndex:2]; + break; + } + case LookinAttrTypeCGRect: { + CGRect expectedValue = [(NSValue *)modification.value CGRectValue]; + [setterInvocation setArgument:&expectedValue atIndex:2]; + break; + } + case LookinAttrTypeCGAffineTransform: { + CGAffineTransform expectedValue = [(NSValue *)modification.value CGAffineTransformValue]; + [setterInvocation setArgument:&expectedValue atIndex:2]; + break; + } + case LookinAttrTypeUIEdgeInsets: { + UIEdgeInsets expectedValue = [(NSValue *)modification.value UIEdgeInsetsValue]; + [setterInvocation setArgument:&expectedValue atIndex:2]; + break; + } + case LookinAttrTypeUIOffset: { + UIOffset expectedValue = [(NSValue *)modification.value UIOffsetValue]; + [setterInvocation setArgument:&expectedValue atIndex:2]; + break; + } + case LookinAttrTypeCustomObj: + case LookinAttrTypeNSString: { + NSObject *expectedValue = modification.value; + [setterInvocation setArgument:&expectedValue atIndex:2]; + [setterInvocation retainArguments]; + break; + } + case LookinAttrTypeUIColor: { + NSArray *rgba = modification.value; + UIColor *expectedValue = [UIColor lks_colorFromRGBAComponents:rgba]; + [setterInvocation setArgument:&expectedValue atIndex:2]; + [setterInvocation retainArguments]; + break; + } + default: { + completion(nil, LookinErr_Inner); + return; + } + } + + NSError *error = nil; + @try { + [setterInvocation invoke]; + } @catch (NSException *exception) { + NSString *errorMsg = [NSString stringWithFormat:LKS_Localized(@"<%@: %p>: an exception was raised when invoking %@. (%@)"), NSStringFromClass(receiver.class), receiver, NSStringFromSelector(modification.setterSelector), exception.reason]; + error = [NSError errorWithDomain:LookinErrorDomain code:LookinErrCode_Exception userInfo:@{NSLocalizedDescriptionKey:LKS_Localized(@"The modification may failed."), NSLocalizedRecoverySuggestionErrorKey:errorMsg}]; + } @finally { + + } + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + CALayer *layer = nil; + if ([receiver isKindOfClass:[CALayer class]]) { + layer = (CALayer *)receiver; + } else if ([receiver isKindOfClass:[UIView class]]) { + layer = ((UIView *)receiver).layer; + } else { + completion(nil, LookinErr_ObjNotFound); + return; + } + // 比如试图更改 frame 时,这个改动很有可能触发用户业务的 relayout,因此这时 dispatch 一下以确保拿到的 attrGroups 数据是最新的 + LookinDisplayItemDetail *detail = [LookinDisplayItemDetail new]; + detail.displayItemOid = modification.targetOid; + detail.attributesGroupList = [LKS_AttrGroupsMaker attrGroupsForLayer:layer]; + + NSString *version = modification.clientReadableVersion; + if (version.length > 0 && [version lookin_numbericOSVersion] >= 10004) { + LKS_CustomAttrGroupsMaker *maker = [[LKS_CustomAttrGroupsMaker alloc] initWithLayer:layer]; + [maker execute]; + detail.customAttrGroupList = [maker getGroups]; + } + + detail.frameValue = [NSValue valueWithCGRect:layer.frame]; + detail.boundsValue = [NSValue valueWithCGRect:layer.bounds]; + detail.hiddenValue = [NSNumber numberWithBool:layer.isHidden]; + detail.alphaValue = @(layer.opacity); + completion(detail, error); + }); +} + + ++ (void)handlePatchWithTasks:(NSArray *)tasks block:(void (^)(LookinDisplayItemDetail *data))block { + if (!block) { + NSAssert(NO, @""); + return; + } + [tasks enumerateObjectsUsingBlock:^(LookinStaticAsyncUpdateTask * _Nonnull task, NSUInteger idx, BOOL * _Nonnull stop) { + LookinDisplayItemDetail *itemDetail = [LookinDisplayItemDetail new]; + itemDetail.displayItemOid = task.oid; + id object = [NSObject lks_objectWithOid:task.oid]; + if (!object || ![object isKindOfClass:[CALayer class]]) { + block(itemDetail); + return; + } + + CALayer *layer = object; + if (task.taskType == LookinStaticAsyncUpdateTaskTypeSoloScreenshot) { + UIImage *image = [layer lks_soloScreenshotWithLowQuality:NO]; + itemDetail.soloScreenshot = image; + } else if (task.taskType == LookinStaticAsyncUpdateTaskTypeGroupScreenshot) { + UIImage *image = [layer lks_groupScreenshotWithLowQuality:NO]; + itemDetail.groupScreenshot = image; + } + block(itemDetail); + }]; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/LookinServer.h b/Pods/LookinServer/Src/Main/Server/LookinServer.h new file mode 100644 index 0000000..408b431 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/LookinServer.h @@ -0,0 +1,17 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinServer.h +// LookinServer +// +// Created by Li Kai on 2019/7/20. +// https://lookin.work +// + +#ifndef LookinServer_h +#define LookinServer_h + + +#endif /* LookinServer_h */ + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Others/LKSConfigManager.h b/Pods/LookinServer/Src/Main/Server/Others/LKSConfigManager.h new file mode 100644 index 0000000..1eecebe --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Others/LKSConfigManager.h @@ -0,0 +1,26 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LKSConfigManager.h +// LookinServer +// +// Created by likai.123 on 2023/1/10. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface LKSConfigManager : NSObject + ++ (NSArray *)collapsedClassList; + ++ (NSDictionary *)colorAlias; + ++ (BOOL)shouldCaptureScreenshotOfLayer:(CALayer *)layer; + +@end + +NS_ASSUME_NONNULL_END + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Others/LKSConfigManager.m b/Pods/LookinServer/Src/Main/Server/Others/LKSConfigManager.m new file mode 100644 index 0000000..830866a --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Others/LKSConfigManager.m @@ -0,0 +1,195 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LKSConfigManager.m +// LookinServer +// +// Created by likai.123 on 2023/1/10. +// + +#import "LKSConfigManager.h" +#import "NSArray+Lookin.h" +#import "CALayer+LookinServer.h" + +@implementation LKSConfigManager + ++ (NSArray *)collapsedClassList { + NSArray *result = [self queryCollapsedClassListWithClass:[NSObject class] selector:@"lookin_collapsedClassList"]; + if (result) { + return result; + } + + // Legacy logic. Deprecated. + Class configClass = NSClassFromString(@"LookinConfig"); + if (!configClass) { + return nil; + } + NSArray *legacyCodeResult = [self queryCollapsedClassListWithClass:configClass selector:@"collapsedClasses"]; + return legacyCodeResult; +} + ++ (NSArray *)queryCollapsedClassListWithClass:(Class)class selector:(NSString *)selectorName { + SEL selector = NSSelectorFromString(selectorName); + if (![class respondsToSelector:selector]) { + return nil; + } + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[class methodSignatureForSelector:selector]]; + [invocation setTarget:class]; + [invocation setSelector:selector]; + [invocation invoke]; + void *arrayValue; + [invocation getReturnValue:&arrayValue]; + id classList = (__bridge id)(arrayValue); + + if ([classList isKindOfClass:[NSArray class]]) { + NSArray *validClassList = [((NSArray *)classList) lookin_filter:^BOOL(id obj) { + return [obj isKindOfClass:[NSString class]]; + }]; + return [validClassList copy]; + } + return nil; +} + ++ (NSDictionary *)colorAlias { + NSDictionary *result = [self queryColorAliasWithClass:[NSObject class] selector:@"lookin_colorAlias"]; + if (result) { + return result; + } + + // Legacy logic. Deprecated. + Class configClass = NSClassFromString(@"LookinConfig"); + if (!configClass) { + return nil; + } + NSDictionary *legacyCodeResult = [self queryColorAliasWithClass:configClass selector:@"colors"]; + return legacyCodeResult; +} + ++ (NSDictionary *)queryColorAliasWithClass:(Class)class selector:(NSString *)selectorName { + SEL selector = NSSelectorFromString(selectorName); + if (![class respondsToSelector:selector]) { + return nil; + } + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[class methodSignatureForSelector:selector]]; + [invocation setTarget:class]; + [invocation setSelector:selector]; + [invocation invoke]; + void *dictValue; + [invocation getReturnValue:&dictValue]; + id colorAlias = (__bridge id)(dictValue); + + if ([colorAlias isKindOfClass:[NSDictionary class]]) { + NSMutableDictionary *validDictionary = [NSMutableDictionary dictionary]; + [(NSDictionary *)colorAlias enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { + if ([key isKindOfClass:[NSString class]]) { + if ([obj isKindOfClass:[UIColor class]]) { + [validDictionary setObject:obj forKey:key]; + + } else if ([obj isKindOfClass:[NSDictionary class]]) { + __block BOOL isValidSubDict = YES; + [((NSDictionary *)obj) enumerateKeysAndObjectsUsingBlock:^(id _Nonnull subKey, id _Nonnull subObj, BOOL * _Nonnull stop) { + if (![subKey isKindOfClass:[NSString class]] || ![subObj isKindOfClass:[UIColor class]]) { + isValidSubDict = NO; + *stop = YES; + } + }]; + if (isValidSubDict) { + [validDictionary setObject:obj forKey:key]; + } + } + } + }]; + return [validDictionary copy]; + } + return nil; +} + ++ (BOOL)shouldCaptureScreenshotOfLayer:(CALayer *)layer { + if (!layer) { + return YES; + } + if (![self shouldCaptureImageOfLayer:layer]) { + return NO; + } + UIView *view = layer.lks_hostView; + if (!view) { + return YES; + } + if (![self shouldCaptureImageOfView:view]) { + return NO; + } + return YES; +} + ++ (BOOL)shouldCaptureImageOfLayer:(CALayer *)layer { + if (!layer) { + return YES; + } + SEL selector = NSSelectorFromString(@"lookin_shouldCaptureImageOfLayer:"); + if ([NSObject respondsToSelector:selector]) { + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[NSObject methodSignatureForSelector:selector]]; + [invocation setTarget:[NSObject class]]; + [invocation setSelector:selector]; + [invocation setArgument:&layer atIndex:2]; + [invocation invoke]; + BOOL resultValue = YES; + [invocation getReturnValue:&resultValue]; + if (!resultValue) { + return NO; + } + } + + SEL selector2 = NSSelectorFromString(@"lookin_shouldCaptureImage"); + if ([layer respondsToSelector:selector2]) { + NSInvocation *invocation2 = [NSInvocation invocationWithMethodSignature:[layer methodSignatureForSelector:selector2]]; + [invocation2 setTarget:layer]; + [invocation2 setSelector:selector2]; + [invocation2 invoke]; + BOOL resultValue2 = YES; + [invocation2 getReturnValue:&resultValue2]; + if (!resultValue2) { + return NO; + } + } + + return YES; +} + ++ (BOOL)shouldCaptureImageOfView:(UIView *)view { + if (!view) { + return YES; + } + + SEL selector = NSSelectorFromString(@"lookin_shouldCaptureImageOfView:"); + if ([NSObject respondsToSelector:selector]) { + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[NSObject methodSignatureForSelector:selector]]; + [invocation setTarget:[NSObject class]]; + [invocation setSelector:selector]; + [invocation setArgument:&view atIndex:2]; + [invocation invoke]; + BOOL resultValue = YES; + [invocation getReturnValue:&resultValue]; + if (!resultValue) { + return NO; + } + } + + SEL selector2 = NSSelectorFromString(@"lookin_shouldCaptureImage"); + if ([view respondsToSelector:selector2]) { + NSInvocation *invocation2 = [NSInvocation invocationWithMethodSignature:[view methodSignatureForSelector:selector2]]; + [invocation2 setTarget:view]; + [invocation2 setSelector:selector2]; + [invocation2 invoke]; + BOOL resultValue2 = YES; + [invocation2 getReturnValue:&resultValue2]; + if (!resultValue2) { + return NO; + } + } + + return YES; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Others/LKS_AttrGroupsMaker.h b/Pods/LookinServer/Src/Main/Server/Others/LKS_AttrGroupsMaker.h new file mode 100644 index 0000000..1902da2 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Others/LKS_AttrGroupsMaker.h @@ -0,0 +1,21 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LKS_AttrGroupsMaker.h +// LookinServer +// +// Created by Li Kai on 2019/6/6. +// https://lookin.work +// + +#import "LookinDefines.h" + +@class LookinAttributesGroup; + +@interface LKS_AttrGroupsMaker : NSObject + ++ (NSArray *)attrGroupsForLayer:(CALayer *)layer; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Others/LKS_AttrGroupsMaker.m b/Pods/LookinServer/Src/Main/Server/Others/LKS_AttrGroupsMaker.m new file mode 100644 index 0000000..c140f21 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Others/LKS_AttrGroupsMaker.m @@ -0,0 +1,302 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LKS_AttrGroupsMaker.m +// LookinServer +// +// Created by Li Kai on 2019/6/6. +// https://lookin.work +// + +#import "LKS_AttrGroupsMaker.h" +#import "LookinAttributesGroup.h" +#import "LookinAttributesSection.h" +#import "LookinAttribute.h" +#import "LookinDashboardBlueprint.h" +#import "LookinIvarTrace.h" +#import "UIColor+LookinServer.h" +#import "LookinServerDefines.h" + +@implementation LKS_AttrGroupsMaker + ++ (NSArray *)attrGroupsForLayer:(CALayer *)layer { + if (!layer) { + NSAssert(NO, @""); + return nil; + } + NSArray *groups = [[LookinDashboardBlueprint groupIDs] lookin_map:^id(NSUInteger idx, LookinAttrGroupIdentifier groupID) { + LookinAttributesGroup *group = [LookinAttributesGroup new]; + group.identifier = groupID; + + NSArray *secIDs = [LookinDashboardBlueprint sectionIDsForGroupID:groupID]; + group.attrSections = [secIDs lookin_map:^id(NSUInteger idx, LookinAttrSectionIdentifier secID) { + LookinAttributesSection *sec = [LookinAttributesSection new]; + sec.identifier = secID; + + NSArray *attrIDs = [LookinDashboardBlueprint attrIDsForSectionID:secID]; + sec.attributes = [attrIDs lookin_map:^id(NSUInteger idx, LookinAttrIdentifier attrID) { + NSInteger minAvailableVersion = [LookinDashboardBlueprint minAvailableOSVersionWithAttrID:attrID]; + if (minAvailableVersion > 0 && (NSProcessInfo.processInfo.operatingSystemVersion.majorVersion < minAvailableVersion)) { + // iOS 版本过低不支持该属性 + return nil; + } + + id targetObj = nil; + if ([LookinDashboardBlueprint isUIViewPropertyWithAttrID:attrID]) { + targetObj = layer.lks_hostView; + } else { + targetObj = layer; + } + + if (targetObj) { + Class targetClass = NSClassFromString([LookinDashboardBlueprint classNameWithAttrID:attrID]); + if (![targetObj isKindOfClass:targetClass]) { + return nil; + } + + LookinAttribute *attr = [self _attributeWithIdentifer:attrID targetObject:targetObj]; + return attr; + } else { + return nil; + } + }]; + + if (sec.attributes.count) { + return sec; + } else { + return nil; + } + }]; + + if ([groupID isEqualToString:LookinAttrGroup_AutoLayout]) { + // 这里特殊处理一下,如果 AutoLayout 里面不包含 Constraints 的话(只有 Hugging 和 Resistance),就丢弃掉这整个 AutoLayout 不显示 + BOOL hasConstraits = [group.attrSections lookin_any:^BOOL(LookinAttributesSection *obj) { + return [obj.identifier isEqualToString:LookinAttrSec_AutoLayout_Constraints]; + }]; + if (!hasConstraits) { + return nil; + } + } + + if (group.attrSections.count) { + return group; + } else { + return nil; + } + }]; + + return groups; +} + ++ (LookinAttribute *)_attributeWithIdentifer:(LookinAttrIdentifier)identifier targetObject:(id)target { + if (!target) { + NSAssert(NO, @""); + return nil; + } + + LookinAttribute *attribute = [LookinAttribute new]; + attribute.identifier = identifier; + + SEL getter = [LookinDashboardBlueprint getterWithAttrID:identifier]; + if (!getter) { + NSAssert(NO, @""); + return nil; + } + if (![target respondsToSelector:getter]) { + // 比如某些 QMUI 的属性,不引入 QMUI 就会走到这个分支里 + return nil; + } + NSMethodSignature *signature = [target methodSignatureForSelector:getter]; + if (signature.numberOfArguments > 2) { + NSAssert(NO, @"getter 不可以有参数"); + return nil; + } + if (strcmp([signature methodReturnType], @encode(void)) == 0) { + NSAssert(NO, @"getter 返回值不能为 void"); + return nil; + } + + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; + invocation.target = target; + invocation.selector = getter; + [invocation invoke]; + + const char *returnType = [signature methodReturnType]; + + if (strcmp(returnType, @encode(char)) == 0) { + char targetValue; + [invocation getReturnValue:&targetValue]; + attribute.attrType = LookinAttrTypeChar; + attribute.value = @(targetValue); + + } else if (strcmp(returnType, @encode(int)) == 0) { + int targetValue; + [invocation getReturnValue:&targetValue]; + attribute.value = @(targetValue); + if ([LookinDashboardBlueprint enumListNameWithAttrID:identifier]) { + attribute.attrType = LookinAttrTypeEnumInt; + } else { + attribute.attrType = LookinAttrTypeInt; + } + + } else if (strcmp(returnType, @encode(short)) == 0) { + short targetValue; + [invocation getReturnValue:&targetValue]; + attribute.attrType = LookinAttrTypeShort; + attribute.value = @(targetValue); + + } else if (strcmp(returnType, @encode(long)) == 0) { + long targetValue; + [invocation getReturnValue:&targetValue]; + attribute.value = @(targetValue); + if ([LookinDashboardBlueprint enumListNameWithAttrID:identifier]) { + attribute.attrType = LookinAttrTypeEnumLong; + } else { + attribute.attrType = LookinAttrTypeLong; + } + + } else if (strcmp(returnType, @encode(long long)) == 0) { + long long targetValue; + [invocation getReturnValue:&targetValue]; + attribute.attrType = LookinAttrTypeLongLong; + attribute.value = @(targetValue); + + } else if (strcmp(returnType, @encode(unsigned char)) == 0) { + unsigned char targetValue; + [invocation getReturnValue:&targetValue]; + attribute.attrType = LookinAttrTypeUnsignedChar; + attribute.value = @(targetValue); + + } else if (strcmp(returnType, @encode(unsigned int)) == 0) { + unsigned int targetValue; + [invocation getReturnValue:&targetValue]; + attribute.attrType = LookinAttrTypeUnsignedInt; + attribute.value = @(targetValue); + + } else if (strcmp(returnType, @encode(unsigned short)) == 0) { + unsigned short targetValue; + [invocation getReturnValue:&targetValue]; + attribute.attrType = LookinAttrTypeUnsignedShort; + attribute.value = @(targetValue); + + } else if (strcmp(returnType, @encode(unsigned long)) == 0) { + unsigned long targetValue; + [invocation getReturnValue:&targetValue]; + attribute.attrType = LookinAttrTypeUnsignedLong; + attribute.value = @(targetValue); + + } else if (strcmp(returnType, @encode(unsigned long long)) == 0) { + unsigned long long targetValue; + [invocation getReturnValue:&targetValue]; + attribute.attrType = LookinAttrTypeUnsignedLongLong; + attribute.value = @(targetValue); + + } else if (strcmp(returnType, @encode(float)) == 0) { + float targetValue; + [invocation getReturnValue:&targetValue]; + attribute.attrType = LookinAttrTypeFloat; + attribute.value = @(targetValue); + + } else if (strcmp(returnType, @encode(double)) == 0) { + double targetValue; + [invocation getReturnValue:&targetValue]; + attribute.attrType = LookinAttrTypeDouble; + attribute.value = @(targetValue); + + } else if (strcmp(returnType, @encode(BOOL)) == 0) { + BOOL targetValue; + [invocation getReturnValue:&targetValue]; + attribute.attrType = LookinAttrTypeBOOL; + attribute.value = @(targetValue); + + } else if (strcmp(returnType, @encode(SEL)) == 0) { + SEL targetValue; + [invocation getReturnValue:&targetValue]; + attribute.attrType = LookinAttrTypeSel; + attribute.value = NSStringFromSelector(targetValue); + + } else if (strcmp(returnType, @encode(Class)) == 0) { + Class targetValue; + [invocation getReturnValue:&targetValue]; + attribute.attrType = LookinAttrTypeClass; + attribute.value = NSStringFromClass(targetValue); + + } else if (strcmp(returnType, @encode(CGPoint)) == 0) { + CGPoint targetValue; + [invocation getReturnValue:&targetValue]; + attribute.attrType = LookinAttrTypeCGPoint; + attribute.value = [NSValue valueWithCGPoint:targetValue]; + + } else if (strcmp(returnType, @encode(CGVector)) == 0) { + CGVector targetValue; + [invocation getReturnValue:&targetValue]; + attribute.attrType = LookinAttrTypeCGVector; + attribute.value = [NSValue valueWithCGVector:targetValue]; + + } else if (strcmp(returnType, @encode(CGSize)) == 0) { + CGSize targetValue; + [invocation getReturnValue:&targetValue]; + attribute.attrType = LookinAttrTypeCGSize; + attribute.value = [NSValue valueWithCGSize:targetValue]; + + } else if (strcmp(returnType, @encode(CGRect)) == 0) { + CGRect targetValue; + [invocation getReturnValue:&targetValue]; + attribute.attrType = LookinAttrTypeCGRect; + attribute.value = [NSValue valueWithCGRect:targetValue]; + + } else if (strcmp(returnType, @encode(CGAffineTransform)) == 0) { + CGAffineTransform targetValue; + [invocation getReturnValue:&targetValue]; + attribute.attrType = LookinAttrTypeCGAffineTransform; + attribute.value = [NSValue valueWithCGAffineTransform:targetValue]; + + } else if (strcmp(returnType, @encode(UIEdgeInsets)) == 0) { + UIEdgeInsets targetValue; + [invocation getReturnValue:&targetValue]; + attribute.attrType = LookinAttrTypeUIEdgeInsets; + attribute.value = [NSValue valueWithUIEdgeInsets:targetValue]; + + } else if (strcmp(returnType, @encode(UIOffset)) == 0) { + UIOffset targetValue; + [invocation getReturnValue:&targetValue]; + attribute.attrType = LookinAttrTypeUIOffset; + attribute.value = [NSValue valueWithUIOffset:targetValue]; + + } else { + NSString *argType_string = [[NSString alloc] lookin_safeInitWithUTF8String:returnType]; + if ([argType_string hasPrefix:@"@"]) { + __unsafe_unretained id returnObjValue; + [invocation getReturnValue:&returnObjValue]; + + if (!returnObjValue && [LookinDashboardBlueprint hideIfNilWithAttrID:identifier]) { + // 对于某些属性,若 value 为 nil 则不显示 + return nil; + } + + attribute.attrType = [LookinDashboardBlueprint objectAttrTypeWithAttrID:identifier]; + if (attribute.attrType == LookinAttrTypeUIColor) { + if (returnObjValue == nil) { + attribute.value = nil; + } else if ([returnObjValue isKindOfClass:[UIColor class]] && [returnObjValue respondsToSelector:@selector(lks_rgbaComponents)]) { + attribute.value = [returnObjValue lks_rgbaComponents]; + } else { + // https://github.com/QMUI/LookinServer/issues/124 + return nil; + } + } else { + attribute.value = returnObjValue; + } + + } else { + NSAssert(NO, @"不支持解析该类型的返回值"); + return nil; + } + } + + return attribute; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Others/LKS_CustomAttrGroupsMaker.h b/Pods/LookinServer/Src/Main/Server/Others/LKS_CustomAttrGroupsMaker.h new file mode 100644 index 0000000..781711a --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Others/LKS_CustomAttrGroupsMaker.h @@ -0,0 +1,27 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER +// +// LKS_CustomAttrGroupsMaker.h +// LookinServer +// +// Created by LikaiMacStudioWork on 2023/10/31. +// + +#import "LookinDefines.h" + +@class LookinAttributesGroup; + +@interface LKS_CustomAttrGroupsMaker : NSObject + +- (instancetype)initWithLayer:(CALayer *)layer; + +- (void)execute; + +- (NSArray *)getGroups; +- (NSString *)getCustomDisplayTitle; +- (NSString *)getDanceUISource; + ++ (NSArray *)makeGroupsFromRawProperties:(NSArray *)rawProperties saveCustomSetter:(BOOL)saveCustomSetter; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Others/LKS_CustomAttrGroupsMaker.m b/Pods/LookinServer/Src/Main/Server/Others/LKS_CustomAttrGroupsMaker.m new file mode 100644 index 0000000..428b683 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Others/LKS_CustomAttrGroupsMaker.m @@ -0,0 +1,486 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER +// +// LKS_CustomAttrGroupsMaker.m +// LookinServer +// +// Created by LikaiMacStudioWork on 2023/10/31. +// + +#import "LKS_CustomAttrGroupsMaker.h" +#import "LKS_AttrGroupsMaker.h" +#import "LookinAttributesGroup.h" +#import "LookinAttributesSection.h" +#import "LookinAttribute.h" +#import "LookinDashboardBlueprint.h" +#import "LookinIvarTrace.h" +#import "UIColor+LookinServer.h" +#import "LookinServerDefines.h" +#import "LKS_CustomAttrSetterManager.h" + +@interface LKS_CustomAttrGroupsMaker () + +/// key 是 section title +@property(nonatomic, strong) NSMutableDictionary *> *sectionAndAttrs; + +@property(nonatomic, copy) NSString *resolvedCustomDisplayTitle; +@property(nonatomic, copy) NSString *resolvedDanceUISource; +@property(nonatomic, strong) NSMutableArray *resolvedGroups; + +@property(nonatomic, weak) CALayer *layer; + +@end + +@implementation LKS_CustomAttrGroupsMaker + +- (instancetype)initWithLayer:(CALayer *)layer { + if (self = [super init]) { + self.sectionAndAttrs = [NSMutableDictionary dictionary]; + self.layer = layer; + } + return self; +} + +- (void)execute { + if (!self.layer) { + NSAssert(NO, @""); + return; + } + NSMutableArray *selectors = [NSMutableArray array]; + [selectors addObject:@"lookin_customDebugInfos"]; + for (int i = 0; i < 5; i++) { + [selectors addObject:[NSString stringWithFormat:@"lookin_customDebugInfos_%@", @(i)]]; + } + + for (NSString *name in selectors) { + [self makeAttrsForViewOrLayer:self.layer selectorName:name]; + + UIView *view = self.layer.lks_hostView; + if (view) { + [self makeAttrsForViewOrLayer:view selectorName:name]; + } + } + + if ([self.sectionAndAttrs count] == 0) { + return; + } + NSMutableArray *groups = [NSMutableArray array]; + [self.sectionAndAttrs enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull groupTitle, NSMutableArray * _Nonnull attrs, BOOL * _Nonnull stop) { + LookinAttributesGroup *group = [LookinAttributesGroup new]; + group.userCustomTitle = groupTitle; + group.identifier = LookinAttrGroup_UserCustom; + + NSMutableArray *sections = [NSMutableArray array]; + [attrs enumerateObjectsUsingBlock:^(LookinAttribute * _Nonnull attr, NSUInteger idx, BOOL * _Nonnull stop) { + LookinAttributesSection *sec = [LookinAttributesSection new]; + sec.identifier = LookinAttrSec_UserCustom; + sec.attributes = @[attr]; + [sections addObject:sec]; + }]; + + group.attrSections = sections; + [groups addObject:group]; + }]; + [groups sortedArrayUsingComparator:^NSComparisonResult(LookinAttributesGroup *obj1, LookinAttributesGroup *obj2) { + return [obj1.userCustomTitle compare:obj2.userCustomTitle]; + }]; + + self.resolvedGroups = groups; +} + +- (void)makeAttrsForViewOrLayer:(id)viewOrLayer selectorName:(NSString *)selectorName { + if (!viewOrLayer || !selectorName.length) { + return; + } + if (![viewOrLayer isKindOfClass:[UIView class]] && ![viewOrLayer isKindOfClass:[CALayer class]]) { + return; + } + SEL selector = NSSelectorFromString(selectorName); + if (![viewOrLayer respondsToSelector:selector]) { + return; + } + NSMethodSignature *signature = [viewOrLayer methodSignatureForSelector:selector]; + if (signature.numberOfArguments > 2) { + NSAssert(NO, @"LookinServer - There should be no explicit parameters."); + return; + } + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; + [invocation setTarget:viewOrLayer]; + [invocation setSelector:selector]; + [invocation invoke]; + + // 小心这里的内存管理 + NSDictionary * __unsafe_unretained tempRawData; + [invocation getReturnValue:&tempRawData]; + if (!tempRawData || ![tempRawData isKindOfClass:[NSDictionary class]]) { + return; + } + + NSDictionary *rawData = tempRawData; + NSArray *rawProperties = rawData[@"properties"]; + + NSString *customTitle = rawData[@"title"]; + if (customTitle && [customTitle isKindOfClass:[NSString class]] && customTitle.length > 0) { + self.resolvedCustomDisplayTitle = customTitle; + } + + NSString *danceSource = rawData[@"lookin_source"]; + if (danceSource && [danceSource isKindOfClass:[NSString class]] && danceSource.length > 0) { + self.resolvedDanceUISource = danceSource; + } + + [self makeAttrsFromRawProperties:rawProperties]; +} + +- (void)makeAttrsFromRawProperties:(NSArray *)rawProperties { + if (!rawProperties || ![rawProperties isKindOfClass:[NSArray class]]) { + return; + } + + for (NSDictionary *dict in rawProperties) { + NSString *groupTitle; + LookinAttribute *attr = [LKS_CustomAttrGroupsMaker attrFromRawDict:dict saveCustomSetter:YES groupTitle:&groupTitle]; + if (!attr) { + continue; + } + if (!self.sectionAndAttrs[groupTitle]) { + self.sectionAndAttrs[groupTitle] = [NSMutableArray array]; + } + [self.sectionAndAttrs[groupTitle] addObject:attr]; + } +} + ++ (LookinAttribute *)attrFromRawDict:(NSDictionary *)dict saveCustomSetter:(BOOL)saveCustomSetter groupTitle:(inout NSString **)inoutGroupTitle { + LookinAttribute *attr = [LookinAttribute new]; + attr.identifier = LookinAttr_UserCustom; + + NSString *title = dict[@"title"]; + NSString *type = dict[@"valueType"]; + NSString *section = dict[@"section"]; + id value = dict[@"value"]; + + if (!title || ![title isKindOfClass:[NSString class]]) { + NSLog(@"LookinServer - Wrong title"); + return nil; + } + if (!type || ![type isKindOfClass:[NSString class]]) { + NSLog(@"LookinServer - Wrong valueType"); + return nil; + } + if (!section || ![section isKindOfClass:[NSString class]] || section.length == 0) { + *inoutGroupTitle = @"Custom"; + } else { + *inoutGroupTitle = section; + } + + attr.displayTitle = title; + + NSString *fixedType = type.lowercaseString; + if ([fixedType isEqualToString:@"string"]) { + if (value != nil && ![value isKindOfClass:[NSString class]]) { + // nil 是合法的 + NSLog(@"LookinServer - Wrong value type."); + return nil; + } + attr.attrType = LookinAttrTypeNSString; + attr.value = value; + + if (saveCustomSetter && dict[@"retainedSetter"]) { + NSString *uniqueID = [[NSUUID new] UUIDString]; + LKS_StringSetter setter = dict[@"retainedSetter"]; + [[LKS_CustomAttrSetterManager sharedInstance] saveStringSetter:setter uniqueID:uniqueID]; + attr.customSetterID = uniqueID; + } + + return attr; + } + + if ([fixedType isEqualToString:@"number"]) { + if (value == nil) { + NSLog(@"LookinServer - No value."); + return nil; + } + if (![value isKindOfClass:[NSNumber class]]) { + NSLog(@"LookinServer - Wrong value type."); + return nil; + } + attr.attrType = LookinAttrTypeDouble; + attr.value = value; + + if (saveCustomSetter && dict[@"retainedSetter"]) { + NSString *uniqueID = [[NSUUID new] UUIDString]; + LKS_NumberSetter setter = dict[@"retainedSetter"]; + [[LKS_CustomAttrSetterManager sharedInstance] saveNumberSetter:setter uniqueID:uniqueID]; + attr.customSetterID = uniqueID; + } + + return attr; + } + + if ([fixedType isEqualToString:@"bool"]) { + if (value == nil) { + NSLog(@"LookinServer - No value."); + return nil; + } + if (![value isKindOfClass:[NSNumber class]]) { + NSLog(@"LookinServer - Wrong value type."); + return nil; + } + attr.attrType = LookinAttrTypeBOOL; + attr.value = value; + + if (saveCustomSetter && dict[@"retainedSetter"]) { + NSString *uniqueID = [[NSUUID new] UUIDString]; + LKS_BoolSetter setter = dict[@"retainedSetter"]; + [[LKS_CustomAttrSetterManager sharedInstance] saveBoolSetter:setter uniqueID:uniqueID]; + attr.customSetterID = uniqueID; + } + + return attr; + } + + if ([fixedType isEqualToString:@"color"]) { + if (value != nil && ![value isKindOfClass:[UIColor class]]) { + // nil 是合法的 + NSLog(@"LookinServer - Wrong value type."); + return nil; + } + attr.attrType = LookinAttrTypeUIColor; + attr.value = [(UIColor *)value lks_rgbaComponents]; + + if (saveCustomSetter && dict[@"retainedSetter"]) { + NSString *uniqueID = [[NSUUID new] UUIDString]; + LKS_ColorSetter setter = dict[@"retainedSetter"]; + [[LKS_CustomAttrSetterManager sharedInstance] saveColorSetter:setter uniqueID:uniqueID]; + attr.customSetterID = uniqueID; + } + + return attr; + } + + if ([fixedType isEqualToString:@"rect"]) { + if (value == nil) { + NSLog(@"LookinServer - No value."); + return nil; + } + if (![value isKindOfClass:[NSValue class]]) { + NSLog(@"LookinServer - Wrong value type."); + return nil; + } + attr.attrType = LookinAttrTypeCGRect; + attr.value = value; + + if (saveCustomSetter && dict[@"retainedSetter"]) { + NSString *uniqueID = [[NSUUID new] UUIDString]; + LKS_RectSetter setter = dict[@"retainedSetter"]; + [[LKS_CustomAttrSetterManager sharedInstance] saveRectSetter:setter uniqueID:uniqueID]; + attr.customSetterID = uniqueID; + } + + return attr; + } + + if ([fixedType isEqualToString:@"size"]) { + if (value == nil) { + NSLog(@"LookinServer - No value."); + return nil; + } + if (![value isKindOfClass:[NSValue class]]) { + NSLog(@"LookinServer - Wrong value type."); + return nil; + } + attr.attrType = LookinAttrTypeCGSize; + attr.value = value; + + if (saveCustomSetter && dict[@"retainedSetter"]) { + NSString *uniqueID = [[NSUUID new] UUIDString]; + LKS_SizeSetter setter = dict[@"retainedSetter"]; + [[LKS_CustomAttrSetterManager sharedInstance] saveSizeSetter:setter uniqueID:uniqueID]; + attr.customSetterID = uniqueID; + } + + return attr; + } + + if ([fixedType isEqualToString:@"point"]) { + if (value == nil) { + NSLog(@"LookinServer - No value."); + return nil; + } + if (![value isKindOfClass:[NSValue class]]) { + NSLog(@"LookinServer - Wrong value type."); + return nil; + } + attr.attrType = LookinAttrTypeCGPoint; + attr.value = value; + + if (saveCustomSetter && dict[@"retainedSetter"]) { + NSString *uniqueID = [[NSUUID new] UUIDString]; + LKS_PointSetter setter = dict[@"retainedSetter"]; + [[LKS_CustomAttrSetterManager sharedInstance] savePointSetter:setter uniqueID:uniqueID]; + attr.customSetterID = uniqueID; + } + + return attr; + } + + if ([fixedType isEqualToString:@"insets"]) { + if (value == nil) { + NSLog(@"LookinServer - No value."); + return nil; + } + if (![value isKindOfClass:[NSValue class]]) { + NSLog(@"LookinServer - Wrong value type."); + return nil; + } + attr.attrType = LookinAttrTypeUIEdgeInsets; + attr.value = value; + + if (saveCustomSetter && dict[@"retainedSetter"]) { + NSString *uniqueID = [[NSUUID new] UUIDString]; + LKS_InsetsSetter setter = dict[@"retainedSetter"]; + [[LKS_CustomAttrSetterManager sharedInstance] saveInsetsSetter:setter uniqueID:uniqueID]; + attr.customSetterID = uniqueID; + } + + return attr; + } + + if ([fixedType isEqualToString:@"shadow"]) { + if (value == nil) { + NSLog(@"LookinServer - No value."); + return nil; + } + if (![value isKindOfClass:[NSDictionary class]]) { + NSLog(@"LookinServer - Wrong value type."); + return nil; + } + NSDictionary *shadowInfo = value; + if (![shadowInfo[@"offset"] isKindOfClass:[NSValue class]]) { + NSLog(@"LookinServer - Wrong value. No offset."); + return nil; + } + if (![shadowInfo[@"opacity"] isKindOfClass:[NSNumber class]]) { + NSLog(@"LookinServer - Wrong value. No opacity."); + return nil; + } + if (![shadowInfo[@"radius"] isKindOfClass:[NSNumber class]]) { + NSLog(@"LookinServer - Wrong value. No radius."); + return nil; + } + NSMutableDictionary *checkedShadowInfo = [@{ + @"offset": shadowInfo[@"offset"], + @"opacity": shadowInfo[@"opacity"], + @"radius": shadowInfo[@"radius"] + } mutableCopy]; + if ([shadowInfo[@"color"] isKindOfClass:[UIColor class]]) { + checkedShadowInfo[@"color"] = [(UIColor *)shadowInfo[@"color"] lks_rgbaComponents]; + } + + attr.attrType = LookinAttrTypeShadow; + attr.value = checkedShadowInfo; + + return attr; + } + + if ([fixedType isEqualToString:@"enum"]) { + if (value == nil) { + NSLog(@"LookinServer - No value."); + return nil; + } + if (![value isKindOfClass:[NSString class]]) { + NSLog(@"LookinServer - Wrong value type."); + return nil; + } + attr.attrType = LookinAttrTypeEnumString; + attr.value = value; + + NSArray *allEnumCases = dict[@"allEnumCases"]; + if ([allEnumCases isKindOfClass:[NSArray class]]) { + attr.extraValue = allEnumCases; + } + + if (saveCustomSetter && dict[@"retainedSetter"]) { + NSString *uniqueID = [[NSUUID new] UUIDString]; + LKS_EnumSetter setter = dict[@"retainedSetter"]; + [[LKS_CustomAttrSetterManager sharedInstance] saveEnumSetter:setter uniqueID:uniqueID]; + attr.customSetterID = uniqueID; + } + + return attr; + } + + if ([fixedType isEqualToString:@"json"]) { + if (![value isKindOfClass:[NSString class]]) { + NSLog(@"LookinServer - Wrong value type."); + return nil; + } + attr.attrType = LookinAttrTypeJson; + attr.value = value; + + return attr; + } + + NSLog(@"LookinServer - Unsupported value type."); + return nil; +} + +- (NSArray *)getGroups { + return self.resolvedGroups; +} + +- (NSString *)getCustomDisplayTitle { + return self.resolvedCustomDisplayTitle; +} + +- (NSString *)getDanceUISource { + return self.resolvedDanceUISource; +} + ++ (NSArray *)makeGroupsFromRawProperties:(NSArray *)rawProperties saveCustomSetter:(BOOL)saveCustomSetter { + if (!rawProperties || ![rawProperties isKindOfClass:[NSArray class]]) { + return nil; + } + // key 是 group title + NSMutableDictionary *> *groupTitleAndAttrs = [NSMutableDictionary dictionary]; + + for (NSDictionary *dict in rawProperties) { + NSString *groupTitle; + LookinAttribute *attr = [LKS_CustomAttrGroupsMaker attrFromRawDict:dict saveCustomSetter:saveCustomSetter groupTitle:&groupTitle]; + if (!attr) { + continue; + } + if (!groupTitleAndAttrs[groupTitle]) { + groupTitleAndAttrs[groupTitle] = [NSMutableArray array]; + } + [groupTitleAndAttrs[groupTitle] addObject:attr]; + } + + if ([groupTitleAndAttrs count] == 0) { + return nil; + } + NSMutableArray *groups = [NSMutableArray array]; + [groupTitleAndAttrs enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull groupTitle, NSMutableArray * _Nonnull attrs, BOOL * _Nonnull stop) { + LookinAttributesGroup *group = [LookinAttributesGroup new]; + group.userCustomTitle = groupTitle; + group.identifier = LookinAttrGroup_UserCustom; + + NSMutableArray *sections = [NSMutableArray array]; + [attrs enumerateObjectsUsingBlock:^(LookinAttribute * _Nonnull attr, NSUInteger idx, BOOL * _Nonnull stop) { + LookinAttributesSection *sec = [LookinAttributesSection new]; + sec.identifier = LookinAttrSec_UserCustom; + sec.attributes = @[attr]; + [sections addObject:sec]; + }]; + + group.attrSections = sections; + [groups addObject:group]; + }]; + [groups sortedArrayUsingComparator:^NSComparisonResult(LookinAttributesGroup *obj1, LookinAttributesGroup *obj2) { + return [obj1.userCustomTitle compare:obj2.userCustomTitle]; + }]; + return [groups copy]; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Others/LKS_CustomAttrSetterManager.h b/Pods/LookinServer/Src/Main/Server/Others/LKS_CustomAttrSetterManager.h new file mode 100644 index 0000000..7fccc77 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Others/LKS_CustomAttrSetterManager.h @@ -0,0 +1,56 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER +// +// LKS_CustomAttrSetterManager.h +// LookinServer +// +// Created by likai.123 on 2023/11/4. +// + +#import + +typedef void(^LKS_StringSetter)(NSString *); +typedef void(^LKS_NumberSetter)(NSNumber *); +typedef void(^LKS_BoolSetter)(BOOL); +typedef void(^LKS_ColorSetter)(UIColor *); +typedef void(^LKS_EnumSetter)(NSString *); +typedef void(^LKS_RectSetter)(CGRect); +typedef void(^LKS_SizeSetter)(CGSize); +typedef void(^LKS_PointSetter)(CGPoint); +typedef void(^LKS_InsetsSetter)(UIEdgeInsets); + +@interface LKS_CustomAttrSetterManager : NSObject + ++ (instancetype)sharedInstance; + +- (void)removeAll; + +- (void)saveStringSetter:(LKS_StringSetter)setter uniqueID:(NSString *)uniqueID; +- (LKS_StringSetter)getStringSetterWithID:(NSString *)uniqueID; + +- (void)saveNumberSetter:(LKS_NumberSetter)setter uniqueID:(NSString *)uniqueID; +- (LKS_NumberSetter)getNumberSetterWithID:(NSString *)uniqueID; + +- (void)saveBoolSetter:(LKS_BoolSetter)setter uniqueID:(NSString *)uniqueID; +- (LKS_BoolSetter)getBoolSetterWithID:(NSString *)uniqueID; + +- (void)saveColorSetter:(LKS_ColorSetter)setter uniqueID:(NSString *)uniqueID; +- (LKS_ColorSetter)getColorSetterWithID:(NSString *)uniqueID; + +- (void)saveEnumSetter:(LKS_EnumSetter)setter uniqueID:(NSString *)uniqueID; +- (LKS_EnumSetter)getEnumSetterWithID:(NSString *)uniqueID; + +- (void)saveRectSetter:(LKS_RectSetter)setter uniqueID:(NSString *)uniqueID; +- (LKS_RectSetter)getRectSetterWithID:(NSString *)uniqueID; + +- (void)saveSizeSetter:(LKS_SizeSetter)setter uniqueID:(NSString *)uniqueID; +- (LKS_SizeSetter)getSizeSetterWithID:(NSString *)uniqueID; + +- (void)savePointSetter:(LKS_PointSetter)setter uniqueID:(NSString *)uniqueID; +- (LKS_PointSetter)getPointSetterWithID:(NSString *)uniqueID; + +- (void)saveInsetsSetter:(LKS_InsetsSetter)setter uniqueID:(NSString *)uniqueID; +- (LKS_InsetsSetter)getInsetsSetterWithID:(NSString *)uniqueID; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Others/LKS_CustomAttrSetterManager.m b/Pods/LookinServer/Src/Main/Server/Others/LKS_CustomAttrSetterManager.m new file mode 100644 index 0000000..20b73c9 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Others/LKS_CustomAttrSetterManager.m @@ -0,0 +1,117 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER +// +// LKS_CustomAttrSetterManager.m +// LookinServer +// +// Created by likai.123 on 2023/11/4. +// + +#import "LKS_CustomAttrSetterManager.h" + +@interface LKS_CustomAttrSetterManager () + +@property(nonatomic, strong) NSMutableDictionary *settersMap; + +@end + +@implementation LKS_CustomAttrSetterManager + ++ (instancetype)sharedInstance { + static dispatch_once_t onceToken; + static LKS_CustomAttrSetterManager *instance = nil; + dispatch_once(&onceToken,^{ + instance = [[super allocWithZone:NULL] init]; + }); + return instance; +} + ++ (id)allocWithZone:(struct _NSZone *)zone { + return [self sharedInstance]; +} + +- (instancetype)init { + self = [super init]; + if (self) { + self.settersMap = [NSMutableDictionary new]; + } + return self; +} + +- (void)removeAll { + [self.settersMap removeAllObjects]; +} + +- (void)saveStringSetter:(nonnull LKS_StringSetter)setter uniqueID:(nonnull NSString *)uniqueID { + self.settersMap[uniqueID] = setter; +} + +- (nullable LKS_StringSetter)getStringSetterWithID:(nonnull NSString *)uniqueID { + return self.settersMap[uniqueID]; +} + +- (void)saveNumberSetter:(LKS_NumberSetter)setter uniqueID:(NSString *)uniqueID { + self.settersMap[uniqueID] = setter; +} + +- (nullable LKS_NumberSetter)getNumberSetterWithID:(NSString *)uniqueID { + return self.settersMap[uniqueID]; +} + +- (void)saveBoolSetter:(LKS_BoolSetter)setter uniqueID:(NSString *)uniqueID { + self.settersMap[uniqueID] = setter; +} + +- (LKS_BoolSetter)getBoolSetterWithID:(NSString *)uniqueID { + return self.settersMap[uniqueID]; +} + +- (void)saveColorSetter:(LKS_ColorSetter)setter uniqueID:(NSString *)uniqueID { + self.settersMap[uniqueID] = setter; +} + +- (LKS_ColorSetter)getColorSetterWithID:(NSString *)uniqueID { + return self.settersMap[uniqueID]; +} + +- (void)saveEnumSetter:(LKS_EnumSetter)setter uniqueID:(NSString *)uniqueID { + self.settersMap[uniqueID] = setter; +} + +- (LKS_EnumSetter)getEnumSetterWithID:(NSString *)uniqueID { + return self.settersMap[uniqueID]; +} + +- (void)saveRectSetter:(LKS_RectSetter)setter uniqueID:(NSString *)uniqueID { + self.settersMap[uniqueID] = setter; +} + +- (LKS_RectSetter)getRectSetterWithID:(NSString *)uniqueID { + return self.settersMap[uniqueID]; +} + +- (void)saveSizeSetter:(LKS_SizeSetter)setter uniqueID:(NSString *)uniqueID { + self.settersMap[uniqueID] = setter; +} + +- (LKS_SizeSetter)getSizeSetterWithID:(NSString *)uniqueID { + return self.settersMap[uniqueID]; +} + +- (void)savePointSetter:(LKS_PointSetter)setter uniqueID:(NSString *)uniqueID { + self.settersMap[uniqueID] = setter; +} + +- (LKS_PointSetter)getPointSetterWithID:(NSString *)uniqueID { + return self.settersMap[uniqueID]; +} + +- (void)saveInsetsSetter:(LKS_InsetsSetter)setter uniqueID:(NSString *)uniqueID { + self.settersMap[uniqueID] = setter; +} + +- (LKS_InsetsSetter)getInsetsSetterWithID:(NSString *)uniqueID { + return self.settersMap[uniqueID]; +} + +@end +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Others/LKS_CustomDisplayItemsMaker.h b/Pods/LookinServer/Src/Main/Server/Others/LKS_CustomDisplayItemsMaker.h new file mode 100644 index 0000000..7cf658e --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Others/LKS_CustomDisplayItemsMaker.h @@ -0,0 +1,22 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LKS_CustomDisplayItemsMaker.h +// LookinServer +// +// Created by likai.123 on 2023/11/1. +// + +#import + +@class LookinDisplayItem; + +@interface LKS_CustomDisplayItemsMaker : NSObject + +- (instancetype)initWithLayer:(CALayer *)layer saveAttrSetter:(BOOL)saveAttrSetter; + +- (NSArray *)make; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Others/LKS_CustomDisplayItemsMaker.m b/Pods/LookinServer/Src/Main/Server/Others/LKS_CustomDisplayItemsMaker.m new file mode 100644 index 0000000..bdffcfc --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Others/LKS_CustomDisplayItemsMaker.m @@ -0,0 +1,144 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LKS_CustomDisplayItemsMaker.m +// LookinServer +// +// Created by likai.123 on 2023/11/1. +// + +#import "LKS_CustomDisplayItemsMaker.h" +#import "CALayer+LookinServer.h" +#import "LookinDisplayItem.h" +#import "NSArray+Lookin.h" +#import "LKS_CustomAttrGroupsMaker.h" + +@interface LKS_CustomDisplayItemsMaker () + +@property(nonatomic, weak) CALayer *layer; +@property(nonatomic, assign) BOOL saveAttrSetter; +@property(nonatomic, strong) NSMutableArray *allSubitems; + +@end + +@implementation LKS_CustomDisplayItemsMaker + +- (instancetype)initWithLayer:(CALayer *)layer saveAttrSetter:(BOOL)saveAttrSetter { + if (self = [super init]) { + self.layer = layer; + self.saveAttrSetter = saveAttrSetter; + self.allSubitems = [NSMutableArray array]; + } + return self; +} + +- (NSArray *)make { + if (!self.layer) { + NSAssert(NO, @""); + return nil; + } + NSMutableArray *selectors = [NSMutableArray array]; + [selectors addObject:@"lookin_customDebugInfos"]; + for (int i = 0; i < 5; i++) { + [selectors addObject:[NSString stringWithFormat:@"lookin_customDebugInfos_%@", @(i)]]; + } + + for (NSString *name in selectors) { + [self makeSubitemsForViewOrLayer:self.layer selectorName:name]; + + UIView *view = self.layer.lks_hostView; + if (view) { + [self makeSubitemsForViewOrLayer:view selectorName:name]; + } + } + + if (self.allSubitems.count) { + return self.allSubitems; + } else { + return nil; + } +} + +- (void)makeSubitemsForViewOrLayer:(id)viewOrLayer selectorName:(NSString *)selectorName { + if (!viewOrLayer || !selectorName.length) { + return; + } + if (![viewOrLayer isKindOfClass:[UIView class]] && ![viewOrLayer isKindOfClass:[CALayer class]]) { + return; + } + SEL selector = NSSelectorFromString(selectorName); + if (![viewOrLayer respondsToSelector:selector]) { + return; + } + NSMethodSignature *signature = [viewOrLayer methodSignatureForSelector:selector]; + if (signature.numberOfArguments > 2) { + NSAssert(NO, @"LookinServer - There should be no explicit parameters."); + return; + } + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; + [invocation setTarget:viewOrLayer]; + [invocation setSelector:selector]; + [invocation invoke]; + + // 小心这里的内存管理 + NSDictionary * __unsafe_unretained tempRawData; + [invocation getReturnValue:&tempRawData]; + NSDictionary *rawData = tempRawData; + + [self makeSubitemsFromRawData:rawData]; +} + +- (void)makeSubitemsFromRawData:(NSDictionary *)data { + if (!data || ![data isKindOfClass:[NSDictionary class]]) { + return; + } + NSArray *rawSubviews = data[@"subviews"]; + NSArray *newSubitems = [self displayItemsFromRawArray:rawSubviews]; + if (newSubitems) { + [self.allSubitems addObjectsFromArray:newSubitems]; + } +} + +- (NSArray *)displayItemsFromRawArray:(NSArray *)rawArray { + if (!rawArray || ![rawArray isKindOfClass:[NSArray class]]) { + return nil; + } + NSArray *items = [rawArray lookin_map:^id(NSUInteger idx, NSDictionary *rawDict) { + if (![rawDict isKindOfClass:[NSDictionary class]]) { + return nil; + } + return [self displayItemFromRawDict:rawDict]; + }]; + return items; +} + +- (LookinDisplayItem *)displayItemFromRawDict:(NSDictionary *)dict { + NSString *title = dict[@"title"]; + NSString *subtitle = dict[@"subtitle"]; + NSValue *frameValue = dict[@"frameInWindow"]; + NSArray *properties = dict[@"properties"]; + NSArray *subviews = dict[@"subviews"]; + NSString *danceSource = dict[@"lookin_source"]; + + if (![title isKindOfClass:[NSString class]]) { + return nil; + } + LookinDisplayItem *newItem = [LookinDisplayItem new]; + if (subviews && [subviews isKindOfClass:[NSArray class]]) { + newItem.subitems = [self displayItemsFromRawArray:subviews]; + } + newItem.isHidden = NO; + newItem.alpha = 1.0; + newItem.customInfo = [LookinCustomDisplayItemInfo new]; + newItem.customInfo.title = title; + newItem.customInfo.subtitle = subtitle; + newItem.customInfo.frameInWindow = frameValue; + newItem.customInfo.danceuiSource = danceSource; + newItem.customAttrGroupList = [LKS_CustomAttrGroupsMaker makeGroupsFromRawProperties:properties saveCustomSetter:self.saveAttrSetter]; + + return newItem; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Others/LKS_EventHandlerMaker.h b/Pods/LookinServer/Src/Main/Server/Others/LKS_EventHandlerMaker.h new file mode 100644 index 0000000..cc12c49 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Others/LKS_EventHandlerMaker.h @@ -0,0 +1,21 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LKS_EventHandlerMaker.h +// LookinServer +// +// Created by Li Kai on 2019/8/7. +// https://lookin.work +// + +#import "LookinDefines.h" + +@class LookinEventHandler; + +@interface LKS_EventHandlerMaker : NSObject + ++ (NSArray *)makeForView:(UIView *)view; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Others/LKS_EventHandlerMaker.m b/Pods/LookinServer/Src/Main/Server/Others/LKS_EventHandlerMaker.m new file mode 100644 index 0000000..200543e --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Others/LKS_EventHandlerMaker.m @@ -0,0 +1,215 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LKS_EventHandlerMaker.m +// LookinServer +// +// Created by Li Kai on 2019/8/7. +// https://lookin.work +// + +#import "LKS_EventHandlerMaker.h" +#import "LookinTuple.h" +#import "LookinEventHandler.h" +#import "LookinObject.h" +#import "LookinWeakContainer.h" +#import "LookinIvarTrace.h" +#import "LookinServerDefines.h" +#import "LKS_GestureTargetActionsSearcher.h" +#import "LKS_MultiplatformAdapter.h" + +@implementation LKS_EventHandlerMaker + ++ (NSArray *)makeForView:(UIView *)view { + if (!view) { + return nil; + } + + NSMutableArray *allHandlers = nil; + + if ([view isKindOfClass:[UIControl class]]) { + NSArray *targetActionHandlers = [self _targetActionHandlersForControl:(UIControl *)view]; + if (targetActionHandlers.count) { + if (!allHandlers) { + allHandlers = [NSMutableArray array]; + } + [allHandlers addObjectsFromArray:targetActionHandlers]; + } + } + + NSArray *gestureHandlers = [self _gestureHandlersForView:view]; + if (gestureHandlers.count) { + if (!allHandlers) { + allHandlers = [NSMutableArray array]; + } + [allHandlers addObjectsFromArray:gestureHandlers]; + } + + return allHandlers.copy; +} + ++ (NSArray *)_gestureHandlersForView:(UIView *)view { + if (view.gestureRecognizers.count == 0) { + return nil; + } + NSArray *handlers = [view.gestureRecognizers lookin_map:^id(NSUInteger idx, __kindof UIGestureRecognizer *recognizer) { + LookinEventHandler *handler = [LookinEventHandler new]; + handler.handlerType = LookinEventHandlerTypeGesture; + handler.eventName = NSStringFromClass([recognizer class]); + + NSArray *targetActionInfos = [LKS_GestureTargetActionsSearcher getTargetActionsFromRecognizer:recognizer]; + handler.targetActions = [targetActionInfos lookin_map:^id(NSUInteger idx, LookinTwoTuple *rawTuple) { + NSObject *target = ((LookinWeakContainer *)rawTuple.first).object; + if (!target) { + // 该 target 已被释放 + return nil; + } + LookinStringTwoTuple *newTuple = [LookinStringTwoTuple new]; + newTuple.first = [LKS_Helper descriptionOfObject:target]; + newTuple.second = (NSString *)rawTuple.second; + return newTuple; + }]; + handler.inheritedRecognizerName = [self _inheritedRecognizerNameForRecognizer:recognizer]; + handler.gestureRecognizerIsEnabled = recognizer.enabled; + if (recognizer.delegate) { + handler.gestureRecognizerDelegator = [LKS_Helper descriptionOfObject:recognizer.delegate]; + } + handler.recognizerIvarTraces = [recognizer.lks_ivarTraces lookin_map:^id(NSUInteger idx, LookinIvarTrace *trace) { + return [NSString stringWithFormat:@"(%@ *) -> %@", trace.hostClassName, trace.ivarName]; + }]; + + handler.recognizerOid = [recognizer lks_registerOid]; + return handler; + }]; + return handlers; +} + ++ (NSString *)_inheritedRecognizerNameForRecognizer:(UIGestureRecognizer *)recognizer { + if (!recognizer) { + NSAssert(NO, @""); + return nil; + } + + static NSArray *baseRecognizers; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + // 注意这里 UIScreenEdgePanGestureRecognizer 在 UIPanGestureRecognizer 前面,因为 UIScreenEdgePanGestureRecognizer 继承于 UIPanGestureRecognizer +#if TARGET_OS_TV + baseRecognizers = @[[UILongPressGestureRecognizer class], + [UIPanGestureRecognizer class], + [UISwipeGestureRecognizer class], + [UITapGestureRecognizer class]]; +#elif TARGET_OS_VISION + baseRecognizers = @[[UILongPressGestureRecognizer class], + [UIPanGestureRecognizer class], + [UISwipeGestureRecognizer class], + [UIRotationGestureRecognizer class], + [UIPinchGestureRecognizer class], + [UITapGestureRecognizer class]]; +#else + baseRecognizers = @[[UILongPressGestureRecognizer class], + [UIScreenEdgePanGestureRecognizer class], + [UIPanGestureRecognizer class], + [UISwipeGestureRecognizer class], + [UIRotationGestureRecognizer class], + [UIPinchGestureRecognizer class], + [UITapGestureRecognizer class]]; +#endif + + }); + + __block NSString *result = @"UIGestureRecognizer"; + [baseRecognizers enumerateObjectsUsingBlock:^(Class _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + if ([recognizer isMemberOfClass:obj]) { + // 自身就是基本款,则直接置为 nil + result = nil; + *stop = YES; + return; + } + if ([recognizer isKindOfClass:obj]) { + result = NSStringFromClass(obj); + *stop = YES; + return; + } + }]; + return result; +} + ++ (NSArray *)_targetActionHandlersForControl:(UIControl *)control { + static dispatch_once_t onceToken; + static NSArray *allEvents = nil; + dispatch_once(&onceToken,^{ + allEvents = @[@(UIControlEventTouchDown), @(UIControlEventTouchDownRepeat), @(UIControlEventTouchDragInside), @(UIControlEventTouchDragOutside), @(UIControlEventTouchDragEnter), @(UIControlEventTouchDragExit), @(UIControlEventTouchUpInside), @(UIControlEventTouchUpOutside), @(UIControlEventTouchCancel), @(UIControlEventValueChanged), @(UIControlEventEditingDidBegin), @(UIControlEventEditingChanged), @(UIControlEventEditingDidEnd), @(UIControlEventEditingDidEndOnExit)]; + if (@available(iOS 9.0, *)) { + allEvents = [allEvents arrayByAddingObject:@(UIControlEventPrimaryActionTriggered)]; + } + }); + + NSSet *allTargets = control.allTargets; + + if (!allTargets.count) { + return nil; + } + + NSMutableArray *handlers = [NSMutableArray array]; + + [allEvents enumerateObjectsUsingBlock:^(NSNumber * _Nonnull eventNum, NSUInteger idx, BOOL * _Nonnull stop) { + UIControlEvents event = [eventNum unsignedIntegerValue]; + + NSMutableArray *targetActions = [NSMutableArray array]; + + [allTargets enumerateObjectsUsingBlock:^(id _Nonnull target, BOOL * _Nonnull stop) { + NSArray *actions = [control actionsForTarget:target forControlEvent:event]; + [actions enumerateObjectsUsingBlock:^(NSString * _Nonnull action, NSUInteger idx, BOOL * _Nonnull stop) { + LookinStringTwoTuple *tuple = [LookinStringTwoTuple new]; + tuple.first = [LKS_Helper descriptionOfObject:target]; + tuple.second = action; + [targetActions addObject:tuple]; + }]; + }]; + + if (targetActions.count) { + LookinEventHandler *handler = [LookinEventHandler new]; + handler.handlerType = LookinEventHandlerTypeTargetAction; + handler.eventName = [self _nameFromControlEvent:event]; + handler.targetActions = targetActions.copy; + [handlers addObject:handler]; + } + }]; + + return handlers; +} + ++ (NSString *)_nameFromControlEvent:(UIControlEvents)event { + static dispatch_once_t onceToken; + static NSDictionary *eventsAndNames = nil; + dispatch_once(&onceToken,^{ + NSMutableDictionary *eventsAndNames_m = @{ + @(UIControlEventTouchDown): @"UIControlEventTouchDown", + @(UIControlEventTouchDownRepeat): @"UIControlEventTouchDownRepeat", + @(UIControlEventTouchDragInside): @"UIControlEventTouchDragInside", + @(UIControlEventTouchDragOutside): @"UIControlEventTouchDragOutside", + @(UIControlEventTouchDragEnter): @"UIControlEventTouchDragEnter", + @(UIControlEventTouchDragExit): @"UIControlEventTouchDragExit", + @(UIControlEventTouchUpInside): @"UIControlEventTouchUpInside", + @(UIControlEventTouchUpOutside): @"UIControlEventTouchUpOutside", + @(UIControlEventTouchCancel): @"UIControlEventTouchCancel", + @(UIControlEventValueChanged): @"UIControlEventValueChanged", + @(UIControlEventEditingDidBegin): @"UIControlEventEditingDidBegin", + @(UIControlEventEditingChanged): @"UIControlEventEditingChanged", + @(UIControlEventEditingDidEnd): @"UIControlEventEditingDidEnd", + @(UIControlEventEditingDidEndOnExit): @"UIControlEventEditingDidEndOnExit", + }.mutableCopy; + if (@available(iOS 9.0, *)) { + eventsAndNames_m[@(UIControlEventPrimaryActionTriggered)] = @"UIControlEventPrimaryActionTriggered"; + } + eventsAndNames = eventsAndNames_m.copy; + }); + + NSString *name = eventsAndNames[@(event)]; + return name; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Others/LKS_ExportManager.h b/Pods/LookinServer/Src/Main/Server/Others/LKS_ExportManager.h new file mode 100644 index 0000000..90fe53b --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Others/LKS_ExportManager.h @@ -0,0 +1,21 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LKS_ExportManager.h +// LookinServer +// +// Created by Li Kai on 2019/5/13. +// https://lookin.work +// + +#import + +@interface LKS_ExportManager : NSObject + ++ (instancetype)sharedInstance; + +- (void)exportAndShare; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Others/LKS_ExportManager.m b/Pods/LookinServer/Src/Main/Server/Others/LKS_ExportManager.m new file mode 100644 index 0000000..be040b9 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Others/LKS_ExportManager.m @@ -0,0 +1,193 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LKS_ExportManager.m +// LookinServer +// +// Created by Li Kai on 2019/5/13. +// https://lookin.work +// + +#import "LKS_ExportManager.h" +#import "UIViewController+LookinServer.h" +#import "LookinHierarchyInfo.h" +#import "LookinHierarchyFile.h" +#import "LookinAppInfo.h" +#import "LookinServerDefines.h" +#import "LKS_MultiplatformAdapter.h" + +@interface LKS_ExportManagerMaskView : UIView + +@property(nonatomic, strong) UIView *tipsView; +@property(nonatomic, strong) UILabel *firstLabel; +@property(nonatomic, strong) UILabel *secondLabel; +@property(nonatomic, strong) UILabel *thirdLabel; + +@end + +@implementation LKS_ExportManagerMaskView + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + self.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:.35]; + + self.tipsView = [UIView new]; + self.tipsView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:.88]; + self.tipsView.layer.cornerRadius = 6; + self.tipsView.layer.masksToBounds = YES; + [self addSubview:self.tipsView]; + + self.firstLabel = [UILabel new]; + self.firstLabel.text = LKS_Localized(@"Creating File…"); + self.firstLabel.textColor = [UIColor whiteColor]; + self.firstLabel.font = [UIFont boldSystemFontOfSize:14]; + self.firstLabel.textAlignment = NSTextAlignmentCenter; + self.firstLabel.numberOfLines = 0; + [self.tipsView addSubview:self.firstLabel]; + + self.secondLabel = [UILabel new]; + self.secondLabel.text = LKS_Localized(@"May take 8 or more seconds according to the UI complexity."); + self.secondLabel.textColor = [UIColor colorWithRed:173/255.0 green:180/255.0 blue:190/255.0 alpha:1]; + self.secondLabel.font = [UIFont systemFontOfSize:12]; + self.secondLabel.textAlignment = NSTextAlignmentLeft; + self.secondLabel.numberOfLines = 0; + [self.tipsView addSubview:self.secondLabel]; + + self.thirdLabel = [UILabel new]; + self.thirdLabel.text = LKS_Localized(@"The file can be opend by Lookin.app in macOS."); + self.thirdLabel.textColor = [UIColor colorWithRed:173/255.0 green:180/255.0 blue:190/255.0 alpha:1]; + self.thirdLabel.font = [UIFont systemFontOfSize:12]; + self.thirdLabel.textAlignment = NSTextAlignmentCenter; + self.thirdLabel.numberOfLines = 0; + [self.tipsView addSubview:self.thirdLabel]; + } + return self; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + + UIEdgeInsets insets = UIEdgeInsetsMake(8, 10, 8, 10); + CGFloat maxLabelWidth = self.bounds.size.width * .8 - insets.left - insets.right; + + CGSize firstSize = [self.firstLabel sizeThatFits:CGSizeMake(maxLabelWidth, CGFLOAT_MAX)]; + CGSize secondSize = [self.secondLabel sizeThatFits:CGSizeMake(maxLabelWidth, CGFLOAT_MAX)]; + CGSize thirdSize = [self.thirdLabel sizeThatFits:CGSizeMake(maxLabelWidth, CGFLOAT_MAX)]; + + CGFloat tipsWidth = MAX(MAX(firstSize.width, secondSize.width), thirdSize.width) + insets.left + insets.right; + + self.firstLabel.frame = CGRectMake(tipsWidth / 2.0 - firstSize.width / 2.0, insets.top, firstSize.width, firstSize.height); + self.secondLabel.frame = CGRectMake(tipsWidth / 2.0 - secondSize.width / 2.0, CGRectGetMaxY(self.firstLabel.frame) + 10, secondSize.width, secondSize.height); + self.thirdLabel.frame = CGRectMake(tipsWidth / 2.0 - thirdSize.width / 2.0, CGRectGetMaxY(self.secondLabel.frame) + 5, thirdSize.width, thirdSize.height); + + self.tipsView.frame = ({ + CGFloat height = CGRectGetMaxY(self.thirdLabel.frame) + insets.bottom; + CGRectMake(self.bounds.size.width / 2.0 - tipsWidth / 2.0, self.bounds.size.height / 2.0 - height / 2.0, tipsWidth, height); + }); +} + +@end + +@interface LKS_ExportManager () + +#if TARGET_OS_TV +#else +@property(nonatomic, strong) UIDocumentInteractionController *documentController; +#endif + +@property(nonatomic, strong) LKS_ExportManagerMaskView *maskView; + +@end + +@implementation LKS_ExportManager + ++ (instancetype)sharedInstance { + static dispatch_once_t onceToken; + static LKS_ExportManager *instance = nil; + dispatch_once(&onceToken,^{ + instance = [[super allocWithZone:NULL] init]; + }); + return instance; +} + ++ (id)allocWithZone:(struct _NSZone *)zone{ + return [self sharedInstance]; +} + +#if TARGET_OS_TV +- (void)exportAndShare { + NSAssert(NO, @"not supported"); +} +#else +- (void)exportAndShare { + + UIViewController *visibleVc = [UIViewController lks_visibleViewController]; + if (!visibleVc) { + NSLog(@"LookinServer - Failed to export because we didn't find any visible view controller."); + return; + } + + [[NSNotificationCenter defaultCenter] postNotificationName:@"Lookin_WillExport" object:nil]; + + if (!self.maskView) { + self.maskView = [LKS_ExportManagerMaskView new]; + } + [visibleVc.view.window addSubview:self.maskView]; + self.maskView.frame = visibleVc.view.window.bounds; + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + LookinHierarchyInfo *info = [LookinHierarchyInfo exportedInfo]; + LookinHierarchyFile *file = [LookinHierarchyFile new]; + file.serverVersion = info.serverVersion; + file.hierarchyInfo = info; + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:file]; + if (!data) { + return; + } + + NSString *fileName = ({ + NSString *timeString = ({ + NSDate *date = [NSDate date]; + NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; + [formatter setDateFormat:@"MMddHHmm"]; + [formatter stringFromDate:date]; + }); + NSString *iOSVersion = ({ + NSString *str = info.appInfo.osDescription; + NSUInteger dotIdx = [str rangeOfString:@"."].location; + if (dotIdx != NSNotFound) { + str = [str substringToIndex:dotIdx]; + } + str; + }); + [NSString stringWithFormat:@"%@_ios%@_%@.lookin", info.appInfo.appName, iOSVersion, timeString]; + }); + NSString *path = [NSString stringWithFormat:@"%@%@", NSTemporaryDirectory(), fileName]; + [data writeToFile:path atomically:YES]; + + [self.maskView removeFromSuperview]; + + if (!self.documentController) { + self.documentController = [UIDocumentInteractionController new]; + } + self.documentController.URL = [NSURL fileURLWithPath:path]; + if ([LKS_MultiplatformAdapter isiPad]) { + [self.documentController presentOpenInMenuFromRect:CGRectMake(0, 0, 1, 1) inView:visibleVc.view animated:YES]; + } else { + [self.documentController presentOpenInMenuFromRect:visibleVc.view.bounds inView:visibleVc.view animated:YES]; + } + + [[NSNotificationCenter defaultCenter] postNotificationName:@"Lookin_DidFinishExport" object:nil]; + +// [self.documentController presentOptionsMenuFromRect:visibleVc.view.bounds inView:visibleVc.view animated:YES]; + +// CFTimeInterval endTime = CACurrentMediaTime(); +// CFTimeInterval consumingTime = endTime - startTime; +// NSLog(@"LookinServer - 导出 UI 结构耗时:%@", @(consumingTime)); + }); +} +#endif + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Others/LKS_GestureTargetActionsSearcher.h b/Pods/LookinServer/Src/Main/Server/Others/LKS_GestureTargetActionsSearcher.h new file mode 100644 index 0000000..def0ca9 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Others/LKS_GestureTargetActionsSearcher.h @@ -0,0 +1,26 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LKS_GestureTargetActionsSearcher.h +// LookinServer +// +// Created by likai.123 on 2023/9/11. +// + +#import + +@class LookinTwoTuple; + +NS_ASSUME_NONNULL_BEGIN + +@interface LKS_GestureTargetActionsSearcher : NSObject + +/// 返回一个 UIGestureRecognizer 实例身上绑定的 target & action 信息 +/// tuple.first => LookinWeakContainer(包裹着 target),tuple.second => action(方法名字符串) ++ (NSArray *)getTargetActionsFromRecognizer:(UIGestureRecognizer *)recognizer; + +@end + +NS_ASSUME_NONNULL_END + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Others/LKS_GestureTargetActionsSearcher.m b/Pods/LookinServer/Src/Main/Server/Others/LKS_GestureTargetActionsSearcher.m new file mode 100644 index 0000000..0487bff --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Others/LKS_GestureTargetActionsSearcher.m @@ -0,0 +1,52 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LKS_GestureTargetActionsSearcher.m +// LookinServer +// +// Created by likai.123 on 2023/9/11. +// + +#import "LKS_GestureTargetActionsSearcher.h" +#import +#import "NSArray+Lookin.h" +#import "LookinTuple.h" +#import "LookinWeakContainer.h" + +@implementation LKS_GestureTargetActionsSearcher + ++ (NSArray *)getTargetActionsFromRecognizer:(UIGestureRecognizer *)recognizer { + if (!recognizer) { + return @[]; + } + // KVC 要放到 try catch 里面防止 Crash + @try { + NSArray* targetsList = [recognizer valueForKey:@"_targets"]; + if (!targetsList || targetsList.count == 0) { + return @[]; + } + // 数组元素对象是 UIGestureRecognizerTarget* + // 这个元素有两个属性,一个是名为 _target 的属性指向某个实例,另一个是名为 _action 的属性保存一个 SEL + NSArray* ret = [targetsList lookin_map:^id(NSUInteger idx, id targetBox) { + id targetObj = [targetBox valueForKey:@"_target"]; + if (!targetObj) { + return nil; + } + SEL action = ((SEL (*)(id, Ivar))object_getIvar)(targetBox, class_getInstanceVariable([targetBox class], "_action")); + + LookinTwoTuple* tuple = [LookinTwoTuple new]; + tuple.first = [LookinWeakContainer containerWithObject:targetObj]; + tuple.second = (action == NULL ? @"NULL" : NSStringFromSelector(action)); + return tuple; + }]; + return ret; + } + @catch (NSException * e) { + NSLog(@"LookinServer - %@", e); + return @[]; + } +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Others/LKS_Helper.h b/Pods/LookinServer/Src/Main/Server/Others/LKS_Helper.h new file mode 100644 index 0000000..dcb16d7 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Others/LKS_Helper.h @@ -0,0 +1,29 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LKS_Helper.h +// LookinServer +// +// Created by Li Kai on 2019/7/20. +// https://lookin.work +// + +#import "LookinDefines.h" + + + +#import + +#define LKS_Localized(stringKey) NSLocalizedStringFromTableInBundle(stringKey, nil, [NSBundle bundleForClass:self.class], nil) + +@interface LKS_Helper : NSObject + +/// 如果 object 为 nil 则返回字符串 “nil”,否则返回字符串格式类似于 (UIView *) ++ (NSString *)descriptionOfObject:(id)object; + +/// 返回当前的bundle ++ (NSBundle *)bundle; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Others/LKS_Helper.m b/Pods/LookinServer/Src/Main/Server/Others/LKS_Helper.m new file mode 100644 index 0000000..8a0368f --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Others/LKS_Helper.m @@ -0,0 +1,38 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LKS_Helper.m +// LookinServer +// +// Created by Li Kai on 2019/7/20. +// https://lookin.work +// + +#import "LKS_Helper.h" +#import "NSObject+LookinServer.h" + +@implementation LKS_Helper + ++ (NSString *)descriptionOfObject:(id)object { + if (!object) { + return @"nil"; + } + NSString *className = NSStringFromClass([object class]); + return [NSString stringWithFormat:@"(%@ *)", className]; +} + ++ (NSBundle *)bundle { + static id bundle = nil; + if (bundle != nil) { +#ifdef SPM_RESOURCE_BUNDLE_IDENTIFITER + bundle = [NSBundle bundleWithIdentifier:SPM_RESOURCE_BUNDLE_IDENTIFITER]; +#else + bundle = [NSBundle bundleForClass:self.class]; +#endif + } + return bundle; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Others/LKS_HierarchyDisplayItemsMaker.h b/Pods/LookinServer/Src/Main/Server/Others/LKS_HierarchyDisplayItemsMaker.h new file mode 100644 index 0000000..6e9bbe0 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Others/LKS_HierarchyDisplayItemsMaker.h @@ -0,0 +1,31 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LKS_HierarchyDisplayItemsMaker.h +// LookinServer +// +// Created by Li Kai on 2019/2/19. +// https://lookin.work +// + + + +#import "LookinDefines.h" + +@class LookinDisplayItem; + +@interface LKS_HierarchyDisplayItemsMaker : NSObject + +/// @param hasScreenshots 是否包含 soloScreenshots 和 groupScreenshot 属性 +/// @param hasAttrList 是否包含 attributesGroupList 属性 +/// @param lowQuality screenshots 是否为低质量(当 hasScreenshots 为 NO 时,该属性无意义) +/// @param readCustomInfo 是否读取 lookin_customDebugInfos,比如低版本的 Lookin 发请求时,就无需读取(因为 Lookin 解析不了、还可能出 Bug) +/// @param saveCustomSetter 是否要读取并保存用户给 attribute 配置的 custom setter ++ (NSArray *)itemsWithScreenshots:(BOOL)hasScreenshots attrList:(BOOL)hasAttrList lowImageQuality:(BOOL)lowQuality readCustomInfo:(BOOL)readCustomInfo saveCustomSetter:(BOOL)saveCustomSetter; + +/// 把 layer 的 sublayers 转换为 displayItem 数组并返回 ++ (NSArray *)subitemsOfLayer:(CALayer *)layer; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Others/LKS_HierarchyDisplayItemsMaker.m b/Pods/LookinServer/Src/Main/Server/Others/LKS_HierarchyDisplayItemsMaker.m new file mode 100644 index 0000000..4207a43 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Others/LKS_HierarchyDisplayItemsMaker.m @@ -0,0 +1,162 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LKS_HierarchyDisplayItemsMaker.m +// LookinServer +// +// Created by Li Kai on 2019/2/19. +// https://lookin.work +// + +#import "LKS_HierarchyDisplayItemsMaker.h" +#import "LookinDisplayItem.h" +#import "LKS_TraceManager.h" +#import "LKS_AttrGroupsMaker.h" +#import "LKS_EventHandlerMaker.h" +#import "LookinServerDefines.h" +#import "UIColor+LookinServer.h" +#import "LKSConfigManager.h" +#import "LKS_CustomAttrGroupsMaker.h" +#import "LKS_CustomDisplayItemsMaker.h" +#import "LKS_CustomAttrSetterManager.h" +#import "LKS_MultiplatformAdapter.h" + +@implementation LKS_HierarchyDisplayItemsMaker + ++ (NSArray *)itemsWithScreenshots:(BOOL)hasScreenshots attrList:(BOOL)hasAttrList lowImageQuality:(BOOL)lowQuality readCustomInfo:(BOOL)readCustomInfo saveCustomSetter:(BOOL)saveCustomSetter { + + [[LKS_TraceManager sharedInstance] reload]; + + NSArray *windows = [LKS_MultiplatformAdapter allWindows]; + NSMutableArray *resultArray = [NSMutableArray arrayWithCapacity:windows.count]; + [windows enumerateObjectsUsingBlock:^(__kindof UIWindow * _Nonnull window, NSUInteger idx, BOOL * _Nonnull stop) { + LookinDisplayItem *item = [self _displayItemWithLayer:window.layer screenshots:hasScreenshots attrList:hasAttrList lowImageQuality:lowQuality readCustomInfo:readCustomInfo saveCustomSetter:saveCustomSetter]; + item.representedAsKeyWindow = window.isKeyWindow; + if (item) { + [resultArray addObject:item]; + } + }]; + + return [resultArray copy]; +} + ++ (LookinDisplayItem *)_displayItemWithLayer:(CALayer *)layer screenshots:(BOOL)hasScreenshots attrList:(BOOL)hasAttrList lowImageQuality:(BOOL)lowQuality readCustomInfo:(BOOL)readCustomInfo saveCustomSetter:(BOOL)saveCustomSetter { + if (!layer) { + return nil; + } + + LookinDisplayItem *item = [LookinDisplayItem new]; + CGRect layerFrame = layer.frame; + UIView *hostView = layer.lks_hostView; + if (hostView && hostView.superview) { + layerFrame = [hostView.superview convertRect:layerFrame toView:nil]; + } + if ([self validateFrame:layerFrame]) { + item.frame = layer.frame; + } else { + NSLog(@"LookinServer - The layer frame(%@) seems really weird. Lookin will ignore it to avoid potential render error in Lookin.", NSStringFromCGRect(layer.frame)); + item.frame = CGRectZero; + } + item.bounds = layer.bounds; + if (hasScreenshots) { + item.soloScreenshot = [layer lks_soloScreenshotWithLowQuality:lowQuality]; + item.groupScreenshot = [layer lks_groupScreenshotWithLowQuality:lowQuality]; + item.screenshotEncodeType = LookinDisplayItemImageEncodeTypeNSData; + } + + if (hasAttrList) { + item.attributesGroupList = [LKS_AttrGroupsMaker attrGroupsForLayer:layer]; + LKS_CustomAttrGroupsMaker *maker = [[LKS_CustomAttrGroupsMaker alloc] initWithLayer:layer]; + [maker execute]; + item.customAttrGroupList = [maker getGroups]; + item.customDisplayTitle = [maker getCustomDisplayTitle]; + item.danceuiSource = [maker getDanceUISource]; + } + + item.isHidden = layer.isHidden; + item.alpha = layer.opacity; + item.layerObject = [LookinObject instanceWithObject:layer]; + item.shouldCaptureImage = [LKSConfigManager shouldCaptureScreenshotOfLayer:layer]; + + if (layer.lks_hostView) { + UIView *view = layer.lks_hostView; + item.viewObject = [LookinObject instanceWithObject:view]; + item.eventHandlers = [LKS_EventHandlerMaker makeForView:view]; + item.backgroundColor = view.backgroundColor; + + UIViewController* vc = [view lks_findHostViewController]; + if (vc) { + item.hostViewControllerObject = [LookinObject instanceWithObject:vc]; + } + } else { + item.backgroundColor = [UIColor lks_colorWithCGColor:layer.backgroundColor]; + } + + if (layer.sublayers.count) { + NSArray *sublayers = [layer.sublayers copy]; + NSMutableArray *allSubitems = [NSMutableArray arrayWithCapacity:sublayers.count]; + [sublayers enumerateObjectsUsingBlock:^(__kindof CALayer * _Nonnull sublayer, NSUInteger idx, BOOL * _Nonnull stop) { + LookinDisplayItem *sublayer_item = [self _displayItemWithLayer:sublayer screenshots:hasScreenshots attrList:hasAttrList lowImageQuality:lowQuality readCustomInfo:readCustomInfo saveCustomSetter:saveCustomSetter]; + if (sublayer_item) { + [allSubitems addObject:sublayer_item]; + } + }]; + item.subitems = [allSubitems copy]; + } + if (readCustomInfo) { + NSArray *customSubitems = [[[LKS_CustomDisplayItemsMaker alloc] initWithLayer:layer saveAttrSetter:saveCustomSetter] make]; + if (customSubitems.count > 0) { + if (item.subitems) { + item.subitems = [item.subitems arrayByAddingObjectsFromArray:customSubitems]; + } else { + item.subitems = customSubitems; + } + } + } + + return item; +} + ++ (NSArray *)subitemsOfLayer:(CALayer *)layer { + if (!layer || layer.sublayers.count == 0) { + return @[]; + } + [[LKS_TraceManager sharedInstance] reload]; + + NSMutableArray *resultSubitems = [NSMutableArray array]; + + NSArray *sublayers = [layer.sublayers copy]; + [sublayers enumerateObjectsUsingBlock:^(__kindof CALayer * _Nonnull sublayer, NSUInteger idx, BOOL * _Nonnull stop) { + LookinDisplayItem *sublayer_item = [self _displayItemWithLayer:sublayer screenshots:NO attrList:NO lowImageQuality:NO readCustomInfo:YES saveCustomSetter:YES]; + if (sublayer_item) { + [resultSubitems addObject:sublayer_item]; + } + }]; + + NSArray *customSubitems = [[[LKS_CustomDisplayItemsMaker alloc] initWithLayer:layer saveAttrSetter:YES] make]; + if (customSubitems.count > 0) { + [resultSubitems addObjectsFromArray:customSubitems]; + } + + return resultSubitems; +} + ++ (BOOL)validateFrame:(CGRect)frame { + return !CGRectIsNull(frame) && !CGRectIsInfinite(frame) && ![self cgRectIsNaN:frame] && ![self cgRectIsInf:frame] && ![self cgRectIsUnreasonable:frame]; +} + ++ (BOOL)cgRectIsNaN:(CGRect)rect { + return isnan(rect.origin.x) || isnan(rect.origin.y) || isnan(rect.size.width) || isnan(rect.size.height); +} + ++ (BOOL)cgRectIsInf:(CGRect)rect { + return isinf(rect.origin.x) || isinf(rect.origin.y) || isinf(rect.size.width) || isinf(rect.size.height); +} + ++ (BOOL)cgRectIsUnreasonable:(CGRect)rect { + return ABS(rect.origin.x) > 100000 || ABS(rect.origin.y) > 100000 || rect.size.width < 0 || rect.size.height < 0 || rect.size.width > 100000 || rect.size.height > 100000; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Others/LKS_MultiplatformAdapter.h b/Pods/LookinServer/Src/Main/Server/Others/LKS_MultiplatformAdapter.h new file mode 100644 index 0000000..dc13f64 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Others/LKS_MultiplatformAdapter.h @@ -0,0 +1,30 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER +// +// LKS_MultiplatformAdapter.h +// +// +// Created by nixjiang on 2024/3/12. +// + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface LKS_MultiplatformAdapter : NSObject + ++ (UIWindow *)keyWindow; + ++ (NSArray *)allWindows; + ++ (CGRect)mainScreenBounds; + ++ (CGFloat)mainScreenScale; + ++ (BOOL)isiPad; + +@end + +NS_ASSUME_NONNULL_END + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Others/LKS_MultiplatformAdapter.m b/Pods/LookinServer/Src/Main/Server/Others/LKS_MultiplatformAdapter.m new file mode 100644 index 0000000..8c04b98 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Others/LKS_MultiplatformAdapter.m @@ -0,0 +1,92 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER +// +// LKS_MultiplatformAdapter.m +// +// +// Created by nixjiang on 2024/3/12. +// + +#import "LKS_MultiplatformAdapter.h" +#import + +@implementation LKS_MultiplatformAdapter + ++ (BOOL)isiPad { + static BOOL s_isiPad = NO; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSString *nsModel = [UIDevice currentDevice].model; + s_isiPad = [nsModel hasPrefix:@"iPad"]; + }); + + return s_isiPad; +} + ++ (CGRect)mainScreenBounds { +#if TARGET_OS_VISION + return [LKS_MultiplatformAdapter getFirstActiveWindowScene].coordinateSpace.bounds; +#else + return [UIScreen mainScreen].bounds; +#endif +} + ++ (CGFloat)mainScreenScale { +#if TARGET_OS_VISION + return 2.f; +#else + return [UIScreen mainScreen].scale; +#endif +} + +#if TARGET_OS_VISION ++ (UIWindowScene *)getFirstActiveWindowScene { + for (UIScene *scene in UIApplication.sharedApplication.connectedScenes) { + if (![scene isKindOfClass:UIWindowScene.class]) { + continue; + } + UIWindowScene *windowScene = (UIWindowScene *)scene; + if (windowScene.activationState == UISceneActivationStateForegroundActive) { + return windowScene; + } + } + return nil; +} +#endif + ++ (UIWindow *)keyWindow { +#if TARGET_OS_VISION + return [self getFirstActiveWindowScene].keyWindow; +#else + return [UIApplication sharedApplication].keyWindow; +#endif +} + ++ (NSArray *)allWindows { +#if TARGET_OS_VISION + NSMutableArray *windows = [NSMutableArray new]; + for (UIScene *scene in + UIApplication.sharedApplication.connectedScenes) { + if (![scene isKindOfClass:UIWindowScene.class]) { + continue; + } + UIWindowScene *windowScene = (UIWindowScene *)scene; + [windows addObjectsFromArray:windowScene.windows]; + + // 以UIModalPresentationFormSheet形式展示的页面由系统私有window承载,不出现在scene.windows,不过可以从scene.keyWindow中获取 + if (![windows containsObject:windowScene.keyWindow]) { + if (![NSStringFromClass(windowScene.keyWindow.class) containsString:@"HUD"]) { + [windows addObject:windowScene.keyWindow]; + } + } + } + + return [windows copy]; +#else + return [[UIApplication sharedApplication].windows copy]; +#endif +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Others/LKS_ObjectRegistry.h b/Pods/LookinServer/Src/Main/Server/Others/LKS_ObjectRegistry.h new file mode 100644 index 0000000..64a1252 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Others/LKS_ObjectRegistry.h @@ -0,0 +1,23 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LKS_ObjectRegistry.h +// LookinServer +// +// Created by Li Kai on 2019/4/21. +// https://lookin.work +// + +#import + +@interface LKS_ObjectRegistry : NSObject + ++ (instancetype)sharedInstance; + +- (unsigned long)addObject:(NSObject *)object; + +- (NSObject *)objectWithOid:(unsigned long)oid; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Others/LKS_ObjectRegistry.m b/Pods/LookinServer/Src/Main/Server/Others/LKS_ObjectRegistry.m new file mode 100644 index 0000000..e651cc3 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Others/LKS_ObjectRegistry.m @@ -0,0 +1,62 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LKS_ObjectRegistry.m +// LookinServer +// +// Created by Li Kai on 2019/4/21. +// https://lookin.work +// + +#import "LKS_ObjectRegistry.h" +#import + +@interface LKS_ObjectRegistry () + +@property(nonatomic, strong) NSPointerArray *data; + +@end + +@implementation LKS_ObjectRegistry + ++ (instancetype)sharedInstance { + static dispatch_once_t onceToken; + static LKS_ObjectRegistry *instance = nil; + dispatch_once(&onceToken,^{ + instance = [[super allocWithZone:NULL] init]; + }); + return instance; +} + ++ (id)allocWithZone:(struct _NSZone *)zone{ + return [self sharedInstance]; +} + +- (instancetype)init { + if (self = [super init]) { + self.data = [NSPointerArray weakObjectsPointerArray]; + // index 为 0 用 Null 填充 + self.data.count = 1; + } + return self; +} + +- (unsigned long)addObject:(NSObject *)object { + if (!object) { + return 0; + } + [self.data addPointer:(void *)object]; + return self.data.count - 1; +} + +- (NSObject *)objectWithOid:(unsigned long)oid { + if (self.data.count <= oid) { + return nil; + } + id object = [self.data pointerAtIndex:oid]; + return object; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Others/LKS_TraceManager.h b/Pods/LookinServer/Src/Main/Server/Others/LKS_TraceManager.h new file mode 100644 index 0000000..aac9ef7 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Others/LKS_TraceManager.h @@ -0,0 +1,27 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LKS_TraceManager.h +// LookinServer +// +// Created by Li Kai on 2019/5/5. +// https://lookin.work +// + + + +#import + +@class LookinIvarTrace; + +@interface LKS_TraceManager : NSObject + ++ (instancetype)sharedInstance; + +- (void)reload; + +- (void)addSearchTarger:(id)target; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Others/LKS_TraceManager.m b/Pods/LookinServer/Src/Main/Server/Others/LKS_TraceManager.m new file mode 100644 index 0000000..b90fdf3 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Others/LKS_TraceManager.m @@ -0,0 +1,310 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LKS_TraceManager.m +// LookinServer +// +// Created by Li Kai on 2019/5/5. +// https://lookin.work +// + +#import "LKS_TraceManager.h" +#import +#import "LookinIvarTrace.h" +#import "LookinServerDefines.h" +#import "LookinWeakContainer.h" +#import "LKS_MultiplatformAdapter.h" + +#ifdef LOOKIN_SERVER_SWIFT_ENABLED + +#if __has_include() + #import + #define LOOKIN_SERVER_SWIFT_ENABLED_SUCCESSFULLY +#elif __has_include("LookinServer-Swift.h") + #import "LookinServer-Swift.h" + #define LOOKIN_SERVER_SWIFT_ENABLED_SUCCESSFULLY +#endif + +#endif + +#ifdef SPM_LOOKIN_SERVER_ENABLED +@import LookinServerSwift; +#define LOOKIN_SERVER_SWIFT_ENABLED_SUCCESSFULLY +#endif + +@interface LKS_TraceManager () + +@property(nonatomic, strong) NSMutableArray *searchTargets; + +@end + +@implementation LKS_TraceManager + ++ (instancetype)sharedInstance { + static dispatch_once_t onceToken; + static LKS_TraceManager *instance = nil; + dispatch_once(&onceToken,^{ + instance = [[super allocWithZone:NULL] init]; + }); + return instance; +} + ++ (id)allocWithZone:(struct _NSZone *)zone { + return [self sharedInstance]; +} + +- (void)addSearchTarger:(id)target { + if (!target) { + return; + } + if (!self.searchTargets) { + self.searchTargets = [NSMutableArray array]; + } + LookinWeakContainer *container = [LookinWeakContainer containerWithObject:target]; + [self.searchTargets addObject:container]; +} + +- (void)reload { + // 把旧的先都清理掉 + [NSObject lks_clearAllObjectsTraces]; + + [self.searchTargets enumerateObjectsUsingBlock:^(LookinWeakContainer * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + if (!obj.object) { + return; + } + [self _markIVarsInAllClassLevelsOfObject:obj.object]; + }]; + + [[LKS_MultiplatformAdapter allWindows] enumerateObjectsUsingBlock:^(__kindof UIWindow * _Nonnull window, NSUInteger idx, BOOL * _Nonnull stop) { + [self _addTraceForLayersRootedByLayer:window.layer]; + }]; +} + +- (void)_addTraceForLayersRootedByLayer:(CALayer *)layer { + UIView *view = layer.lks_hostView; + + if ([view.superview lks_isChildrenViewOfTabBar]) { + view.lks_isChildrenViewOfTabBar = YES; + } else if ([view isKindOfClass:[UITabBar class]]) { + view.lks_isChildrenViewOfTabBar = YES; + } + + if (view) { + [self _markIVarsInAllClassLevelsOfObject:view]; + UIViewController* vc = [view lks_findHostViewController]; + if (vc) { + [self _markIVarsInAllClassLevelsOfObject:vc]; + } + + [self _buildSpecialTraceForView:view]; + } else { + [self _markIVarsInAllClassLevelsOfObject:layer]; + } + + [[layer.sublayers copy] enumerateObjectsUsingBlock:^(__kindof CALayer * _Nonnull sublayer, NSUInteger idx, BOOL * _Nonnull stop) { + [self _addTraceForLayersRootedByLayer:sublayer]; + }]; +} + +- (void)_buildSpecialTraceForView:(UIView *)view { + UIViewController* vc = [view lks_findHostViewController]; + if (vc) { + view.lks_specialTrace = [NSString stringWithFormat:@"%@.view", NSStringFromClass(vc.class)]; + + } else if ([view isKindOfClass:[UIWindow class]]) { + CGFloat currentWindowLevel = ((UIWindow *)view).windowLevel; + + if (((UIWindow *)view).isKeyWindow) { + view.lks_specialTrace = [NSString stringWithFormat:@"KeyWindow ( Level: %@ )", @(currentWindowLevel)]; + } else { + view.lks_specialTrace = [NSString stringWithFormat:@"WindowLevel: %@", @(currentWindowLevel)]; + } + } else if ([view isKindOfClass:[UITableViewCell class]]) { + ((UITableViewCell *)view).backgroundView.lks_specialTrace = @"cell.backgroundView"; + ((UITableViewCell *)view).accessoryView.lks_specialTrace = @"cell.accessoryView"; + + } else if ([view isKindOfClass:[UITableView class]]) { + UITableView *tableView = (UITableView *)view; + + NSMutableArray *relatedSectionIdx = [NSMutableArray array]; + [[tableView visibleCells] enumerateObjectsUsingBlock:^(__kindof UITableViewCell * _Nonnull cell, NSUInteger idx, BOOL * _Nonnull stop) { + NSIndexPath *indexPath = [tableView indexPathForCell:cell]; + cell.lks_specialTrace = [NSString stringWithFormat:@"{ sec:%@, row:%@ }", @(indexPath.section), @(indexPath.row)]; + + if (![relatedSectionIdx containsObject:@(indexPath.section)]) { + [relatedSectionIdx addObject:@(indexPath.section)]; + } + }]; + + [relatedSectionIdx enumerateObjectsUsingBlock:^(NSNumber * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + NSUInteger secIdx = [obj unsignedIntegerValue]; + UIView *secHeaderView = [tableView headerViewForSection:secIdx]; + secHeaderView.lks_specialTrace = [NSString stringWithFormat:@"sectionHeader { sec: %@ }", @(secIdx)]; + + UIView *secFooterView = [tableView footerViewForSection:secIdx]; + secFooterView.lks_specialTrace = [NSString stringWithFormat:@"sectionFooter { sec: %@ }", @(secIdx)]; + }]; + + } else if ([view isKindOfClass:[UICollectionView class]]) { + UICollectionView *collectionView = (UICollectionView *)view; + collectionView.backgroundView.lks_specialTrace = @"collectionView.backgroundView"; + + if (@available(iOS 9.0, *)) { + [[collectionView indexPathsForVisibleSupplementaryElementsOfKind:UICollectionElementKindSectionHeader] enumerateObjectsUsingBlock:^(NSIndexPath * _Nonnull indexPath, NSUInteger idx, BOOL * _Nonnull stop) { + UIView *headerView = [collectionView supplementaryViewForElementKind:UICollectionElementKindSectionHeader atIndexPath:indexPath]; + headerView.lks_specialTrace = [NSString stringWithFormat:@"sectionHeader { sec:%@ }", @(indexPath.section)]; + }]; + [[collectionView indexPathsForVisibleSupplementaryElementsOfKind:UICollectionElementKindSectionFooter] enumerateObjectsUsingBlock:^(NSIndexPath * _Nonnull indexPath, NSUInteger idx, BOOL * _Nonnull stop) { + UIView *footerView = [collectionView supplementaryViewForElementKind:UICollectionElementKindSectionFooter atIndexPath:indexPath]; + footerView.lks_specialTrace = [NSString stringWithFormat:@"sectionFooter { sec:%@ }", @(indexPath.section)]; + }]; + } + + [[collectionView visibleCells] enumerateObjectsUsingBlock:^(__kindof UICollectionViewCell * _Nonnull cell, NSUInteger idx, BOOL * _Nonnull stop) { + NSIndexPath *indexPath = [collectionView indexPathForCell:cell]; + cell.lks_specialTrace = [NSString stringWithFormat:@"{ item:%@, sec:%@ }", @(indexPath.item), @(indexPath.section)]; + }]; + + } else if ([view isKindOfClass:[UITableViewHeaderFooterView class]]) { + UITableViewHeaderFooterView *headerFooterView = (UITableViewHeaderFooterView *)view; + headerFooterView.textLabel.lks_specialTrace = @"sectionHeaderFooter.textLabel"; + headerFooterView.detailTextLabel.lks_specialTrace = @"sectionHeaderFooter.detailTextLabel"; + } +} + +- (void)_markIVarsInAllClassLevelsOfObject:(NSObject *)object { + [self _markIVarsOfObject:object class:object.class]; +#ifdef LOOKIN_SERVER_SWIFT_ENABLED_SUCCESSFULLY + [LKS_SwiftTraceManager swiftMarkIVarsOfObject:object]; +#endif +} + +- (void)_markIVarsOfObject:(NSObject *)hostObject class:(Class)targetClass { + if (!targetClass) { + return; + } + + NSArray *prefixesToTerminateRecursion = @[@"NSObject", @"UIResponder", @"UIButton", @"UIButtonLabel"]; + BOOL hasPrefix = [prefixesToTerminateRecursion lookin_any:^BOOL(NSString *prefix) { + return [NSStringFromClass(targetClass) hasPrefix:prefix]; + }]; + if (hasPrefix) { + return; + } + + unsigned int outCount = 0; + Ivar *ivars = class_copyIvarList(targetClass, &outCount); + for (unsigned int i = 0; i < outCount; i ++) { + Ivar ivar = ivars[i]; + NSString *ivarType = [[NSString alloc] lookin_safeInitWithUTF8String:ivar_getTypeEncoding(ivar)]; + if (![ivarType hasPrefix:@"@"] || ivarType.length <= 3) { + continue; + } + NSString *ivarClassName = [ivarType substringWithRange:NSMakeRange(2, ivarType.length - 3)]; + Class ivarClass = NSClassFromString(ivarClassName); + if (![ivarClass isSubclassOfClass:[UIView class]] + && ![ivarClass isSubclassOfClass:[CALayer class]] + && ![ivarClass isSubclassOfClass:[UIViewController class]] + && ![ivarClass isSubclassOfClass:[UIGestureRecognizer class]]) { + continue; + } + const char * ivarNameChar = ivar_getName(ivar); + if (!ivarNameChar) { + continue; + } + // 这个 ivarObject 可能的类型:UIView, CALayer, UIViewController, UIGestureRecognizer + NSObject *ivarObject = object_getIvar(hostObject, ivar); + if (!ivarObject || ![ivarObject isKindOfClass:[NSObject class]]) { + continue; + } + + LookinIvarTrace *ivarTrace = [LookinIvarTrace new]; + ivarTrace.hostObject = hostObject; + ivarTrace.hostClassName = [self makeDisplayClassNameWithSuper:targetClass childClass:hostObject.class]; + ivarTrace.ivarName = [[NSString alloc] lookin_safeInitWithUTF8String:ivarNameChar]; + + if (hostObject == ivarObject) { + ivarTrace.relation = LookinIvarTraceRelationValue_Self; + } else if ([hostObject isKindOfClass:[UIView class]]) { + CALayer *ivarLayer = nil; + if ([ivarObject isKindOfClass:[CALayer class]]) { + ivarLayer = (CALayer *)ivarObject; + } else if ([ivarObject isKindOfClass:[UIView class]]) { + ivarLayer = ((UIView *)ivarObject).layer; + } + if (ivarLayer && (ivarLayer.superlayer == ((UIView *)hostObject).layer)) { + ivarTrace.relation = @"superview"; + } + } + + if ([LKS_InvalidIvarTraces() containsObject:ivarTrace]) { + continue; + } + + if (![ivarObject respondsToSelector:@selector(lks_ivarTraces)] || ![ivarObject respondsToSelector:@selector(setLks_ivarTraces:)]) { + continue; + } + if (!ivarObject.lks_ivarTraces) { + ivarObject.lks_ivarTraces = [NSArray array]; + } + if (![ivarObject.lks_ivarTraces containsObject:ivarTrace]) { + ivarObject.lks_ivarTraces = [ivarObject.lks_ivarTraces arrayByAddingObject:ivarTrace]; + } + } + free(ivars); + + Class superClass = [targetClass superclass]; + [self _markIVarsOfObject:hostObject class:superClass]; +} + +// 比如 superClass 可能是 UIView,而 childClass 可能是 UIButton +- (NSString *)makeDisplayClassNameWithSuper:(Class)superClass childClass:(Class)childClass { + NSString *superName = NSStringFromClass(superClass); + if (!childClass) { + return superName; + } + NSString *childName = NSStringFromClass(childClass); + if ([childName isEqualToString:superName]) { + return superName; + } + return [NSString stringWithFormat:@"%@ : %@", childName, superName]; +} + +static NSSet *LKS_InvalidIvarTraces(void) { + static NSSet *list; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSMutableSet *set = [NSMutableSet set]; + + [set addObject:({ + LookinIvarTrace *trace = [LookinIvarTrace new]; + trace.hostClassName = @"UIView"; + trace.ivarName = @"_window"; + trace; + })]; + [set addObject:({ + LookinIvarTrace *trace = [LookinIvarTrace new]; + trace.hostClassName = @"UIViewController"; + trace.ivarName = @"_view"; + trace; + })]; + [set addObject:({ + LookinIvarTrace *trace = [LookinIvarTrace new]; + trace.hostClassName = @"UIView"; + trace.ivarName = @"_viewDelegate"; + trace; + })]; + [set addObject:({ + LookinIvarTrace *trace = [LookinIvarTrace new]; + trace.hostClassName = @"UIViewController"; + trace.ivarName = @"_parentViewController"; + trace; + })]; + list = set.copy; + }); + return list; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Server/Others/LookinServerDefines.h b/Pods/LookinServer/Src/Main/Server/Others/LookinServerDefines.h new file mode 100644 index 0000000..53f7a7c --- /dev/null +++ b/Pods/LookinServer/Src/Main/Server/Others/LookinServerDefines.h @@ -0,0 +1,23 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinServer_PrefixHeader.pch +// LookinServer +// +// Created by Li Kai on 2018/12/21. +// https://lookin.work +// + +#import "TargetConditionals.h" +#import "LookinDefines.h" +#import "LKS_Helper.h" +#import "NSObject+LookinServer.h" +#import "NSArray+Lookin.h" +#import "NSSet+Lookin.h" +#import "CALayer+Lookin.h" +#import "UIView+LookinServer.h" +#import "CALayer+LookinServer.h" +#import "NSObject+Lookin.h" +#import "NSString+Lookin.h" + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/Category/CALayer+Lookin.h b/Pods/LookinServer/Src/Main/Shared/Category/CALayer+Lookin.h new file mode 100644 index 0000000..815459a --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/Category/CALayer+Lookin.h @@ -0,0 +1,23 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// CALayer+Lookin.h +// Lookin +// +// Created by Li Kai on 2018/8/4. +// https://lookin.work +// + +#import "LookinDefines.h" + + + +#import + +@interface CALayer (Lookin) + +- (void)lookin_removeImplicitAnimations; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/Category/CALayer+Lookin.m b/Pods/LookinServer/Src/Main/Shared/Category/CALayer+Lookin.m new file mode 100644 index 0000000..e756fc4 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/Category/CALayer+Lookin.m @@ -0,0 +1,70 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// CALayer+Lookin.m +// Lookin +// +// Created by Li Kai on 2018/8/4. +// https://lookin.work +// + + + +#import "CALayer+Lookin.h" + +@implementation CALayer (Lookin) + +- (void)lookin_removeImplicitAnimations { + NSMutableDictionary> *actions = @{NSStringFromSelector(@selector(bounds)): [NSNull null], + NSStringFromSelector(@selector(position)): [NSNull null], + NSStringFromSelector(@selector(zPosition)): [NSNull null], + NSStringFromSelector(@selector(anchorPoint)): [NSNull null], + NSStringFromSelector(@selector(anchorPointZ)): [NSNull null], + NSStringFromSelector(@selector(transform)): [NSNull null], + NSStringFromSelector(@selector(sublayerTransform)): [NSNull null], + NSStringFromSelector(@selector(masksToBounds)): [NSNull null], + NSStringFromSelector(@selector(contents)): [NSNull null], + NSStringFromSelector(@selector(contentsRect)): [NSNull null], + NSStringFromSelector(@selector(contentsScale)): [NSNull null], + NSStringFromSelector(@selector(contentsCenter)): [NSNull null], + NSStringFromSelector(@selector(minificationFilterBias)): [NSNull null], + NSStringFromSelector(@selector(backgroundColor)): [NSNull null], + NSStringFromSelector(@selector(cornerRadius)): [NSNull null], + NSStringFromSelector(@selector(borderWidth)): [NSNull null], + NSStringFromSelector(@selector(borderColor)): [NSNull null], + NSStringFromSelector(@selector(opacity)): [NSNull null], + NSStringFromSelector(@selector(compositingFilter)): [NSNull null], + NSStringFromSelector(@selector(filters)): [NSNull null], + NSStringFromSelector(@selector(backgroundFilters)): [NSNull null], + NSStringFromSelector(@selector(shouldRasterize)): [NSNull null], + NSStringFromSelector(@selector(rasterizationScale)): [NSNull null], + NSStringFromSelector(@selector(shadowColor)): [NSNull null], + NSStringFromSelector(@selector(shadowOpacity)): [NSNull null], + NSStringFromSelector(@selector(shadowOffset)): [NSNull null], + NSStringFromSelector(@selector(shadowRadius)): [NSNull null], + NSStringFromSelector(@selector(shadowPath)): [NSNull null]}.mutableCopy; + + if ([self isKindOfClass:[CAShapeLayer class]]) { + [actions addEntriesFromDictionary:@{NSStringFromSelector(@selector(path)): [NSNull null], + NSStringFromSelector(@selector(fillColor)): [NSNull null], + NSStringFromSelector(@selector(strokeColor)): [NSNull null], + NSStringFromSelector(@selector(strokeStart)): [NSNull null], + NSStringFromSelector(@selector(strokeEnd)): [NSNull null], + NSStringFromSelector(@selector(lineWidth)): [NSNull null], + NSStringFromSelector(@selector(miterLimit)): [NSNull null], + NSStringFromSelector(@selector(lineDashPhase)): [NSNull null]}]; + } + + if ([self isKindOfClass:[CAGradientLayer class]]) { + [actions addEntriesFromDictionary:@{NSStringFromSelector(@selector(colors)): [NSNull null], + NSStringFromSelector(@selector(locations)): [NSNull null], + NSStringFromSelector(@selector(startPoint)): [NSNull null], + NSStringFromSelector(@selector(endPoint)): [NSNull null]}]; + } + + self.actions = actions; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/Category/Color+Lookin.h b/Pods/LookinServer/Src/Main/Shared/Category/Color+Lookin.h new file mode 100644 index 0000000..9a49ab9 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/Category/Color+Lookin.h @@ -0,0 +1,27 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// Color+Lookin.h +// LookinShared +// +// Created by 李凯 on 2022/4/2. +// + +#import + +#if TARGET_OS_IPHONE + +#elif TARGET_OS_MAC + +@interface NSColor (Lookin) + ++ (instancetype)lookin_colorFromRGBAComponents:(NSArray *)components; + +- (NSArray *)lookin_rgbaComponents; + +@end + +#endif + + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/Category/Color+Lookin.m b/Pods/LookinServer/Src/Main/Shared/Category/Color+Lookin.m new file mode 100644 index 0000000..4f5ede1 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/Category/Color+Lookin.m @@ -0,0 +1,42 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// Color+Lookin.m +// LookinShared +// +// Created by 李凯 on 2022/4/2. +// + +#import "Image+Lookin.h" + +#if TARGET_OS_IPHONE + +#elif TARGET_OS_MAC + +@implementation NSColor (Lookin) + ++ (instancetype)lookin_colorFromRGBAComponents:(NSArray *)components { + if (!components) { + return nil; + } + if (components.count != 4) { + NSAssert(NO, @""); + return nil; + } + NSColor *color = [NSColor colorWithRed:components[0].doubleValue green:components[1].doubleValue blue:components[2].doubleValue alpha:components[3].doubleValue]; + return color; +} + +- (NSArray *)lookin_rgbaComponents { + NSColor *rgbColor = [self colorUsingColorSpace:NSColorSpace.sRGBColorSpace]; + CGFloat r, g, b, a; + [rgbColor getRed:&r green:&g blue:&b alpha:&a]; + NSArray *rgba = @[@(r), @(g), @(b), @(a)]; + return rgba; +} + +@end + +#endif + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/Category/Image+Lookin.h b/Pods/LookinServer/Src/Main/Shared/Category/Image+Lookin.h new file mode 100644 index 0000000..7fe33c8 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/Category/Image+Lookin.h @@ -0,0 +1,25 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// Image+Lookin.h +// LookinShared +// +// Created by 李凯 on 2022/4/2. +// + +#import + +#if TARGET_OS_IPHONE + +#elif TARGET_OS_MAC + +@interface NSImage (LookinClient) + +- (NSData *)lookin_data; + +@end + +#endif + + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/Category/Image+Lookin.m b/Pods/LookinServer/Src/Main/Shared/Category/Image+Lookin.m new file mode 100644 index 0000000..d285d54 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/Category/Image+Lookin.m @@ -0,0 +1,26 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// Image+Lookin.m +// LookinShared +// +// Created by 李凯 on 2022/4/2. +// + +#import "Image+Lookin.h" + +#if TARGET_OS_IPHONE + +#elif TARGET_OS_MAC + +@implementation NSImage (LookinClient) + +- (NSData *)lookin_data { + return [self TIFFRepresentation]; +} + +@end + +#endif + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/Category/NSArray+Lookin.h b/Pods/LookinServer/Src/Main/Shared/Category/NSArray+Lookin.h new file mode 100644 index 0000000..a66e02a --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/Category/NSArray+Lookin.h @@ -0,0 +1,72 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// NSArray+Lookin.h +// Lookin +// +// Created by Li Kai on 2018/9/3. +// https://lookin.work +// + +#import "LookinDefines.h" + + + +#import +#import + +@interface NSArray<__covariant ValueType> (Lookin) + +/** + 初始化一个新的 NSArray 并返回,新数组的长度为 count,如果当前数组长度比 count 小则会补充新元素(被补充的元素由 addBlock 返回),如果当前数组长度比 count 大则会舍弃多余的元素,被舍弃的元素会作为参数传入 removeBlock。最终,新数组的所有元素均会作为参数被传入 doBlock。 + */ +- (NSArray *)lookin_resizeWithCount:(NSUInteger)count add:(ValueType (^)(NSUInteger idx))addBlock remove:(void (^)(NSUInteger idx, ValueType obj))removeBlock doNext:(void (^)(NSUInteger idx, ValueType obj))doBlock __attribute__((warn_unused_result)); + ++ (NSArray *)lookin_arrayWithCount:(NSUInteger)count block:(id (^)(NSUInteger idx))block; + +/** + 检查 index 位置是否有元素存在 + */ +- (BOOL)lookin_hasIndex:(NSInteger)index; + +- (NSArray *)lookin_map:(id (^)(NSUInteger idx, ValueType value))block; + +- (NSArray *)lookin_filter:(BOOL (^)( ValueType obj))block; + +- (ValueType)lookin_firstFiltered:(BOOL (^)(ValueType obj))block; + +/// 返回最后一个 block 返回 YES 的元素 +- (ValueType)lookin_lastFiltered:(BOOL (^)(ValueType obj))block; + +- (id)lookin_reduce:(id (^)(id accumulator, NSUInteger idx, ValueType obj))block; + +- (CGFloat)lookin_reduceCGFloat:(CGFloat (^)(CGFloat accumulator, NSUInteger idx, ValueType obj))block initialAccumlator:(CGFloat)initialAccumlator; +- (NSInteger)lookin_reduceInteger:(NSInteger (^)(NSInteger accumulator, NSUInteger idx, ValueType obj))block initialAccumlator:(NSInteger)initialAccumlator; + +- (BOOL)lookin_all:(BOOL (^)(ValueType obj))block; + +- (BOOL)lookin_any:(BOOL (^)(ValueType obj))block; + +- (NSArray *)lookin_arrayByRemovingObject:(ValueType)obj; + +- (NSArray *)lookin_nonredundantArray; + +- (ValueType)lookin_safeObjectAtIndex:(NSInteger)idx; + +/// 字符串长度从短到长,即 length 小的字符串的 idx 更小 +- (NSArray *)lookin_sortedArrayByStringLength; + +@end + +@interface NSMutableArray (Lookin) + +/** + 如果当前数组长度比 count 小则会补充新元素(被补充的元素由 addBlock 返回),如果当前数组长度比 count 大则多余的元素会被作为参数传入 notDequeued。然后从 idx 为 0 算起,前 count 个元素会被作为参数传入 doBlock + */ +- (void)lookin_dequeueWithCount:(NSUInteger)count add:(ValueType (^)(NSUInteger idx))addBlock notDequeued:(void (^)(NSUInteger idx, ValueType obj))notDequeuedBlock doNext:(void (^)(NSUInteger idx, ValueType obj))doBlock; + +- (void)lookin_removeObjectsPassingTest:(BOOL (^)(NSUInteger idx, ValueType obj))block; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/Category/NSArray+Lookin.m b/Pods/LookinServer/Src/Main/Shared/Category/NSArray+Lookin.m new file mode 100644 index 0000000..6df614b --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/Category/NSArray+Lookin.m @@ -0,0 +1,300 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// NSArray+Lookin.m +// Lookin +// +// Created by Li Kai on 2018/9/3. +// https://lookin.work +// + + + +#import "NSArray+Lookin.h" + +@implementation NSArray (Lookin) + +- (NSArray *)lookin_resizeWithCount:(NSUInteger)count add:(id (^)(NSUInteger idx))addBlock remove:(void (^)(NSUInteger idx, id obj))removeBlock doNext:(void (^)(NSUInteger idx, id obj))doBlock { + NSMutableArray *resultArray = [NSMutableArray arrayWithCapacity:count]; + + for (NSUInteger i = 0; i < count; i++) { + if (self.count > i) { + id obj = [self objectAtIndex:i]; + [resultArray addObject:obj]; + if (doBlock) { + doBlock(i, obj); + } + } else { + if (addBlock) { + id newObj = addBlock(i); + if (newObj) { + [resultArray addObject:newObj]; + if (doBlock) { + doBlock(i, newObj); + } + } else { + NSAssert(NO, @""); + } + } else { + NSAssert(NO, @""); + } + } + } + + if (removeBlock) { + if (self.count > count) { + for (NSUInteger i = count; i < self.count; i++) { + id obj = [self objectAtIndex:i]; + removeBlock(i, obj); + } + } + } + + return [resultArray copy]; +} + ++ (NSArray *)lookin_arrayWithCount:(NSUInteger)count block:(id (^)(NSUInteger idx))block { + NSMutableArray *array = [NSMutableArray arrayWithCapacity:count]; + for (NSUInteger i = 0; i < count; i++) { + id obj = block(i); + if (obj) { + [array addObject:obj]; + } + } + return [array copy]; +} + +- (BOOL)lookin_hasIndex:(NSInteger)index { + if (index == NSNotFound || index < 0) { + return NO; + } + return self.count > index; +} + +- (NSArray *)lookin_map:(id (^)(NSUInteger , id))block { + if (!block) { + NSAssert(NO, @""); + return nil; + } + + NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:self.count]; + [self enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + id newObj = block(idx, obj); + if (newObj) { + [array addObject:newObj]; + } + }]; + return [array copy]; +} + +- (NSArray *)lookin_filter:(BOOL (^)(id obj))block { + if (!block) { + NSAssert(NO, @""); + return nil; + } + + NSMutableArray *mArray = [NSMutableArray array]; + [self enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + if (block(obj)) { + [mArray addObject:obj]; + } + }]; + return [mArray copy]; +} + +- (id)lookin_firstFiltered:(BOOL (^)(id obj))block { + if (!block) { + NSAssert(NO, @""); + return nil; + } + + __block id targetObj = nil; + [self enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + if (block(obj)) { + targetObj = obj; + *stop = YES; + } + }]; + return targetObj; +} + +- (id)lookin_lastFiltered:(BOOL (^)(id obj))block { + if (!block) { + NSAssert(NO, @""); + return nil; + } + + __block id targetObj = nil; + [self enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + if (block(obj)) { + targetObj = obj; + *stop = YES; + } + }]; + return targetObj; +} + +- (id)lookin_reduce:(id (^)(id accumulator, NSUInteger idx, id obj))block { + if (!block) { + NSAssert(NO, @""); + return nil; + } + + __block id accumulator = nil; + [self enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + accumulator = block(accumulator, idx, obj); + }]; + return accumulator; +} + +- (CGFloat)lookin_reduceCGFloat:(CGFloat (^)(CGFloat accumulator, NSUInteger idx, id obj))block initialAccumlator:(CGFloat)initialAccumlator { + if (!block) { + NSAssert(NO, @""); + return initialAccumlator; + } + + __block CGFloat accumulator = initialAccumlator; + [self enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + accumulator = block(accumulator, idx, obj); + }]; + return accumulator; +} + +- (NSInteger)lookin_reduceInteger:(NSInteger (^)(NSInteger, NSUInteger, id))block initialAccumlator:(NSInteger)initialAccumlator { + if (!block) { + NSAssert(NO, @""); + return initialAccumlator; + } + + __block NSInteger accumulator = initialAccumlator; + [self enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + accumulator = block(accumulator, idx, obj); + }]; + return accumulator; +} + +- (BOOL)lookin_all:(BOOL (^)(id obj))block { + if (!block) { + NSAssert(NO, @""); + return NO; + } + __block BOOL allPass = YES; + [self enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + BOOL boolValue = block(obj); + if (!boolValue) { + allPass = NO; + *stop = YES; + } + }]; + return allPass; +} + +- (BOOL)lookin_any:(BOOL (^)(id obj))block { + if (!block) { + NSAssert(NO, @""); + return NO; + } + __block BOOL anyPass = NO; + [self enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + BOOL boolValue = block(obj); + if (boolValue) { + anyPass = YES; + *stop = YES; + } + }]; + return anyPass; +} + +- (NSArray *)lookin_arrayByRemovingObject:(id)obj { + if (!obj || ![self containsObject:obj]) { + return self; + } + NSMutableArray *mutableArray = self.mutableCopy; + [mutableArray removeObject:obj]; + return mutableArray.copy; +} + +- (NSArray *)lookin_nonredundantArray { + NSSet *set = [NSSet setWithArray:self]; + NSArray *newArray = [set allObjects]; + return newArray; +} + +- (id)lookin_safeObjectAtIndex:(NSInteger)idx { + if (idx == NSNotFound || idx < 0) { + return nil; + } + if (self.count <= idx) { + return nil; + } + return [self objectAtIndex:idx]; +} + +- (NSArray *)lookin_sortedArrayByStringLength { + NSArray *sortedArray = [self sortedArrayUsingComparator:^NSComparisonResult(NSString *obj1, NSString *obj2) { + if (obj1.length > obj2.length) { + return NSOrderedDescending; + } else if (obj1.length == obj2.length) { + return NSOrderedSame; + } else { + return NSOrderedAscending; + } + }]; + return sortedArray; +} + +@end + +@implementation NSMutableArray (Lookin) + +- (void)lookin_dequeueWithCount:(NSUInteger)count add:(id (^)(NSUInteger idx))addBlock notDequeued:(void (^)(NSUInteger idx, id obj))notDequeuedBlock doNext:(void (^)(NSUInteger idx, id obj))doBlock { + for (NSUInteger i = 0; i < count; i++) { + if ([self lookin_hasIndex:i]) { + id obj = [self objectAtIndex:i]; + if (doBlock) { + doBlock(i, obj); + } + } else { + if (addBlock) { + id newObj = addBlock(i); + if (newObj) { + [self addObject:newObj]; + if (doBlock) { + doBlock(i, newObj); + } + } else { + NSAssert(NO, @""); + } + } else { + NSAssert(NO, @""); + } + } + } + + if (notDequeuedBlock) { + if (self.count > count) { + for (NSUInteger i = count; i < self.count; i++) { + id obj = [self objectAtIndex:i]; + notDequeuedBlock(i, obj); + } + } + } +} + +- (void)lookin_removeObjectsPassingTest:(BOOL (^)(NSUInteger idx, id obj))block { + if (!block) { + return; + } + NSMutableIndexSet *indexSet = [NSMutableIndexSet indexSet]; + [self enumerateObjectsUsingBlock:^(id _Nonnull currentObj, NSUInteger idx, BOOL * _Nonnull stop) { + BOOL boolValue = block(idx, currentObj); + if (boolValue) { + [indexSet addIndex:idx]; + } + }]; + [self removeObjectsAtIndexes:indexSet]; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/Category/NSObject+Lookin.h b/Pods/LookinServer/Src/Main/Shared/Category/NSObject+Lookin.h new file mode 100644 index 0000000..c8839cf --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/Category/NSObject+Lookin.h @@ -0,0 +1,108 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// NSObject+Lookin.h +// Lookin +// +// Created by Li Kai on 2018/12/22. +// https://lookin.work +// + +#import "LookinDefines.h" + + + +#import +#import "LookinCodingValueType.h" + +@interface NSObject (Lookin) + +#pragma mark - Data Bind + +/** + 给对象绑定上另一个对象以供后续取出使用,如果 object 传入 nil 则会清除该 key 之前绑定的对象 + + @attention 被绑定的对象会被 strong 强引用 + @note 内部是使用 objc_setAssociatedObject / objc_getAssociatedObject 来实现 + + @code + - (UITableViewCell *)cellForIndexPath:(NSIndexPath *)indexPath { + // 1)在这里给 button 绑定上 indexPath 对象 + [cell lookin_bindObject:indexPath forKey:@"indexPath"]; + } + + - (void)didTapButton:(UIButton *)button { + // 2)在这里取出被点击的 button 的 indexPath 对象 + NSIndexPath *indexPathTapped = [button lookin_getBindObjectForKey:@"indexPath"]; + } + @endcode + */ +- (void)lookin_bindObject:(id)object forKey:(NSString *)key; + +/** + 给对象绑定上另一个对象以供后续取出使用,但相比于 lookin_bindObject:forKey:,该方法不会 strong 强引用传入的 object + */ +- (void)lookin_bindObjectWeakly:(id)object forKey:(NSString *)key; + +/** + 取出之前使用 bind 方法绑定的对象 + */ +- (id)lookin_getBindObjectForKey:(NSString *)key; + +/** + 给对象绑定上一个 double 值以供后续取出使用 + */ +- (void)lookin_bindDouble:(double)doubleValue forKey:(NSString *)key; + +/** + 取出之前用 lookin_bindDouble:forKey: 绑定的值 + */ +- (double)lookin_getBindDoubleForKey:(NSString *)key; + +/** + 给对象绑定上一个 BOOL 值以供后续取出使用 + */ +- (void)lookin_bindBOOL:(BOOL)boolValue forKey:(NSString *)key; + +/** + 取出之前用 lookin_bindBOOL:forKey: 绑定的值 + */ +- (BOOL)lookin_getBindBOOLForKey:(NSString *)key; + +/** + 给对象绑定上一个 long 值以供后续取出使用 + */ +- (void)lookin_bindLong:(long)longValue forKey:(NSString *)key; + +/** + 取出之前用 lookin_bindLong:forKey: 绑定的值 + */ +- (long)lookin_getBindLongForKey:(NSString *)key; + +/** + 给对象绑定上一个 CGPoint 值以供后续取出使用 + */ +- (void)lookin_bindPoint:(CGPoint)pointValue forKey:(NSString *)key; + +/** + 取出之前用 lookin_bindPoint:forKey: 绑定的值 + */ +- (CGPoint)lookin_getBindPointForKey:(NSString *)key; + +/** + 移除之前使用 bind 方法绑定的对象 + */ +- (void)lookin_clearBindForKey:(NSString *)key; + +@end + +@interface NSObject (Lookin_Coding) + +/// 会把 NSImage/UIImage 转换为 NSData,把 NSColor/UIColor 转换回 NSNumber 数组(rgba) +- (id)lookin_encodedObjectWithType:(LookinCodingValueType)type; +/// 会把 NSData 转换回 NSImage/UIImage,把 NSNumber 数组(rgba) 转换为 NSColor/UIColor +- (id)lookin_decodedObjectWithType:(LookinCodingValueType)type; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/Category/NSObject+Lookin.m b/Pods/LookinServer/Src/Main/Shared/Category/NSObject+Lookin.m new file mode 100644 index 0000000..d206613 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/Category/NSObject+Lookin.m @@ -0,0 +1,238 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// NSObject+Lookin.m +// Lookin +// +// Created by Li Kai on 2018/12/22. +// https://lookin.work +// + +#import "NSObject+Lookin.h" +#import +#import "TargetConditionals.h" +#import "LookinWeakContainer.h" + +@implementation NSObject (Lookin) + +#pragma mark - Data Bind + +static char kAssociatedObjectKey_LookinAllBindObjects; +- (NSMutableDictionary *)lookin_allBindObjects { + NSMutableDictionary *dict = objc_getAssociatedObject(self, &kAssociatedObjectKey_LookinAllBindObjects); + if (!dict) { + dict = [NSMutableDictionary dictionary]; + objc_setAssociatedObject(self, &kAssociatedObjectKey_LookinAllBindObjects, dict, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + } + return dict; +} + +- (void)lookin_bindObject:(id)object forKey:(NSString *)key { + if (!key.length) { + NSAssert(NO, @""); + return; + } + @synchronized (self) { + if (object) { + [[self lookin_allBindObjects] setObject:object forKey:key]; + } else { + [[self lookin_allBindObjects] removeObjectForKey:key]; + } + } +} + +- (id)lookin_getBindObjectForKey:(NSString *)key { + if (!key.length) { + NSAssert(NO, @""); + return nil; + } + @synchronized (self) { + id storedObj = [[self lookin_allBindObjects] objectForKey:key]; + if ([storedObj isKindOfClass:[LookinWeakContainer class]]) { + storedObj = [(LookinWeakContainer *)storedObj object]; + } + return storedObj; + } +} + +- (void)lookin_bindObjectWeakly:(id)object forKey:(NSString *)key { + if (!key.length) { + NSAssert(NO, @""); + return; + } + if (object) { + LookinWeakContainer *container = [[LookinWeakContainer alloc] init]; + container.object = object; + [self lookin_bindObject:container forKey:key]; + } else { + [self lookin_bindObject:nil forKey:key]; + } +} + +- (void)lookin_bindDouble:(double)doubleValue forKey:(NSString *)key { + [self lookin_bindObject:@(doubleValue) forKey:key]; +} + +- (double)lookin_getBindDoubleForKey:(NSString *)key { + id object = [self lookin_getBindObjectForKey:key]; + if ([object isKindOfClass:[NSNumber class]]) { + double doubleValue = [(NSNumber *)object doubleValue]; + return doubleValue; + + } else { + return 0.0; + } +} + +- (void)lookin_bindBOOL:(BOOL)boolValue forKey:(NSString *)key { + [self lookin_bindObject:@(boolValue) forKey:key]; +} + +- (BOOL)lookin_getBindBOOLForKey:(NSString *)key { + id object = [self lookin_getBindObjectForKey:key]; + if ([object isKindOfClass:[NSNumber class]]) { + BOOL boolValue = [(NSNumber *)object boolValue]; + return boolValue; + + } else { + return NO; + } +} + +- (void)lookin_bindLong:(long)longValue forKey:(NSString *)key { + [self lookin_bindObject:@(longValue) forKey:key]; +} + +- (long)lookin_getBindLongForKey:(NSString *)key { + id object = [self lookin_getBindObjectForKey:key]; + if ([object isKindOfClass:[NSNumber class]]) { + long longValue = [(NSNumber *)object longValue]; + return longValue; + + } else { + return 0; + } +} + +- (void)lookin_bindPoint:(CGPoint)pointValue forKey:(NSString *)key { +#if TARGET_OS_IPHONE + [self lookin_bindObject:[NSValue valueWithCGPoint:pointValue] forKey:key]; +#elif TARGET_OS_MAC + NSPoint nsPoint = NSMakePoint(pointValue.x, pointValue.y); + [self lookin_bindObject:[NSValue valueWithPoint:nsPoint] forKey:key]; +#endif +} + +- (CGPoint)lookin_getBindPointForKey:(NSString *)key { + id object = [self lookin_getBindObjectForKey:key]; + if ([object isKindOfClass:[NSValue class]]) { +#if TARGET_OS_IPHONE + CGPoint pointValue = [(NSValue *)object CGPointValue]; +#elif TARGET_OS_MAC + NSPoint nsPointValue = [(NSValue *)object pointValue]; + CGPoint pointValue = CGPointMake(nsPointValue.x, nsPointValue.y); +#endif + return pointValue; + } else { + return CGPointZero; + } +} + +- (void)lookin_clearBindForKey:(NSString *)key { + [self lookin_bindObject:nil forKey:key]; +} + +@end + +@implementation NSObject (Lookin_Coding) + +- (id)lookin_encodedObjectWithType:(LookinCodingValueType)type { + if (type == LookinCodingValueTypeColor) { + if ([self isKindOfClass:[LookinColor class]]) { + CGFloat r, g, b, a; +#if TARGET_OS_IPHONE + CGFloat white; + if ([(UIColor *)self getRed:&r green:&g blue:&b alpha:&a]) { + // valid + } else if ([(UIColor *)self getWhite:&white alpha:&a]) { + r = white; + g = white; + b = white; + } else { + NSAssert(NO, @""); + r = 0; + g = 0; + b = 0; + a = 0; + } +#elif TARGET_OS_MAC + NSColor *color = [((NSColor *)self) colorUsingColorSpace:NSColorSpace.sRGBColorSpace]; + [color getRed:&r green:&g blue:&b alpha:&a]; +#endif + NSArray *rgba = @[@(r), @(g), @(b), @(a)]; + return rgba; + + } else { + NSAssert(NO, @""); + return nil; + } + + } else if (type == LookinCodingValueTypeImage) { +#if TARGET_OS_IPHONE + if ([self isKindOfClass:[UIImage class]]) { + UIImage *image = (UIImage *)self; + return UIImagePNGRepresentation(image); + + } else { + NSAssert(NO, @""); + return nil; + } +#elif TARGET_OS_MAC + if ([self isKindOfClass:[NSImage class]]) { + NSImage *image = (NSImage *)self; + return [image TIFFRepresentation]; + + } else { + NSAssert(NO, @""); + return nil; + } +#endif + + } else { + return self; + } +} + +- (id)lookin_decodedObjectWithType:(LookinCodingValueType)type { + if (type == LookinCodingValueTypeColor) { + if ([self isKindOfClass:[NSArray class]]) { + NSArray *rgba = (NSArray *)self; + CGFloat r = [rgba[0] doubleValue]; + CGFloat g = [rgba[1] doubleValue]; + CGFloat b = [rgba[2] doubleValue]; + CGFloat a = [rgba[3] doubleValue]; + LookinColor *color = [LookinColor colorWithRed:r green:g blue:b alpha:a]; + return color; + + } else { + NSAssert(NO, @""); + return nil; + } + + } else if (type == LookinCodingValueTypeImage) { + if ([self isKindOfClass:[NSData class]]) { + LookinImage *image = [[LookinImage alloc] initWithData:(NSData *)self]; + return image; + } else { + NSAssert(NO, @""); + return nil; + } + + } else { + return self; + } +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/Category/NSSet+Lookin.h b/Pods/LookinServer/Src/Main/Shared/Category/NSSet+Lookin.h new file mode 100644 index 0000000..f09a704 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/Category/NSSet+Lookin.h @@ -0,0 +1,39 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// NSSet+Lookin.h +// Lookin +// +// Created by Li Kai on 2019/1/13. +// https://lookin.work +// + +#import "LookinDefines.h" + + + +#import "TargetConditionals.h" +#if TARGET_OS_IPHONE +#import +#elif TARGET_OS_MAC +#import +#endif + +@interface NSSet<__covariant ValueType> (Lookin) + +- (NSSet *)lookin_map:(id (^)(ValueType obj))block; + +- (ValueType)lookin_firstFiltered:(BOOL (^)(ValueType obj))block; + +- (NSSet *)lookin_filter:(BOOL (^)(ValueType obj))block; + + +/** + 是否有任何一个元素满足某条件 + @note 元素将被依次传入 block 里,如果任何一个 block 返回 YES,则该方法返回 YES。如果所有 block 均返回 NO,则该方法返回 NO。 + */ +- (BOOL)lookin_any:(BOOL (^)(ValueType obj))block; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/Category/NSSet+Lookin.m b/Pods/LookinServer/Src/Main/Shared/Category/NSSet+Lookin.m new file mode 100644 index 0000000..1ec9edf --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/Category/NSSet+Lookin.m @@ -0,0 +1,81 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// NSSet+Lookin.m +// Lookin +// +// Created by Li Kai on 2019/1/13. +// https://lookin.work +// + + + +#import "NSSet+Lookin.h" + +@implementation NSSet (Lookin) + +- (NSSet *)lookin_map:(id (^)(id obj))block { + if (!block) { + NSAssert(NO, @""); + return nil; + } + + NSMutableSet *newSet = [NSMutableSet setWithCapacity:self.count]; + [self enumerateObjectsUsingBlock:^(id _Nonnull obj, BOOL * _Nonnull stop) { + id newObj = block(obj); + if (newObj) { + [newSet addObject:newObj]; + } + }]; + return [newSet copy]; +} + +- (id)lookin_firstFiltered:(BOOL (^)(id obj))block { + if (!block) { + NSAssert(NO, @""); + return nil; + } + + __block id targetObj = nil; + [self enumerateObjectsUsingBlock:^(id _Nonnull obj, BOOL * _Nonnull stop) { + if (block(obj)) { + targetObj = obj; + *stop = YES; + } + }]; + return targetObj; +} + +- (NSSet *)lookin_filter:(BOOL (^)(id obj))block { + if (!block) { + NSAssert(NO, @""); + return nil; + } + + NSMutableSet *mSet = [NSMutableSet set]; + [self enumerateObjectsUsingBlock:^(id _Nonnull obj, BOOL * _Nonnull stop) { + if (block(obj)) { + [mSet addObject:obj]; + } + }]; + return [mSet copy]; +} + +- (BOOL)lookin_any:(BOOL (^)(id obj))block { + if (!block) { + NSAssert(NO, @""); + return NO; + } + __block BOOL boolValue = NO; + [self enumerateObjectsUsingBlock:^(id _Nonnull obj, BOOL * _Nonnull stop) { + if (block(obj)) { + boolValue = YES; + *stop = YES; + } + }]; + return boolValue; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/Category/NSString+Lookin.h b/Pods/LookinServer/Src/Main/Shared/Category/NSString+Lookin.h new file mode 100644 index 0000000..15f1171 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/Category/NSString+Lookin.h @@ -0,0 +1,42 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// NSString+Lookin.h +// Lookin +// +// Created by Li Kai on 2019/5/11. +// https://lookin.work +// + +#import "LookinDefines.h" + + + +#import + +@interface NSString (Lookin) + +/** + 把 CGFloat 转成字符串,最多保留 3 位小数,转换后末尾的 0 会被删除 + 如:1.2341 => @"1.234", 2.1002 => @"2.1", 3.000 => @"3" + */ ++ (NSString *)lookin_stringFromDouble:(double)doubleValue decimal:(NSUInteger)decimal; + ++ (NSString *)lookin_stringFromRect:(CGRect)rect; + ++ (NSString *)lookin_stringFromInset:(LookinInsets)insets; + ++ (NSString *)lookin_stringFromSize:(CGSize)size; + ++ (NSString *)lookin_stringFromPoint:(CGPoint)point; + ++ (NSString *)lookin_rgbaStringFromColor:(LookinColor *)color; + +- (NSString *)lookin_safeInitWithUTF8String:(const char *)string; + +/// 把 1.2.3 这种 String 版本号转换成数字,可用于大小比较,如 110205 代表 11.2.5 版本 +- (NSInteger)lookin_numbericOSVersion; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/Category/NSString+Lookin.m b/Pods/LookinServer/Src/Main/Shared/Category/NSString+Lookin.m new file mode 100644 index 0000000..9b76fb5 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/Category/NSString+Lookin.m @@ -0,0 +1,117 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// NSString+Lookin.m +// Lookin +// +// Created by Li Kai on 2019/5/11. +// https://lookin.work +// + + + +#import "NSString+Lookin.h" + +@implementation NSString (Lookin) + ++ (NSString *)lookin_stringFromDouble:(double)doubleValue decimal:(NSUInteger)decimal { + NSString *formatString = [NSString stringWithFormat:@"%%.%@f", @(decimal)]; + NSString *string = [NSString stringWithFormat:formatString, doubleValue]; + for (int i = 0; i < decimal; i++) { + if ([[string substringFromIndex:string.length - 1] isEqualToString:@"0"]) { + string = [string substringToIndex:string.length - 1]; + } + } + if ([[string substringFromIndex:string.length - 1] isEqualToString:@"."]) { + string = [string substringToIndex:string.length - 1]; + } + return string; +} + ++ (NSString *)lookin_stringFromInset:(LookinInsets)insets { + return [NSString stringWithFormat:@"{%@, %@, %@, %@}", + [NSString lookin_stringFromDouble:insets.top decimal:2], + [NSString lookin_stringFromDouble:insets.left decimal:2], + [NSString lookin_stringFromDouble:insets.bottom decimal:2], + [NSString lookin_stringFromDouble:insets.right decimal:2]]; +} + ++ (NSString *)lookin_stringFromSize:(CGSize)size { + return [NSString stringWithFormat:@"{%@, %@}", + [NSString lookin_stringFromDouble:size.width decimal:2], + [NSString lookin_stringFromDouble:size.height decimal:2]]; +} + + ++ (NSString *)lookin_stringFromPoint:(CGPoint)point { + return [NSString stringWithFormat:@"{%@, %@}", + [NSString lookin_stringFromDouble:point.x decimal:2], + [NSString lookin_stringFromDouble:point.y decimal:2]]; +} + ++ (NSString *)lookin_stringFromRect:(CGRect)rect { + return [NSString stringWithFormat:@"{%@, %@, %@, %@}", + [NSString lookin_stringFromDouble:rect.origin.x decimal:2], + [NSString lookin_stringFromDouble:rect.origin.y decimal:2], + [NSString lookin_stringFromDouble:rect.size.width decimal:2], + [NSString lookin_stringFromDouble:rect.size.height decimal:2]]; +} + ++ (NSString *)lookin_rgbaStringFromColor:(LookinColor *)color { + if (!color) { + return @"nil"; + } + +#if TARGET_OS_IPHONE + UIColor *rgbColor = color; +#elif TARGET_OS_MAC + NSColor *rgbColor = [color colorUsingColorSpace:NSColorSpace.sRGBColorSpace]; +#endif + + CGFloat r, g, b, a; + [rgbColor getRed:&r green:&g blue:&b alpha:&a]; + + NSString *colorDesc; + if (a >= 1) { + colorDesc = [NSString stringWithFormat:@"(%.0f, %.0f, %.0f)", r * 255, g * 255, b * 255]; + } else { + colorDesc = [NSString stringWithFormat:@"(%.0f, %.0f, %.0f, %@)", r * 255, g * 255, b * 255, [NSString lookin_stringFromDouble:a decimal:2]]; + + } + + return colorDesc; +} + +- (NSString *)lookin_safeInitWithUTF8String:(const char *)string { + if (NULL != string) { + return [self initWithUTF8String:string]; + } + return nil; +} + +- (NSInteger)lookin_numbericOSVersion { + if (self.length == 0) { + NSAssert(NO, @""); + return 0; + } + NSArray *versionArr = [self componentsSeparatedByString:@"."]; + if (versionArr.count != 3) { + NSAssert(NO, @""); + return 0; + } + + NSInteger numbericOSVersion = 0; + NSInteger pos = 0; + + while ([versionArr count] > pos && pos < 3) { + numbericOSVersion += ([[versionArr objectAtIndex:pos] integerValue] * pow(10, (4 - pos * 2))); + pos++; + } + + return numbericOSVersion; +} + + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinAppInfo.h b/Pods/LookinServer/Src/Main/Shared/LookinAppInfo.h new file mode 100644 index 0000000..1082d12 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinAppInfo.h @@ -0,0 +1,72 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinAppInfo.h +// qmuidemo +// +// Created by Li Kai on 2018/11/3. +// Copyright © 2018 QMUI Team. All rights reserved. +// + + + +#import "LookinDefines.h" + +typedef NS_ENUM(NSInteger, LookinAppInfoDevice) { + LookinAppInfoDeviceSimulator, // 模拟器 + LookinAppInfoDeviceIPad, // iPad 真机 + LookinAppInfoDeviceOthers // 应该视为 iPhone 真机 +}; + +@interface LookinAppInfo : NSObject + +/// 每次启动 app 时都会随机生成一个 appInfoIdentifier 直到 app 被 kill 掉 +@property(nonatomic, assign) NSUInteger appInfoIdentifier; +/// mac 端应该先读取该属性,如果为 YES 则表示应该使用之前保存的旧 appInfo 对象即可 +@property(nonatomic, assign) BOOL shouldUseCache; +/// LookinServer 的版本 +@property(nonatomic, assign) int serverVersion; +/// 类似 "1.1.9",只在 1.2.3 以及之后的 LookinServer 版本里有值 +@property(nonatomic, assign) NSString *serverReadableVersion; +/// 如果 iOS 侧使用了 SPM 或引入了 Swift Subspec,则该属性为 1 +/// 如果 iOS 侧没使用,则该属性为 -1 +/// 如果不知道,则该属性为 0 +@property(nonatomic, assign) int swiftEnabledInLookinServer; +/// app 的当前截图 +@property(nonatomic, strong) LookinImage *screenshot; +/// 可能为 nil,比如新建的 iOS 空项目 +@property(nonatomic, strong) LookinImage *appIcon; +/// @"微信读书" +@property(nonatomic, copy) NSString *appName; +/// hughkli.lookin +@property(nonatomic, copy) NSString *appBundleIdentifier; +/// @"iPhone X" +@property(nonatomic, copy) NSString *deviceDescription; +/// @"12.1" +@property(nonatomic, copy) NSString *osDescription; +/// 返回 os 的主版本号,比如 iOS 12.1 的设备将返回 12,iOS 13.2.1 的设备将返回 13 +@property(nonatomic, assign) NSUInteger osMainVersion; +/// 设备类型 +@property(nonatomic, assign) LookinAppInfoDevice deviceType; +/// 屏幕的宽度 +@property(nonatomic, assign) double screenWidth; +/// 屏幕的高度 +@property(nonatomic, assign) double screenHeight; +/// 是几倍的屏幕 +@property(nonatomic, assign) double screenScale; + +- (BOOL)isEqualToAppInfo:(LookinAppInfo *)info; + +#if TARGET_OS_IPHONE + ++ (LookinAppInfo *)currentInfoWithScreenshot:(BOOL)hasScreenshot icon:(BOOL)hasIcon localIdentifiers:(NSArray *)localIdentifiers; + +#else + +@property(nonatomic, assign) NSTimeInterval cachedTimestamp; + +#endif + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinAppInfo.m b/Pods/LookinServer/Src/Main/Shared/LookinAppInfo.m new file mode 100644 index 0000000..b1c0c50 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinAppInfo.m @@ -0,0 +1,242 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinAppInfo.m +// qmuidemo +// +// Created by Li Kai on 2018/11/3. +// Copyright © 2018 QMUI Team. All rights reserved. +// + + + +#import "LookinAppInfo.h" +#import "LKS_MultiplatformAdapter.h" + +static NSString * const CodingKey_AppIcon = @"1"; +static NSString * const CodingKey_Screenshot = @"2"; +static NSString * const CodingKey_DeviceDescription = @"3"; +static NSString * const CodingKey_OsDescription = @"4"; +static NSString * const CodingKey_AppName = @"5"; +static NSString * const CodingKey_ScreenWidth = @"6"; +static NSString * const CodingKey_ScreenHeight = @"7"; +static NSString * const CodingKey_DeviceType = @"8"; + +@implementation LookinAppInfo + +- (id)copyWithZone:(NSZone *)zone { + LookinAppInfo *newAppInfo = [[LookinAppInfo allocWithZone:zone] init]; + newAppInfo.appIcon = self.appIcon; + newAppInfo.appName = self.appName; + newAppInfo.deviceDescription = self.deviceDescription; + newAppInfo.osDescription = self.osDescription; + newAppInfo.osMainVersion = self.osMainVersion; + newAppInfo.deviceType = self.deviceType; + newAppInfo.screenWidth = self.screenWidth; + newAppInfo.screenHeight = self.screenHeight; + newAppInfo.screenScale = self.screenScale; + newAppInfo.appInfoIdentifier = self.appInfoIdentifier; + return newAppInfo; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if (self = [super init]) { + + self.serverVersion = [aDecoder decodeIntForKey:@"serverVersion"]; + self.serverReadableVersion = [aDecoder decodeObjectForKey:@"serverReadableVersion"]; + self.swiftEnabledInLookinServer = [aDecoder decodeIntForKey:@"swiftEnabledInLookinServer"]; + NSData *screenshotData = [aDecoder decodeObjectForKey:CodingKey_Screenshot]; + self.screenshot = [[LookinImage alloc] initWithData:screenshotData]; + + NSData *appIconData = [aDecoder decodeObjectForKey:CodingKey_AppIcon]; + self.appIcon = [[LookinImage alloc] initWithData:appIconData]; + + self.appName = [aDecoder decodeObjectForKey:CodingKey_AppName]; + self.appBundleIdentifier = [aDecoder decodeObjectForKey:@"appBundleIdentifier"]; + self.deviceDescription = [aDecoder decodeObjectForKey:CodingKey_DeviceDescription]; + self.osDescription = [aDecoder decodeObjectForKey:CodingKey_OsDescription]; + self.osMainVersion = [aDecoder decodeIntegerForKey:@"osMainVersion"]; + self.deviceType = [aDecoder decodeIntegerForKey:CodingKey_DeviceType]; + self.screenWidth = [aDecoder decodeDoubleForKey:CodingKey_ScreenWidth]; + self.screenHeight = [aDecoder decodeDoubleForKey:CodingKey_ScreenHeight]; + self.screenScale = [aDecoder decodeDoubleForKey:@"screenScale"]; + self.appInfoIdentifier = [aDecoder decodeIntegerForKey:@"appInfoIdentifier"]; + self.shouldUseCache = [aDecoder decodeBoolForKey:@"shouldUseCache"]; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeInt:self.serverVersion forKey:@"serverVersion"]; + [aCoder encodeObject:self.serverReadableVersion forKey:@"serverReadableVersion"]; + [aCoder encodeInt:self.swiftEnabledInLookinServer forKey:@"swiftEnabledInLookinServer"]; + +#if TARGET_OS_IPHONE + NSData *screenshotData = UIImagePNGRepresentation(self.screenshot); + [aCoder encodeObject:screenshotData forKey:CodingKey_Screenshot]; + + NSData *appIconData = UIImagePNGRepresentation(self.appIcon); + [aCoder encodeObject:appIconData forKey:CodingKey_AppIcon]; +#elif TARGET_OS_MAC + NSData *screenshotData = [self.screenshot TIFFRepresentation]; + [aCoder encodeObject:screenshotData forKey:CodingKey_Screenshot]; + + NSData *appIconData = [self.appIcon TIFFRepresentation]; + [aCoder encodeObject:appIconData forKey:CodingKey_AppIcon]; +#endif + + [aCoder encodeObject:self.appName forKey:CodingKey_AppName]; + [aCoder encodeObject:self.appBundleIdentifier forKey:@"appBundleIdentifier"]; + [aCoder encodeObject:self.deviceDescription forKey:CodingKey_DeviceDescription]; + [aCoder encodeObject:self.osDescription forKey:CodingKey_OsDescription]; + [aCoder encodeInteger:self.osMainVersion forKey:@"osMainVersion"]; + [aCoder encodeInteger:self.deviceType forKey:CodingKey_DeviceType]; + [aCoder encodeDouble:self.screenWidth forKey:CodingKey_ScreenWidth]; + [aCoder encodeDouble:self.screenHeight forKey:CodingKey_ScreenHeight]; + [aCoder encodeDouble:self.screenScale forKey:@"screenScale"]; + [aCoder encodeInteger:self.appInfoIdentifier forKey:@"appInfoIdentifier"]; + [aCoder encodeBool:self.shouldUseCache forKey:@"shouldUseCache"]; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[LookinAppInfo class]]) { + return NO; + } + if ([self isEqualToAppInfo:object]) { + return YES; + } + return NO; +} + +- (NSUInteger)hash { + return self.appName.hash ^ self.deviceDescription.hash ^ self.osDescription.hash ^ self.deviceType; +} + +- (BOOL)isEqualToAppInfo:(LookinAppInfo *)info { + if (!info) { + return NO; + } + if ([self.appName isEqualToString:info.appName] && [self.deviceDescription isEqualToString:info.deviceDescription] && [self.osDescription isEqualToString:info.osDescription] && self.deviceType == info.deviceType) { + return YES; + } + return NO; +} + +#if TARGET_OS_IPHONE + ++ (LookinAppInfo *)currentInfoWithScreenshot:(BOOL)hasScreenshot icon:(BOOL)hasIcon localIdentifiers:(NSArray *)localIdentifiers { + NSInteger selfIdentifier = [self getAppInfoIdentifier]; + if ([localIdentifiers containsObject:@(selfIdentifier)]) { + LookinAppInfo *info = [LookinAppInfo new]; + info.appInfoIdentifier = selfIdentifier; + info.shouldUseCache = YES; + return info; + } + + LookinAppInfo *info = [[LookinAppInfo alloc] init]; + info.serverReadableVersion = LOOKIN_SERVER_READABLE_VERSION; +#ifdef LOOKIN_SERVER_SWIFT_ENABLED + info.swiftEnabledInLookinServer = 1; +#else + info.swiftEnabledInLookinServer = -1; +#endif + info.appInfoIdentifier = selfIdentifier; + info.appName = [self appName]; + info.deviceDescription = [UIDevice currentDevice].name; + info.appBundleIdentifier = [[NSBundle mainBundle] bundleIdentifier]; + if ([self isSimulator]) { + info.deviceType = LookinAppInfoDeviceSimulator; + } else if ([LKS_MultiplatformAdapter isiPad]) { + info.deviceType = LookinAppInfoDeviceIPad; + } else { + info.deviceType = LookinAppInfoDeviceOthers; + } + + info.osDescription = [UIDevice currentDevice].systemVersion; + + NSString *mainVersionStr = [[[UIDevice currentDevice] systemVersion] componentsSeparatedByString:@"."].firstObject; + info.osMainVersion = [mainVersionStr integerValue]; + + CGSize screenSize = [LKS_MultiplatformAdapter mainScreenBounds].size; + info.screenWidth = screenSize.width; + info.screenHeight = screenSize.height; + info.screenScale = [LKS_MultiplatformAdapter mainScreenScale]; + + if (hasScreenshot) { + info.screenshot = [self screenshotImage]; + } + if (hasIcon) { + info.appIcon = [self appIcon]; + } + + return info; +} + ++ (NSString *)appName { + NSDictionary *info = [[NSBundle mainBundle] infoDictionary]; + NSString *displayName = [info objectForKey:@"CFBundleDisplayName"]; + NSString *name = [info objectForKey:@"CFBundleName"]; + return displayName.length ? displayName : name; +} + ++ (UIImage *)appIcon { +#if TARGET_OS_TV + return nil; +#else + NSString *imageName = [[[[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIcons"] objectForKey:@"CFBundlePrimaryIcon"] objectForKey:@"CFBundleIconFiles"] lastObject]; + if (!imageName.length) { + // 正常情况下拿到的 name 可能比如 “AppIcon60x60”。但某些情况可能为 nil,此时直接 return 否则 [UIImage imageNamed:nil] 可能导致 console 报 "CUICatalog: Invalid asset name supplied: '(null)'" 的错误信息 + return nil; + } + return [UIImage imageNamed:imageName]; +#endif +} + ++ (UIImage *)screenshotImage { + UIWindow *window = [LKS_MultiplatformAdapter keyWindow]; + if (!window) { + return nil; + } + CGSize size = window.bounds.size; + if (size.width <= 0 || size.height <= 0) { + // *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UIGraphicsBeginImageContext() failed to allocate CGBitampContext: size={0, 0}, scale=3.000000, bitmapInfo=0x2002. Use UIGraphicsImageRenderer to avoid this assert.' + + // https://github.com/hughkli/Lookin/issues/21 + return nil; + } + UIGraphicsBeginImageContextWithOptions(size, YES, 0.4); + [window drawViewHierarchyInRect:window.bounds afterScreenUpdates:YES]; + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + return image; +} + ++ (BOOL)isSimulator { + if (TARGET_OS_SIMULATOR) { + return YES; + } + return NO; +} + +#endif + ++ (NSInteger)getAppInfoIdentifier { + static dispatch_once_t onceToken; + static NSInteger identifier = 0; + dispatch_once(&onceToken,^{ + identifier = [[NSDate date] timeIntervalSince1970]; + }); + return identifier; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinAttrIdentifiers.h b/Pods/LookinServer/Src/Main/Shared/LookinAttrIdentifiers.h new file mode 100644 index 0000000..577d532 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinAttrIdentifiers.h @@ -0,0 +1,257 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinAttrIdentifiers.h +// Lookin +// +// Created by Li Kai on 2019/9/18. +// https://lookin.work +// + + + +#import + +#pragma mark - Group + +typedef NSString * LookinAttrGroupIdentifier; + +extern LookinAttrGroupIdentifier const LookinAttrGroup_None; +extern LookinAttrGroupIdentifier const LookinAttrGroup_Class; +extern LookinAttrGroupIdentifier const LookinAttrGroup_Relation; +extern LookinAttrGroupIdentifier const LookinAttrGroup_Layout; +extern LookinAttrGroupIdentifier const LookinAttrGroup_AutoLayout; +extern LookinAttrGroupIdentifier const LookinAttrGroup_ViewLayer; +extern LookinAttrGroupIdentifier const LookinAttrGroup_UIImageView; +extern LookinAttrGroupIdentifier const LookinAttrGroup_UILabel; +extern LookinAttrGroupIdentifier const LookinAttrGroup_UIControl; +extern LookinAttrGroupIdentifier const LookinAttrGroup_UIButton; +extern LookinAttrGroupIdentifier const LookinAttrGroup_UIScrollView; +extern LookinAttrGroupIdentifier const LookinAttrGroup_UITableView; +extern LookinAttrGroupIdentifier const LookinAttrGroup_UITextView; +extern LookinAttrGroupIdentifier const LookinAttrGroup_UITextField; +extern LookinAttrGroupIdentifier const LookinAttrGroup_UIVisualEffectView; +extern LookinAttrGroupIdentifier const LookinAttrGroup_UIStackView; + +extern LookinAttrGroupIdentifier const LookinAttrGroup_UserCustom; + +#pragma mark - Section + +typedef NSString * LookinAttrSectionIdentifier; + +extern LookinAttrSectionIdentifier const LookinAttrSec_None; + +extern LookinAttrSectionIdentifier const LookinAttrSec_UserCustom; + +extern LookinAttrSectionIdentifier const LookinAttrSec_Class_Class; + +extern LookinAttrSectionIdentifier const LookinAttrSec_Relation_Relation; + +extern LookinAttrSectionIdentifier const LookinAttrSec_Layout_Frame; +extern LookinAttrSectionIdentifier const LookinAttrSec_Layout_Bounds; +extern LookinAttrSectionIdentifier const LookinAttrSec_Layout_SafeArea; +extern LookinAttrSectionIdentifier const LookinAttrSec_Layout_Position; +extern LookinAttrSectionIdentifier const LookinAttrSec_Layout_AnchorPoint; + +extern LookinAttrSectionIdentifier const LookinAttrSec_AutoLayout_Hugging; +extern LookinAttrSectionIdentifier const LookinAttrSec_AutoLayout_Resistance; +extern LookinAttrSectionIdentifier const LookinAttrSec_AutoLayout_Constraints; +extern LookinAttrSectionIdentifier const LookinAttrSec_AutoLayout_IntrinsicSize; + +extern LookinAttrSectionIdentifier const LookinAttrSec_ViewLayer_Visibility; +extern LookinAttrSectionIdentifier const LookinAttrSec_ViewLayer_InterationAndMasks; +extern LookinAttrSectionIdentifier const LookinAttrSec_ViewLayer_Corner; +extern LookinAttrSectionIdentifier const LookinAttrSec_ViewLayer_BgColor; +extern LookinAttrSectionIdentifier const LookinAttrSec_ViewLayer_Border; +extern LookinAttrSectionIdentifier const LookinAttrSec_ViewLayer_Shadow; +extern LookinAttrSectionIdentifier const LookinAttrSec_ViewLayer_ContentMode; +extern LookinAttrSectionIdentifier const LookinAttrSec_ViewLayer_TintColor; +extern LookinAttrSectionIdentifier const LookinAttrSec_ViewLayer_Tag; + +extern LookinAttrSectionIdentifier const LookinAttrSec_UIImageView_Name; +extern LookinAttrSectionIdentifier const LookinAttrSec_UIImageView_Open; + +extern LookinAttrSectionIdentifier const LookinAttrSec_UILabel_Text; +extern LookinAttrSectionIdentifier const LookinAttrSec_UILabel_Font; +extern LookinAttrSectionIdentifier const LookinAttrSec_UILabel_NumberOfLines; +extern LookinAttrSectionIdentifier const LookinAttrSec_UILabel_TextColor; +extern LookinAttrSectionIdentifier const LookinAttrSec_UILabel_BreakMode; +extern LookinAttrSectionIdentifier const LookinAttrSec_UILabel_Alignment; +extern LookinAttrSectionIdentifier const LookinAttrSec_UILabel_CanAdjustFont; + +extern LookinAttrSectionIdentifier const LookinAttrSec_UIControl_EnabledSelected; +extern LookinAttrSectionIdentifier const LookinAttrSec_UIControl_VerAlignment; +extern LookinAttrSectionIdentifier const LookinAttrSec_UIControl_HorAlignment; +extern LookinAttrSectionIdentifier const LookinAttrSec_UIControl_QMUIOutsideEdge; + +extern LookinAttrSectionIdentifier const LookinAttrSec_UIButton_ContentInsets; +extern LookinAttrSectionIdentifier const LookinAttrSec_UIButton_TitleInsets; +extern LookinAttrSectionIdentifier const LookinAttrSec_UIButton_ImageInsets; + +extern LookinAttrSectionIdentifier const LookinAttrSec_UIScrollView_ContentInset; +extern LookinAttrSectionIdentifier const LookinAttrSec_UIScrollView_AdjustedInset; +extern LookinAttrSectionIdentifier const LookinAttrSec_UIScrollView_IndicatorInset; +extern LookinAttrSectionIdentifier const LookinAttrSec_UIScrollView_Offset; +extern LookinAttrSectionIdentifier const LookinAttrSec_UIScrollView_ContentSize; +extern LookinAttrSectionIdentifier const LookinAttrSec_UIScrollView_Behavior; +extern LookinAttrSectionIdentifier const LookinAttrSec_UIScrollView_ShowsIndicator; +extern LookinAttrSectionIdentifier const LookinAttrSec_UIScrollView_Bounce; +extern LookinAttrSectionIdentifier const LookinAttrSec_UIScrollView_ScrollPaging; +extern LookinAttrSectionIdentifier const LookinAttrSec_UIScrollView_ContentTouches; +extern LookinAttrSectionIdentifier const LookinAttrSec_UIScrollView_Zoom; +extern LookinAttrSectionIdentifier const LookinAttrSec_UIScrollView_QMUIInitialInset; + +extern LookinAttrSectionIdentifier const LookinAttrSec_UITableView_Style; +extern LookinAttrSectionIdentifier const LookinAttrSec_UITableView_SectionsNumber; +extern LookinAttrSectionIdentifier const LookinAttrSec_UITableView_RowsNumber; +extern LookinAttrSectionIdentifier const LookinAttrSec_UITableView_SeparatorStyle; +extern LookinAttrSectionIdentifier const LookinAttrSec_UITableView_SeparatorColor; +extern LookinAttrSectionIdentifier const LookinAttrSec_UITableView_SeparatorInset; + +extern LookinAttrSectionIdentifier const LookinAttrSec_UITextView_Basic; +extern LookinAttrSectionIdentifier const LookinAttrSec_UITextView_Text; +extern LookinAttrSectionIdentifier const LookinAttrSec_UITextView_Font; +extern LookinAttrSectionIdentifier const LookinAttrSec_UITextView_TextColor; +extern LookinAttrSectionIdentifier const LookinAttrSec_UITextView_Alignment; +extern LookinAttrSectionIdentifier const LookinAttrSec_UITextView_ContainerInset; + +extern LookinAttrSectionIdentifier const LookinAttrSec_UITextField_Text; +extern LookinAttrSectionIdentifier const LookinAttrSec_UITextField_Placeholder; +extern LookinAttrSectionIdentifier const LookinAttrSec_UITextField_Font; +extern LookinAttrSectionIdentifier const LookinAttrSec_UITextField_TextColor; +extern LookinAttrSectionIdentifier const LookinAttrSec_UITextField_Alignment; +extern LookinAttrSectionIdentifier const LookinAttrSec_UITextField_Clears; +extern LookinAttrSectionIdentifier const LookinAttrSec_UITextField_CanAdjustFont; +extern LookinAttrSectionIdentifier const LookinAttrSec_UITextField_ClearButtonMode; + +extern LookinAttrSectionIdentifier const LookinAttrSec_UIVisualEffectView_Style; +extern LookinAttrSectionIdentifier const LookinAttrSec_UIVisualEffectView_QMUIForegroundColor; + +extern LookinAttrSectionIdentifier const LookinAttrSec_UIStackView_Axis; +extern LookinAttrSectionIdentifier const LookinAttrSec_UIStackView_Distribution; +extern LookinAttrSectionIdentifier const LookinAttrSec_UIStackView_Alignment; +extern LookinAttrSectionIdentifier const LookinAttrSec_UIStackView_Spacing; + +#pragma mark - Attr + +typedef NSString * LookinAttrIdentifier; + +extern LookinAttrIdentifier const LookinAttr_None; + +/// 用户自定义的 +extern LookinAttrIdentifier const LookinAttr_UserCustom; + +extern LookinAttrIdentifier const LookinAttr_Class_Class_Class; + +extern LookinAttrIdentifier const LookinAttr_Relation_Relation_Relation; + +extern LookinAttrIdentifier const LookinAttr_Layout_Frame_Frame; +extern LookinAttrIdentifier const LookinAttr_Layout_Bounds_Bounds; +extern LookinAttrIdentifier const LookinAttr_Layout_SafeArea_SafeArea; +extern LookinAttrIdentifier const LookinAttr_Layout_Position_Position; +extern LookinAttrIdentifier const LookinAttr_Layout_AnchorPoint_AnchorPoint; + +extern LookinAttrIdentifier const LookinAttr_AutoLayout_Hugging_Hor; +extern LookinAttrIdentifier const LookinAttr_AutoLayout_Hugging_Ver; +extern LookinAttrIdentifier const LookinAttr_AutoLayout_Resistance_Hor; +extern LookinAttrIdentifier const LookinAttr_AutoLayout_Resistance_Ver; +extern LookinAttrIdentifier const LookinAttr_AutoLayout_Constraints_Constraints; +extern LookinAttrIdentifier const LookinAttr_AutoLayout_IntrinsicSize_Size; + +extern LookinAttrIdentifier const LookinAttr_ViewLayer_Visibility_Hidden; +extern LookinAttrIdentifier const LookinAttr_ViewLayer_Visibility_Opacity; +extern LookinAttrIdentifier const LookinAttr_ViewLayer_InterationAndMasks_Interaction; +extern LookinAttrIdentifier const LookinAttr_ViewLayer_InterationAndMasks_MasksToBounds; +extern LookinAttrIdentifier const LookinAttr_ViewLayer_Corner_Radius; +extern LookinAttrIdentifier const LookinAttr_ViewLayer_BgColor_BgColor; +extern LookinAttrIdentifier const LookinAttr_ViewLayer_Border_Color; +extern LookinAttrIdentifier const LookinAttr_ViewLayer_Border_Width; +extern LookinAttrIdentifier const LookinAttr_ViewLayer_Shadow_Color; +extern LookinAttrIdentifier const LookinAttr_ViewLayer_Shadow_Opacity; +extern LookinAttrIdentifier const LookinAttr_ViewLayer_Shadow_Radius; +extern LookinAttrIdentifier const LookinAttr_ViewLayer_Shadow_OffsetW; +extern LookinAttrIdentifier const LookinAttr_ViewLayer_Shadow_OffsetH; +extern LookinAttrIdentifier const LookinAttr_ViewLayer_ContentMode_Mode; +extern LookinAttrIdentifier const LookinAttr_ViewLayer_TintColor_Color; +extern LookinAttrIdentifier const LookinAttr_ViewLayer_TintColor_Mode; +extern LookinAttrIdentifier const LookinAttr_ViewLayer_Tag_Tag; + +extern LookinAttrIdentifier const LookinAttr_UIImageView_Name_Name; +extern LookinAttrIdentifier const LookinAttr_UIImageView_Open_Open; + +extern LookinAttrIdentifier const LookinAttr_UILabel_Text_Text; +extern LookinAttrIdentifier const LookinAttr_UILabel_Font_Name; +extern LookinAttrIdentifier const LookinAttr_UILabel_Font_Size; +extern LookinAttrIdentifier const LookinAttr_UILabel_NumberOfLines_NumberOfLines; +extern LookinAttrIdentifier const LookinAttr_UILabel_TextColor_Color; +extern LookinAttrIdentifier const LookinAttr_UILabel_Alignment_Alignment; +extern LookinAttrIdentifier const LookinAttr_UILabel_BreakMode_Mode; +extern LookinAttrIdentifier const LookinAttr_UILabel_CanAdjustFont_CanAdjustFont; + +extern LookinAttrIdentifier const LookinAttr_UIControl_EnabledSelected_Enabled; +extern LookinAttrIdentifier const LookinAttr_UIControl_EnabledSelected_Selected; +extern LookinAttrIdentifier const LookinAttr_UIControl_VerAlignment_Alignment; +extern LookinAttrIdentifier const LookinAttr_UIControl_HorAlignment_Alignment; +extern LookinAttrIdentifier const LookinAttr_UIControl_QMUIOutsideEdge_Edge; + +extern LookinAttrIdentifier const LookinAttr_UIButton_ContentInsets_Insets; +extern LookinAttrIdentifier const LookinAttr_UIButton_TitleInsets_Insets; +extern LookinAttrIdentifier const LookinAttr_UIButton_ImageInsets_Insets; + +extern LookinAttrIdentifier const LookinAttr_UIScrollView_Offset_Offset; +extern LookinAttrIdentifier const LookinAttr_UIScrollView_ContentSize_Size; +extern LookinAttrIdentifier const LookinAttr_UIScrollView_ContentInset_Inset; +extern LookinAttrIdentifier const LookinAttr_UIScrollView_AdjustedInset_Inset; +extern LookinAttrIdentifier const LookinAttr_UIScrollView_Behavior_Behavior; +extern LookinAttrIdentifier const LookinAttr_UIScrollView_IndicatorInset_Inset; +extern LookinAttrIdentifier const LookinAttr_UIScrollView_ScrollPaging_ScrollEnabled; +extern LookinAttrIdentifier const LookinAttr_UIScrollView_ScrollPaging_PagingEnabled; +extern LookinAttrIdentifier const LookinAttr_UIScrollView_Bounce_Ver; +extern LookinAttrIdentifier const LookinAttr_UIScrollView_Bounce_Hor; +extern LookinAttrIdentifier const LookinAttr_UIScrollView_ShowsIndicator_Hor; +extern LookinAttrIdentifier const LookinAttr_UIScrollView_ShowsIndicator_Ver; +extern LookinAttrIdentifier const LookinAttr_UIScrollView_ContentTouches_Delay; +extern LookinAttrIdentifier const LookinAttr_UIScrollView_ContentTouches_CanCancel; +extern LookinAttrIdentifier const LookinAttr_UIScrollView_Zoom_MinScale; +extern LookinAttrIdentifier const LookinAttr_UIScrollView_Zoom_MaxScale; +extern LookinAttrIdentifier const LookinAttr_UIScrollView_Zoom_Scale; +extern LookinAttrIdentifier const LookinAttr_UIScrollView_Zoom_Bounce; +extern LookinAttrIdentifier const LookinAttr_UIScrollView_QMUIInitialInset_Inset; + +extern LookinAttrIdentifier const LookinAttr_UITableView_Style_Style; +extern LookinAttrIdentifier const LookinAttr_UITableView_SectionsNumber_Number; +extern LookinAttrIdentifier const LookinAttr_UITableView_RowsNumber_Number; +extern LookinAttrIdentifier const LookinAttr_UITableView_SeparatorInset_Inset; +extern LookinAttrIdentifier const LookinAttr_UITableView_SeparatorColor_Color; +extern LookinAttrIdentifier const LookinAttr_UITableView_SeparatorStyle_Style; + +extern LookinAttrIdentifier const LookinAttr_UITextView_Font_Name; +extern LookinAttrIdentifier const LookinAttr_UITextView_Font_Size; +extern LookinAttrIdentifier const LookinAttr_UITextView_Basic_Editable; +extern LookinAttrIdentifier const LookinAttr_UITextView_Basic_Selectable; +extern LookinAttrIdentifier const LookinAttr_UITextView_Text_Text; +extern LookinAttrIdentifier const LookinAttr_UITextView_TextColor_Color; +extern LookinAttrIdentifier const LookinAttr_UITextView_Alignment_Alignment; +extern LookinAttrIdentifier const LookinAttr_UITextView_ContainerInset_Inset; + +extern LookinAttrIdentifier const LookinAttr_UITextField_Text_Text; +extern LookinAttrIdentifier const LookinAttr_UITextField_Placeholder_Placeholder; +extern LookinAttrIdentifier const LookinAttr_UITextField_Font_Name; +extern LookinAttrIdentifier const LookinAttr_UITextField_Font_Size; +extern LookinAttrIdentifier const LookinAttr_UITextField_TextColor_Color; +extern LookinAttrIdentifier const LookinAttr_UITextField_Alignment_Alignment; +extern LookinAttrIdentifier const LookinAttr_UITextField_Clears_ClearsOnBeginEditing; +extern LookinAttrIdentifier const LookinAttr_UITextField_Clears_ClearsOnInsertion; +extern LookinAttrIdentifier const LookinAttr_UITextField_CanAdjustFont_CanAdjustFont; +extern LookinAttrIdentifier const LookinAttr_UITextField_CanAdjustFont_MinSize; +extern LookinAttrIdentifier const LookinAttr_UITextField_ClearButtonMode_Mode; + +extern LookinAttrIdentifier const LookinAttr_UIVisualEffectView_Style_Style; +extern LookinAttrIdentifier const LookinAttr_UIVisualEffectView_QMUIForegroundColor_Color; + +extern LookinAttrIdentifier const LookinAttr_UIStackView_Axis_Axis; +extern LookinAttrIdentifier const LookinAttr_UIStackView_Distribution_Distribution; +extern LookinAttrIdentifier const LookinAttr_UIStackView_Alignment_Alignment; +extern LookinAttrIdentifier const LookinAttr_UIStackView_Spacing_Spacing; + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinAttrIdentifiers.m b/Pods/LookinServer/Src/Main/Shared/LookinAttrIdentifiers.m new file mode 100644 index 0000000..29a1f98 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinAttrIdentifiers.m @@ -0,0 +1,253 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinAttrIdentifiers.m +// Lookin +// +// Created by Li Kai on 2019/9/18. +// https://lookin.work +// + + + +#import "LookinAttrIdentifiers.h" + +// value 不能重复(AppDelegate 里的 runTests 有相关 test) +// 如果要去掉某一项可以考虑注释掉而非直接删除,以防止新项和旧项的 value 相同而引发 preference 错乱(这些 value 会被存储到 userDefaults 里) + +#pragma mark - Group + +LookinAttrGroupIdentifier const LookinAttrGroup_None = @"n"; +LookinAttrGroupIdentifier const LookinAttrGroup_Class = @"c"; +LookinAttrGroupIdentifier const LookinAttrGroup_Relation = @"r"; +LookinAttrGroupIdentifier const LookinAttrGroup_Layout = @"l"; +LookinAttrGroupIdentifier const LookinAttrGroup_AutoLayout = @"a"; +LookinAttrGroupIdentifier const LookinAttrGroup_ViewLayer = @"vl"; +LookinAttrGroupIdentifier const LookinAttrGroup_UIImageView = @"i"; +LookinAttrGroupIdentifier const LookinAttrGroup_UILabel = @"la"; +LookinAttrGroupIdentifier const LookinAttrGroup_UIControl = @"co"; +LookinAttrGroupIdentifier const LookinAttrGroup_UIButton = @"b"; +LookinAttrGroupIdentifier const LookinAttrGroup_UIScrollView = @"s"; +LookinAttrGroupIdentifier const LookinAttrGroup_UITableView = @"ta"; +LookinAttrGroupIdentifier const LookinAttrGroup_UITextView = @"te"; +LookinAttrGroupIdentifier const LookinAttrGroup_UITextField = @"tf"; +LookinAttrGroupIdentifier const LookinAttrGroup_UIVisualEffectView = @"ve"; +LookinAttrGroupIdentifier const LookinAttrGroup_UIStackView = @"UIStackView"; + +LookinAttrGroupIdentifier const LookinAttrGroup_UserCustom = @"guc"; // user custom + +#pragma mark - Section + +LookinAttrSectionIdentifier const LookinAttrSec_None = @"n"; + +LookinAttrSectionIdentifier const LookinAttrSec_UserCustom = @"sec_ctm"; + +LookinAttrSectionIdentifier const LookinAttrSec_Class_Class = @"cl_c"; + +LookinAttrSectionIdentifier const LookinAttrSec_Relation_Relation = @"r_r"; + +LookinAttrSectionIdentifier const LookinAttrSec_Layout_Frame = @"l_f"; +LookinAttrSectionIdentifier const LookinAttrSec_Layout_Bounds = @"l_b"; +LookinAttrSectionIdentifier const LookinAttrSec_Layout_SafeArea = @"l_s"; +LookinAttrSectionIdentifier const LookinAttrSec_Layout_Position = @"l_p"; +LookinAttrSectionIdentifier const LookinAttrSec_Layout_AnchorPoint = @"l_a"; + +LookinAttrSectionIdentifier const LookinAttrSec_AutoLayout_Hugging = @"a_h"; +LookinAttrSectionIdentifier const LookinAttrSec_AutoLayout_Resistance = @"a_r"; +LookinAttrSectionIdentifier const LookinAttrSec_AutoLayout_Constraints = @"a_c"; +LookinAttrSectionIdentifier const LookinAttrSec_AutoLayout_IntrinsicSize = @"a_i"; + +LookinAttrSectionIdentifier const LookinAttrSec_ViewLayer_Visibility = @"v_v"; +LookinAttrSectionIdentifier const LookinAttrSec_ViewLayer_InterationAndMasks = @"v_i"; +LookinAttrSectionIdentifier const LookinAttrSec_ViewLayer_Corner = @"v_c"; +LookinAttrSectionIdentifier const LookinAttrSec_ViewLayer_BgColor = @"v_b"; +LookinAttrSectionIdentifier const LookinAttrSec_ViewLayer_Border = @"v_bo"; +LookinAttrSectionIdentifier const LookinAttrSec_ViewLayer_Shadow = @"v_s"; +LookinAttrSectionIdentifier const LookinAttrSec_ViewLayer_ContentMode = @"v_co"; +LookinAttrSectionIdentifier const LookinAttrSec_ViewLayer_TintColor = @"v_t"; +LookinAttrSectionIdentifier const LookinAttrSec_ViewLayer_Tag = @"v_ta"; + +LookinAttrSectionIdentifier const LookinAttrSec_UIImageView_Name = @"i_n"; +LookinAttrSectionIdentifier const LookinAttrSec_UIImageView_Open = @"i_o"; + +LookinAttrSectionIdentifier const LookinAttrSec_UILabel_Text = @"lb_t"; +LookinAttrSectionIdentifier const LookinAttrSec_UILabel_Font = @"lb_f"; +LookinAttrSectionIdentifier const LookinAttrSec_UILabel_NumberOfLines = @"lb_n"; +LookinAttrSectionIdentifier const LookinAttrSec_UILabel_TextColor = @"lb_tc"; +LookinAttrSectionIdentifier const LookinAttrSec_UILabel_BreakMode = @"lb_b"; +LookinAttrSectionIdentifier const LookinAttrSec_UILabel_Alignment = @"lb_a"; +LookinAttrSectionIdentifier const LookinAttrSec_UILabel_CanAdjustFont = @"lb_c"; + +LookinAttrSectionIdentifier const LookinAttrSec_UIControl_EnabledSelected = @"c_e"; +LookinAttrSectionIdentifier const LookinAttrSec_UIControl_VerAlignment = @"c_v"; +LookinAttrSectionIdentifier const LookinAttrSec_UIControl_HorAlignment = @"c_h"; +LookinAttrSectionIdentifier const LookinAttrSec_UIControl_QMUIOutsideEdge = @"c_o"; + +LookinAttrSectionIdentifier const LookinAttrSec_UIButton_ContentInsets = @"b_c"; +LookinAttrSectionIdentifier const LookinAttrSec_UIButton_TitleInsets = @"b_t"; +LookinAttrSectionIdentifier const LookinAttrSec_UIButton_ImageInsets = @"b_i"; + +LookinAttrSectionIdentifier const LookinAttrSec_UIScrollView_ContentInset = @"s_c"; +LookinAttrSectionIdentifier const LookinAttrSec_UIScrollView_AdjustedInset = @"s_a"; +LookinAttrSectionIdentifier const LookinAttrSec_UIScrollView_IndicatorInset = @"s_i"; +LookinAttrSectionIdentifier const LookinAttrSec_UIScrollView_Offset = @"s_o"; +LookinAttrSectionIdentifier const LookinAttrSec_UIScrollView_ContentSize = @"s_cs"; +LookinAttrSectionIdentifier const LookinAttrSec_UIScrollView_Behavior = @"s_b"; +LookinAttrSectionIdentifier const LookinAttrSec_UIScrollView_ShowsIndicator = @"s_si"; +LookinAttrSectionIdentifier const LookinAttrSec_UIScrollView_Bounce = @"s_bo"; +LookinAttrSectionIdentifier const LookinAttrSec_UIScrollView_ScrollPaging = @"s_s"; +LookinAttrSectionIdentifier const LookinAttrSec_UIScrollView_ContentTouches = @"s_ct"; +LookinAttrSectionIdentifier const LookinAttrSec_UIScrollView_Zoom = @"s_z"; +LookinAttrSectionIdentifier const LookinAttrSec_UIScrollView_QMUIInitialInset = @"s_ii"; + +LookinAttrSectionIdentifier const LookinAttrSec_UITableView_Style = @"t_s"; +LookinAttrSectionIdentifier const LookinAttrSec_UITableView_SectionsNumber = @"t_sn"; +LookinAttrSectionIdentifier const LookinAttrSec_UITableView_RowsNumber = @"t_r"; +LookinAttrSectionIdentifier const LookinAttrSec_UITableView_SeparatorStyle = @"t_ss"; +LookinAttrSectionIdentifier const LookinAttrSec_UITableView_SeparatorColor = @"t_sc"; +LookinAttrSectionIdentifier const LookinAttrSec_UITableView_SeparatorInset = @"t_si"; + +LookinAttrSectionIdentifier const LookinAttrSec_UITextView_Basic = @"tv_b"; +LookinAttrSectionIdentifier const LookinAttrSec_UITextView_Text = @"tv_t"; +LookinAttrSectionIdentifier const LookinAttrSec_UITextView_Font = @"tv_f"; +LookinAttrSectionIdentifier const LookinAttrSec_UITextView_TextColor = @"tv_tc"; +LookinAttrSectionIdentifier const LookinAttrSec_UITextView_Alignment = @"tv_a"; +LookinAttrSectionIdentifier const LookinAttrSec_UITextView_ContainerInset = @"tv_c"; + +LookinAttrSectionIdentifier const LookinAttrSec_UITextField_Text = @"tf_t"; +LookinAttrSectionIdentifier const LookinAttrSec_UITextField_Placeholder = @"tf_p"; +LookinAttrSectionIdentifier const LookinAttrSec_UITextField_Font = @"tf_f"; +LookinAttrSectionIdentifier const LookinAttrSec_UITextField_TextColor = @"tf_tc"; +LookinAttrSectionIdentifier const LookinAttrSec_UITextField_Alignment = @"tf_a"; +LookinAttrSectionIdentifier const LookinAttrSec_UITextField_Clears = @"tf_c"; +LookinAttrSectionIdentifier const LookinAttrSec_UITextField_CanAdjustFont = @"tf_ca"; +LookinAttrSectionIdentifier const LookinAttrSec_UITextField_ClearButtonMode = @"tf_cb"; + +LookinAttrSectionIdentifier const LookinAttrSec_UIVisualEffectView_Style = @"ve_s"; +LookinAttrSectionIdentifier const LookinAttrSec_UIVisualEffectView_QMUIForegroundColor = @"ve_f"; + +LookinAttrSectionIdentifier const LookinAttrSec_UIStackView_Axis = @"usv_axis"; +LookinAttrSectionIdentifier const LookinAttrSec_UIStackView_Distribution = @"usv_dis"; +LookinAttrSectionIdentifier const LookinAttrSec_UIStackView_Alignment = @"usv_align"; +LookinAttrSectionIdentifier const LookinAttrSec_UIStackView_Spacing = @"usv_spa"; + +#pragma mark - Attr + +LookinAttrIdentifier const LookinAttr_None = @"n"; +LookinAttrIdentifier const LookinAttr_UserCustom = @"ctm"; + +LookinAttrIdentifier const LookinAttr_Class_Class_Class = @"c_c_c"; + + +LookinAttrIdentifier const LookinAttr_Relation_Relation_Relation = @"r_r_r"; + +LookinAttrIdentifier const LookinAttr_Layout_Frame_Frame = @"l_f_f"; +LookinAttrIdentifier const LookinAttr_Layout_Bounds_Bounds = @"l_b_b"; +LookinAttrIdentifier const LookinAttr_Layout_SafeArea_SafeArea = @"l_s_s"; +LookinAttrIdentifier const LookinAttr_Layout_Position_Position = @"l_p_p"; +LookinAttrIdentifier const LookinAttr_Layout_AnchorPoint_AnchorPoint = @"l_a_a"; + +LookinAttrIdentifier const LookinAttr_AutoLayout_Hugging_Hor = @"al_h_h"; +LookinAttrIdentifier const LookinAttr_AutoLayout_Hugging_Ver = @"al_h_v"; +LookinAttrIdentifier const LookinAttr_AutoLayout_Resistance_Hor = @"al_r_h"; +LookinAttrIdentifier const LookinAttr_AutoLayout_Resistance_Ver = @"al_r_v"; +LookinAttrIdentifier const LookinAttr_AutoLayout_Constraints_Constraints = @"al_c_c"; +LookinAttrIdentifier const LookinAttr_AutoLayout_IntrinsicSize_Size = @"cl_i_s"; + +LookinAttrIdentifier const LookinAttr_ViewLayer_Visibility_Hidden = @"vl_v_h"; +LookinAttrIdentifier const LookinAttr_ViewLayer_Visibility_Opacity = @"vl_v_o"; +LookinAttrIdentifier const LookinAttr_ViewLayer_InterationAndMasks_Interaction = @"vl_i_i"; +LookinAttrIdentifier const LookinAttr_ViewLayer_InterationAndMasks_MasksToBounds = @"vl_i_m"; +LookinAttrIdentifier const LookinAttr_ViewLayer_Corner_Radius = @"vl_c_r"; +LookinAttrIdentifier const LookinAttr_ViewLayer_BgColor_BgColor = @"vl_b_b"; +LookinAttrIdentifier const LookinAttr_ViewLayer_Border_Color = @"vl_b_c"; +LookinAttrIdentifier const LookinAttr_ViewLayer_Border_Width = @"vl_b_w"; +LookinAttrIdentifier const LookinAttr_ViewLayer_Shadow_Color = @"vl_s_c"; +LookinAttrIdentifier const LookinAttr_ViewLayer_Shadow_Opacity = @"vl_s_o"; +LookinAttrIdentifier const LookinAttr_ViewLayer_Shadow_Radius = @"vl_s_r"; +LookinAttrIdentifier const LookinAttr_ViewLayer_Shadow_OffsetW = @"vl_s_ow"; +LookinAttrIdentifier const LookinAttr_ViewLayer_Shadow_OffsetH = @"vl_s_oh"; +LookinAttrIdentifier const LookinAttr_ViewLayer_ContentMode_Mode = @"vl_c_m"; +LookinAttrIdentifier const LookinAttr_ViewLayer_TintColor_Color = @"vl_t_c"; +LookinAttrIdentifier const LookinAttr_ViewLayer_TintColor_Mode = @"vl_t_m"; +LookinAttrIdentifier const LookinAttr_ViewLayer_Tag_Tag = @"vl_t_t"; + +LookinAttrIdentifier const LookinAttr_UIImageView_Name_Name = @"iv_n_n"; +LookinAttrIdentifier const LookinAttr_UIImageView_Open_Open = @"iv_o_o"; + +LookinAttrIdentifier const LookinAttr_UILabel_Text_Text = @"lb_t_t"; +LookinAttrIdentifier const LookinAttr_UILabel_Font_Name = @"lb_f_n"; +LookinAttrIdentifier const LookinAttr_UILabel_Font_Size = @"lb_f_s"; +LookinAttrIdentifier const LookinAttr_UILabel_NumberOfLines_NumberOfLines = @"lb_n_n"; +LookinAttrIdentifier const LookinAttr_UILabel_TextColor_Color = @"lb_t_c"; +LookinAttrIdentifier const LookinAttr_UILabel_Alignment_Alignment = @"lb_a_a"; +LookinAttrIdentifier const LookinAttr_UILabel_BreakMode_Mode = @"lb_b_m"; +LookinAttrIdentifier const LookinAttr_UILabel_CanAdjustFont_CanAdjustFont = @"lb_c_c"; + +LookinAttrIdentifier const LookinAttr_UIControl_EnabledSelected_Enabled = @"ct_e_e"; +LookinAttrIdentifier const LookinAttr_UIControl_EnabledSelected_Selected = @"ct_e_s"; +LookinAttrIdentifier const LookinAttr_UIControl_VerAlignment_Alignment = @"ct_v_a"; +LookinAttrIdentifier const LookinAttr_UIControl_HorAlignment_Alignment = @"ct_h_a"; +LookinAttrIdentifier const LookinAttr_UIControl_QMUIOutsideEdge_Edge = @"ct_o_e"; + +LookinAttrIdentifier const LookinAttr_UIButton_ContentInsets_Insets = @"bt_c_i"; +LookinAttrIdentifier const LookinAttr_UIButton_TitleInsets_Insets = @"bt_t_i"; +LookinAttrIdentifier const LookinAttr_UIButton_ImageInsets_Insets = @"bt_i_i"; + +LookinAttrIdentifier const LookinAttr_UIScrollView_Offset_Offset = @"sv_o_o"; +LookinAttrIdentifier const LookinAttr_UIScrollView_ContentSize_Size = @"sv_c_s"; +LookinAttrIdentifier const LookinAttr_UIScrollView_ContentInset_Inset = @"sv_c_i"; +LookinAttrIdentifier const LookinAttr_UIScrollView_AdjustedInset_Inset = @"sv_a_i"; +LookinAttrIdentifier const LookinAttr_UIScrollView_Behavior_Behavior = @"sv_b_b"; +LookinAttrIdentifier const LookinAttr_UIScrollView_IndicatorInset_Inset = @"sv_i_i"; +LookinAttrIdentifier const LookinAttr_UIScrollView_ScrollPaging_ScrollEnabled = @"sv_s_s"; +LookinAttrIdentifier const LookinAttr_UIScrollView_ScrollPaging_PagingEnabled = @"sv_s_p"; +LookinAttrIdentifier const LookinAttr_UIScrollView_Bounce_Ver = @"sv_b_v"; +LookinAttrIdentifier const LookinAttr_UIScrollView_Bounce_Hor = @"sv_b_h"; +LookinAttrIdentifier const LookinAttr_UIScrollView_ShowsIndicator_Hor = @"sv_h_h"; +LookinAttrIdentifier const LookinAttr_UIScrollView_ShowsIndicator_Ver = @"sv_s_v"; +LookinAttrIdentifier const LookinAttr_UIScrollView_ContentTouches_Delay = @"sv_c_d"; +LookinAttrIdentifier const LookinAttr_UIScrollView_ContentTouches_CanCancel = @"sv_c_c"; +LookinAttrIdentifier const LookinAttr_UIScrollView_Zoom_MinScale = @"sv_z_mi"; +LookinAttrIdentifier const LookinAttr_UIScrollView_Zoom_MaxScale = @"sv_z_ma"; +LookinAttrIdentifier const LookinAttr_UIScrollView_Zoom_Scale = @"sv_z_s"; +LookinAttrIdentifier const LookinAttr_UIScrollView_Zoom_Bounce = @"sv_z_b"; +LookinAttrIdentifier const LookinAttr_UIScrollView_QMUIInitialInset_Inset = @"sv_qi_i"; + +LookinAttrIdentifier const LookinAttr_UITableView_Style_Style = @"tv_s_s"; +LookinAttrIdentifier const LookinAttr_UITableView_SectionsNumber_Number = @"tv_s_n"; +LookinAttrIdentifier const LookinAttr_UITableView_RowsNumber_Number = @"tv_r_n"; +LookinAttrIdentifier const LookinAttr_UITableView_SeparatorInset_Inset = @"tv_s_i"; +LookinAttrIdentifier const LookinAttr_UITableView_SeparatorColor_Color = @"tv_s_c"; +LookinAttrIdentifier const LookinAttr_UITableView_SeparatorStyle_Style = @"tv_ss_s"; + +LookinAttrIdentifier const LookinAttr_UITextView_Font_Name = @"te_f_n"; +LookinAttrIdentifier const LookinAttr_UITextView_Font_Size = @"te_f_s"; +LookinAttrIdentifier const LookinAttr_UITextView_Basic_Editable = @"te_b_e"; +LookinAttrIdentifier const LookinAttr_UITextView_Basic_Selectable = @"te_b_s"; +LookinAttrIdentifier const LookinAttr_UITextView_Text_Text = @"te_t_t"; +LookinAttrIdentifier const LookinAttr_UITextView_TextColor_Color = @"te_t_c"; +LookinAttrIdentifier const LookinAttr_UITextView_Alignment_Alignment = @"te_a_a"; +LookinAttrIdentifier const LookinAttr_UITextView_ContainerInset_Inset = @"te_c_i"; + +LookinAttrIdentifier const LookinAttr_UITextField_Text_Text = @"tf_t_t"; +LookinAttrIdentifier const LookinAttr_UITextField_Placeholder_Placeholder = @"tf_p_p"; +LookinAttrIdentifier const LookinAttr_UITextField_Font_Name = @"tf_f_n"; +LookinAttrIdentifier const LookinAttr_UITextField_Font_Size = @"tf_f_s"; +LookinAttrIdentifier const LookinAttr_UITextField_TextColor_Color = @"tf_t_c"; +LookinAttrIdentifier const LookinAttr_UITextField_Alignment_Alignment = @"tf_a_a"; +LookinAttrIdentifier const LookinAttr_UITextField_Clears_ClearsOnBeginEditing = @"tf_c_c"; +LookinAttrIdentifier const LookinAttr_UITextField_Clears_ClearsOnInsertion = @"tf_c_co"; +LookinAttrIdentifier const LookinAttr_UITextField_CanAdjustFont_CanAdjustFont = @"tf_c_ca"; +LookinAttrIdentifier const LookinAttr_UITextField_CanAdjustFont_MinSize = @"tf_c_m"; +LookinAttrIdentifier const LookinAttr_UITextField_ClearButtonMode_Mode = @"tf_cb_m"; + +LookinAttrIdentifier const LookinAttr_UIVisualEffectView_Style_Style = @"ve_s_s"; +LookinAttrIdentifier const LookinAttr_UIVisualEffectView_QMUIForegroundColor_Color = @"ve_f_c"; + +LookinAttrIdentifier const LookinAttr_UIStackView_Axis_Axis = @"usv_axis_axis"; +LookinAttrIdentifier const LookinAttr_UIStackView_Distribution_Distribution = @"usv_dis_dis"; +LookinAttrIdentifier const LookinAttr_UIStackView_Alignment_Alignment = @"usv_ali_ali"; +LookinAttrIdentifier const LookinAttr_UIStackView_Spacing_Spacing = @"usv_spa_spa"; + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinAttrType.h b/Pods/LookinServer/Src/Main/Shared/LookinAttrType.h new file mode 100644 index 0000000..feba9ce --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinAttrType.h @@ -0,0 +1,50 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinAttrIdentifiers.h +// Lookin +// +// Created by Li Kai on 2018/12/1. +// https://lookin.work +// + +/// 注意:新属性只能加到末尾,否则新旧版本搭配时可能有兼容问题 +typedef NS_ENUM(NSInteger, LookinAttrType) { + LookinAttrTypeNone, + LookinAttrTypeVoid, + LookinAttrTypeChar, + LookinAttrTypeInt, + LookinAttrTypeShort, + LookinAttrTypeLong, + LookinAttrTypeLongLong, + LookinAttrTypeUnsignedChar, + LookinAttrTypeUnsignedInt, + LookinAttrTypeUnsignedShort, + LookinAttrTypeUnsignedLong, + LookinAttrTypeUnsignedLongLong, + LookinAttrTypeFloat, + LookinAttrTypeDouble, + LookinAttrTypeBOOL, + LookinAttrTypeSel, + LookinAttrTypeClass, + LookinAttrTypeCGPoint, + LookinAttrTypeCGVector, + LookinAttrTypeCGSize, + LookinAttrTypeCGRect, + LookinAttrTypeCGAffineTransform, + LookinAttrTypeUIEdgeInsets, + LookinAttrTypeUIOffset, + LookinAttrTypeNSString, + LookinAttrTypeEnumInt, + LookinAttrTypeEnumLong, + /// value 实际为 RGBA 数组,即 @[NSNumber, NSNumber, NSNumber, NSNumber],NSNumber 范围是 0 ~ 1 + LookinAttrTypeUIColor, + /// 业务需要根据具体的 AttrIdentifier 来解析 + LookinAttrTypeCustomObj, + + LookinAttrTypeEnumString, + LookinAttrTypeShadow, + LookinAttrTypeJson +}; + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinAttribute.h b/Pods/LookinServer/Src/Main/Shared/LookinAttribute.h new file mode 100644 index 0000000..d86f298 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinAttribute.h @@ -0,0 +1,48 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinAttribute.h +// qmuidemo +// +// Created by Li Kai on 2018/11/17. +// Copyright © 2018 QMUI Team. All rights reserved. +// + +#import "LookinAttrIdentifiers.h" +#import "LookinCodingValueType.h" +#import "LookinAttrType.h" + +@class LookinDisplayItem; + +@interface LookinAttribute : NSObject + +@property(nonatomic, copy) LookinAttrIdentifier identifier; + +/// 只有 Custom Attr 才有该属性 +@property(nonatomic, copy) NSString *displayTitle; + +/// 标识 value 的具体类型(如 double / NSString /...) +@property(nonatomic, assign) LookinAttrType attrType; + +/// 具体的值,需配合 attrType 属性来解析它 +/// 对于 String、Color 等 attyType,该属性可能为 nil +@property(nonatomic, strong) id value; + +/// 额外信息,大部分情况下它是 nil +/// 当 attyType 为 LookinAttrTypeEnumString 时,extraValue 是一个 [String] 且保存了 allEnumCases +@property(nonatomic, strong) id extraValue; + +/// 仅 Custom Attr 可能有该属性 +/// 对于有 retainedSetter 的 Custom Attr,它的 setter 会以 customSetterID 作为 key 被保存到 LKS_CustomAttrSetterManager 里,后续可以通过这个 uniqueID 重新把 setter 从 LKS_CustomAttrSetterManager 里取出来并调用 +@property(nonatomic, copy) NSString *customSetterID; + +#pragma mark - 以下属性不会参与 encode/decode + +/// 标识该 LookinAttribute 对象隶属于哪一个 LookinDisplayItem +@property(nonatomic, weak) LookinDisplayItem *targetDisplayItem; + +- (BOOL)isUserCustom; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinAttribute.m b/Pods/LookinServer/Src/Main/Shared/LookinAttribute.m new file mode 100644 index 0000000..c0625d7 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinAttribute.m @@ -0,0 +1,64 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinAttribute.m +// qmuidemo +// +// Created by Li Kai on 2018/11/17. +// Copyright © 2018 QMUI Team. All rights reserved. +// + + + +#import "LookinAttribute.h" +#import "LookinDisplayItem.h" + +@implementation LookinAttribute + +#pragma mark - + +- (id)copyWithZone:(NSZone *)zone { + LookinAttribute *newAttr = [[LookinAttribute allocWithZone:zone] init]; + newAttr.identifier = self.identifier; + newAttr.displayTitle = self.displayTitle; + newAttr.value = self.value; + newAttr.attrType = self.attrType; + newAttr.extraValue = self.extraValue; + newAttr.customSetterID = self.customSetterID; + return newAttr; +} + +#pragma mark - + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:self.displayTitle forKey:@"displayTitle"]; + [aCoder encodeObject:self.identifier forKey:@"identifier"]; + [aCoder encodeInteger:self.attrType forKey:@"attrType"]; + [aCoder encodeObject:self.value forKey:@"value"]; + [aCoder encodeObject:self.extraValue forKey:@"extraValue"]; + [aCoder encodeObject:self.customSetterID forKey:@"customSetterID"]; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if (self = [super init]) { + self.displayTitle = [aDecoder decodeObjectForKey:@"displayTitle"]; + self.identifier = [aDecoder decodeObjectForKey:@"identifier"]; + self.attrType = [aDecoder decodeIntegerForKey:@"attrType"]; + self.value = [aDecoder decodeObjectForKey:@"value"]; + self.extraValue = [aDecoder decodeObjectForKey:@"extraValue"]; + self.customSetterID = [aDecoder decodeObjectForKey:@"customSetterID"]; + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isUserCustom { + return [self.identifier isEqualToString:LookinAttr_UserCustom]; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinAttributeModification.h b/Pods/LookinServer/Src/Main/Shared/LookinAttributeModification.h new file mode 100644 index 0000000..c9357e0 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinAttributeModification.h @@ -0,0 +1,31 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinAttributeModification.h +// Lookin +// +// Created by Li Kai on 2018/11/20. +// https://lookin.work +// + + + +#import +#import "LookinAttrType.h" + +@interface LookinAttributeModification : NSObject + +@property(nonatomic, assign) unsigned long targetOid; + +@property(nonatomic, assign) SEL setterSelector; +@property(nonatomic, assign) SEL getterSelector; + +@property(nonatomic, assign) LookinAttrType attrType; +@property(nonatomic, strong) id value; + +/// 1.0.4 开始加入这个参数 +@property(nonatomic, copy) NSString *clientReadableVersion; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinAttributeModification.m b/Pods/LookinServer/Src/Main/Shared/LookinAttributeModification.m new file mode 100644 index 0000000..39f16c9 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinAttributeModification.m @@ -0,0 +1,40 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinAttributeModification.m +// Lookin +// +// Created by Li Kai on 2018/11/20. +// https://lookin.work +// + +#import "LookinAttributeModification.h" + +@implementation LookinAttributeModification + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:@(self.targetOid) forKey:@"targetOid"]; + [aCoder encodeObject:NSStringFromSelector(self.setterSelector) forKey:@"setterSelector"]; + [aCoder encodeInteger:self.attrType forKey:@"attrType"]; + [aCoder encodeObject:self.value forKey:@"value"]; + [aCoder encodeObject:self.clientReadableVersion forKey:@"clientReadableVersion"]; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if (self = [super init]) { + self.targetOid = [[aDecoder decodeObjectForKey:@"targetOid"] unsignedLongValue]; + self.setterSelector = NSSelectorFromString([aDecoder decodeObjectForKey:@"setterSelector"]); + self.attrType = [aDecoder decodeIntegerForKey:@"attrType"]; + self.value = [aDecoder decodeObjectForKey:@"value"]; + self.clientReadableVersion = [aDecoder decodeObjectForKey:@"clientReadableVersion"]; + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinAttributesGroup.h b/Pods/LookinServer/Src/Main/Shared/LookinAttributesGroup.h new file mode 100644 index 0000000..e8ee7ed --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinAttributesGroup.h @@ -0,0 +1,41 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinAttributesGroup.h +// Lookin +// +// Created by Li Kai on 2018/11/19. +// https://lookin.work +// + + + +#import +#import "LookinAttrIdentifiers.h" + +@class LookinAttributesSection; + +/** + In Lookin, a LookinAttributesGroup instance will be rendered as a property card. + + When isUserCustom is false: two LookinAttributesGroup instances will be regard as equal when they has the same LookinAttrGroupIdentifier. + When isUserCustom is true: two LookinAttributesGroup instances will be regard as equal when they has the same title. + 当 isUserCustom 为 false 时:若两个 attrGroup 有相同的 LookinAttrGroupIdentifier,则 isEqual: 返回 YES + */ +@interface LookinAttributesGroup : NSObject + +/// 只有在 identifier 为 custom 时,才存在该值 +@property(nonatomic, copy) NSString *userCustomTitle; + +@property(nonatomic, copy) LookinAttrGroupIdentifier identifier; + +@property(nonatomic, copy) NSArray *attrSections; + +/// 如果是 custom 则返回 userCustomTitle,如果不是 custom 则返回 identifier +- (NSString *)uniqueKey; + +- (BOOL)isUserCustom; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinAttributesGroup.m b/Pods/LookinServer/Src/Main/Shared/LookinAttributesGroup.m new file mode 100644 index 0000000..49a4825 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinAttributesGroup.m @@ -0,0 +1,92 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinAttributesGroup.m +// Lookin +// +// Created by Li Kai on 2018/11/19. +// https://lookin.work +// + + + +#import "LookinAttributesGroup.h" +#import "LookinAttribute.h" +#import "LookinAttributesSection.h" +#import "LookinDashboardBlueprint.h" +#import "NSArray+Lookin.h" + +@implementation LookinAttributesGroup + +#pragma mark - + +- (id)copyWithZone:(NSZone *)zone { + LookinAttributesGroup *newGroup = [[LookinAttributesGroup allocWithZone:zone] init]; + newGroup.userCustomTitle = self.userCustomTitle; + newGroup.identifier = self.identifier; + newGroup.attrSections = [self.attrSections lookin_map:^id(NSUInteger idx, LookinAttributesSection *value) { + return value.copy; + }]; + return newGroup; +} + +#pragma mark - + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:self.userCustomTitle forKey:@"userCustomTitle"]; + [aCoder encodeObject:self.identifier forKey:@"identifier"]; + [aCoder encodeObject:self.attrSections forKey:@"attrSections"]; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if (self = [super init]) { + self.userCustomTitle = [aDecoder decodeObjectForKey:@"userCustomTitle"]; + self.identifier = [aDecoder decodeObjectForKey:@"identifier"]; + self.attrSections = [aDecoder decodeObjectForKey:@"attrSections"]; + } + return self; +} + +- (NSUInteger)hash { + return self.uniqueKey.hash; +} + +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[LookinAttributesGroup class]]) { + return NO; + } + LookinAttributesGroup *targetObject = object; + + if (![self.identifier isEqualToString:targetObject.identifier]) { + return false; + } + if ([self.identifier isEqualToString:LookinAttrGroup_UserCustom]) { + BOOL ret = [self.userCustomTitle isEqualToString:targetObject.userCustomTitle]; + return ret; + } else { + return true; + } +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (NSString *)uniqueKey { + if ([self.identifier isEqualToString:LookinAttrGroup_UserCustom]) { + return self.userCustomTitle; + } else { + return self.identifier; + } +} + +- (BOOL)isUserCustom { + return [self.identifier isEqualToString:LookinAttrSec_UserCustom]; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinAttributesSection.h b/Pods/LookinServer/Src/Main/Shared/LookinAttributesSection.h new file mode 100644 index 0000000..32ddec8 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinAttributesSection.h @@ -0,0 +1,35 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinAttributesSection.h +// Lookin +// +// Created by Li Kai on 2019/3/2. +// https://lookin.work +// + + + +#import +#import "LookinAttrIdentifiers.h" + +@class LookinAttribute; + +typedef NS_ENUM (NSInteger, LookinAttributesSectionStyle) { + LookinAttributesSectionStyleDefault, // 每个 attr 独占一行 + LookinAttributesSectionStyle0, // frame 等卡片使用,前 4 个 attr 每行两个,之后每个 attr 在同一排,每个宽度为 1/4 + LookinAttributesSectionStyle1, // 第一个 attr 在第一排靠左,第二个 attr 在第一排靠右,之后的 attr 每个独占一行 + LookinAttributesSectionStyle2 // 第一排独占一行,剩下的在同一行且均分宽度 +}; + +@interface LookinAttributesSection : NSObject + +@property(nonatomic, copy) LookinAttrSectionIdentifier identifier; + +@property(nonatomic, copy) NSArray *attributes; + +- (BOOL)isUserCustom; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinAttributesSection.m b/Pods/LookinServer/Src/Main/Shared/LookinAttributesSection.m new file mode 100644 index 0000000..7617c09 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinAttributesSection.m @@ -0,0 +1,56 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinAttributesSection.m +// Lookin +// +// Created by Li Kai on 2019/3/2. +// https://lookin.work +// + + + +#import "LookinAttributesSection.h" +#import "LookinAttribute.h" + +#import "NSArray+Lookin.h" + +@implementation LookinAttributesSection + +#pragma mark - + +- (id)copyWithZone:(NSZone *)zone { + LookinAttributesSection *newSection = [[LookinAttributesSection allocWithZone:zone] init]; + newSection.identifier = self.identifier; + newSection.attributes = [self.attributes lookin_map:^id(NSUInteger idx, LookinAttribute *value) { + return value.copy; + }]; + return newSection; +} + +#pragma mark - + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:self.identifier forKey:@"identifier"]; + [aCoder encodeObject:self.attributes forKey:@"attributes"]; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if (self = [super init]) { + self.identifier = [aDecoder decodeObjectForKey:@"identifier"]; + self.attributes = [aDecoder decodeObjectForKey:@"attributes"]; + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isUserCustom { + return [self.identifier isEqualToString:LookinAttrSec_UserCustom]; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinAutoLayoutConstraint.h b/Pods/LookinServer/Src/Main/Shared/LookinAutoLayoutConstraint.h new file mode 100644 index 0000000..3edf865 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinAutoLayoutConstraint.h @@ -0,0 +1,51 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinAutoLayoutConstraint.h +// Lookin +// +// Created by Li Kai on 2019/9/28. +// https://lookin.work +// + + + +#import "LookinDefines.h" + +@class LookinObject; + +typedef NS_ENUM(NSInteger, LookinConstraintItemType) { + LookinConstraintItemTypeUnknown, + LookinConstraintItemTypeNil, + LookinConstraintItemTypeView, + LookinConstraintItemTypeSelf, + LookinConstraintItemTypeSuper, + LookinConstraintItemTypeLayoutGuide +}; + +@interface LookinAutoLayoutConstraint : NSObject + +#if TARGET_OS_IPHONE ++ (instancetype)instanceFromNSConstraint:(NSLayoutConstraint *)constraint isEffective:(BOOL)isEffective firstItemType:(LookinConstraintItemType)firstItemType secondItemType:(LookinConstraintItemType)secondItemType; +#endif + +@property(nonatomic, assign) BOOL effective; +@property(nonatomic, assign) BOOL active; +@property(nonatomic, assign) BOOL shouldBeArchived; +@property(nonatomic, strong) LookinObject *firstItem; +@property(nonatomic, assign) LookinConstraintItemType firstItemType; +/// iOS 里的 NSLayoutAttribute,注意 iOS 和 macOS 虽然都有 NSLayoutAttribute 但是 value 非常不同,因此这里使用 NSInteger 避免混淆 +@property(nonatomic, assign) NSInteger firstAttribute; +@property(nonatomic, assign) NSLayoutRelation relation; +@property(nonatomic, strong) LookinObject *secondItem; +@property(nonatomic, assign) LookinConstraintItemType secondItemType; +/// iOS 里的 NSLayoutAttribute,注意 iOS 和 macOS 虽然都有 NSLayoutAttribute 但是 value 非常不同,因此这里使用 NSInteger 避免混淆 +@property(nonatomic, assign) NSInteger secondAttribute; +@property(nonatomic, assign) CGFloat multiplier; +@property(nonatomic, assign) CGFloat constant; +@property(nonatomic, assign) CGFloat priority; +@property(nonatomic, copy) NSString *identifier; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinAutoLayoutConstraint.m b/Pods/LookinServer/Src/Main/Shared/LookinAutoLayoutConstraint.m new file mode 100644 index 0000000..a8e4520 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinAutoLayoutConstraint.m @@ -0,0 +1,107 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinAutoLayoutConstraint.m +// Lookin +// +// Created by Li Kai on 2019/9/28. +// https://lookin.work +// + + + +#import "LookinAutoLayoutConstraint.h" +#import "LookinObject.h" + +@implementation LookinAutoLayoutConstraint + +#if TARGET_OS_IPHONE + ++ (instancetype)instanceFromNSConstraint:(NSLayoutConstraint *)constraint isEffective:(BOOL)isEffective firstItemType:(LookinConstraintItemType)firstItemType secondItemType:(LookinConstraintItemType)secondItemType { + LookinAutoLayoutConstraint *instance = [LookinAutoLayoutConstraint new]; + instance.effective = isEffective; + instance.active = constraint.active; + instance.shouldBeArchived = constraint.shouldBeArchived; + instance.firstItem = [LookinObject instanceWithObject:constraint.firstItem]; + instance.firstItemType = firstItemType; + instance.firstAttribute = constraint.firstAttribute; + instance.relation = constraint.relation; + instance.secondItem = [LookinObject instanceWithObject:constraint.secondItem]; + instance.secondItemType = secondItemType; + instance.secondAttribute = constraint.secondAttribute; + instance.multiplier = constraint.multiplier; + instance.constant = constraint.constant; + instance.priority = constraint.priority; + instance.identifier = constraint.identifier; + + return instance; +} + +- (void)setFirstAttribute:(NSInteger)firstAttribute { + _firstAttribute = firstAttribute; + [self _assertUnknownAttribute:firstAttribute]; +} + +- (void)setSecondAttribute:(NSInteger)secondAttribute { + _secondAttribute = secondAttribute; + [self _assertUnknownAttribute:secondAttribute]; +} + +- (void)_assertUnknownAttribute:(NSInteger)attribute { + // 以下几个 assert 用来帮助发现那些系统私有的定义,正式发布时应该去掉这几个 assert + if (attribute > 20 && attribute < 32) { + NSAssert(NO, nil); + } + if (attribute > 37) { + NSAssert(NO, nil); + } +} + +#endif + +#pragma mark - + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeBool:self.effective forKey:@"effective"]; + [aCoder encodeBool:self.active forKey:@"active"]; + [aCoder encodeBool:self.shouldBeArchived forKey:@"shouldBeArchived"]; + [aCoder encodeObject:self.firstItem forKey:@"firstItem"]; + [aCoder encodeInteger:self.firstItemType forKey:@"firstItemType"]; + [aCoder encodeInteger:self.firstAttribute forKey:@"firstAttribute"]; + [aCoder encodeInteger:self.relation forKey:@"relation"]; + [aCoder encodeObject:self.secondItem forKey:@"secondItem"]; + [aCoder encodeInteger:self.secondItemType forKey:@"secondItemType"]; + [aCoder encodeInteger:self.secondAttribute forKey:@"secondAttribute"]; + [aCoder encodeDouble:self.multiplier forKey:@"multiplier"]; + [aCoder encodeDouble:self.constant forKey:@"constant"]; + [aCoder encodeDouble:self.priority forKey:@"priority"]; + [aCoder encodeObject:self.identifier forKey:@"identifier"]; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if (self = [super init]) { + self.effective = [aDecoder decodeBoolForKey:@"effective"]; + self.active = [aDecoder decodeBoolForKey:@"active"]; + self.shouldBeArchived = [aDecoder decodeBoolForKey:@"shouldBeArchived"]; + self.firstItem = [aDecoder decodeObjectForKey:@"firstItem"]; + self.firstItemType = [aDecoder decodeIntegerForKey:@"firstItemType"]; + self.firstAttribute = [aDecoder decodeIntegerForKey:@"firstAttribute"]; + self.relation = [aDecoder decodeIntegerForKey:@"relation"]; + self.secondItem = [aDecoder decodeObjectForKey:@"secondItem"]; + self.secondItemType = [aDecoder decodeIntegerForKey:@"secondItemType"]; + self.secondAttribute = [aDecoder decodeIntegerForKey:@"secondAttribute"]; + self.multiplier = [aDecoder decodeDoubleForKey:@"multiplier"]; + self.constant = [aDecoder decodeDoubleForKey:@"constant"]; + self.priority = [aDecoder decodeDoubleForKey:@"priority"]; + self.identifier = [aDecoder decodeObjectForKey:@"identifier"]; + } + return self; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinCodingValueType.h b/Pods/LookinServer/Src/Main/Shared/LookinCodingValueType.h new file mode 100644 index 0000000..8349d68 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinCodingValueType.h @@ -0,0 +1,30 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinCodingValueType.h +// Lookin +// +// Created by Li Kai on 2019/2/13. +// https://lookin.work +// + +typedef NS_ENUM(NSInteger, LookinCodingValueType) { + LookinCodingValueTypeUnknown, + LookinCodingValueTypeChar, + LookinCodingValueTypeDouble, + LookinCodingValueTypeFloat, + LookinCodingValueTypeLongLong, +// LookinCodingValueTypePoint, +// LookinCodingValueTypeString, +// LookinCodingValueTypeStringArray, +// LookinCodingValueTypeEdgeInsets, +// LookinCodingValueTypeRect, + LookinCodingValueTypeBOOL, +// LookinCodingValueTypeSize, + LookinCodingValueTypeColor, + LookinCodingValueTypeEnum, +// LookinCodingValueTypeRange, + LookinCodingValueTypeImage +}; + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinConnectionAttachment.h b/Pods/LookinServer/Src/Main/Shared/LookinConnectionAttachment.h new file mode 100644 index 0000000..54a4b90 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinConnectionAttachment.h @@ -0,0 +1,24 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinConnectionAttachment.h +// Lookin +// +// Created by Li Kai on 2019/2/15. +// https://lookin.work +// + + + +#import +#import "LookinCodingValueType.h" + +@interface LookinConnectionAttachment : NSObject + +@property(nonatomic, assign) LookinCodingValueType dataType; + +@property(nonatomic, strong) id data; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinConnectionAttachment.m b/Pods/LookinServer/Src/Main/Shared/LookinConnectionAttachment.m new file mode 100644 index 0000000..99eda1e --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinConnectionAttachment.m @@ -0,0 +1,52 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinConnectionAttachment.m +// Lookin +// +// Created by Li Kai on 2019/2/15. +// https://lookin.work +// + + + +#import "LookinConnectionAttachment.h" +#import "LookinDefines.h" +#import "NSObject+Lookin.h" + +static NSString * const Key_Data = @"0"; +static NSString * const Key_DataType = @"1"; + +@interface LookinConnectionAttachment () + +@end + +@implementation LookinConnectionAttachment + +- (instancetype)init { + if (self = [super init]) { + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + + [aCoder encodeObject:[self.data lookin_encodedObjectWithType:self.dataType] forKey:Key_Data]; + [aCoder encodeInteger:self.dataType forKey:Key_DataType]; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if (self = [super init]) { + self.dataType = [aDecoder decodeIntegerForKey:Key_DataType]; + self.data = [[aDecoder decodeObjectForKey:Key_Data] lookin_decodedObjectWithType:self.dataType]; + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinConnectionResponseAttachment.h b/Pods/LookinServer/Src/Main/Shared/LookinConnectionResponseAttachment.h new file mode 100644 index 0000000..46bb0e9 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinConnectionResponseAttachment.h @@ -0,0 +1,36 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinConnectionResponse.h +// Lookin +// +// Created by Li Kai on 2019/1/15. +// https://lookin.work +// + + + +#import +#import "LookinConnectionAttachment.h" + +@interface LookinConnectionResponseAttachment : LookinConnectionAttachment + ++ (instancetype)attachmentWithError:(NSError *)error; + +@property(nonatomic, assign) int lookinServerVersion; + +@property(nonatomic, strong) NSError *error; + +/// 如果为 YES,则表示 app 正处于后台模式,默认为 NO +@property(nonatomic, assign) BOOL appIsInBackground; + +/** + dataTotalCount 为 0 时表示仅有这一个 response,默认为 0 + dataTotalCount 大于 0 时表示可能有多个 response,当所有 response 的 currentDataCount 的总和大于 dataTotalCount 即表示所有 response 已接收完毕 + */ +@property(nonatomic, assign) NSUInteger dataTotalCount; +@property(nonatomic, assign) NSUInteger currentDataCount; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinConnectionResponseAttachment.m b/Pods/LookinServer/Src/Main/Shared/LookinConnectionResponseAttachment.m new file mode 100644 index 0000000..71f62fe --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinConnectionResponseAttachment.m @@ -0,0 +1,62 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinConnectionResponse.m +// Lookin +// +// Created by Li Kai on 2019/1/15. +// https://lookin.work +// + + + +#import "LookinConnectionResponseAttachment.h" +#import "LookinDefines.h" + +@interface LookinConnectionResponseAttachment () + +@end + +@implementation LookinConnectionResponseAttachment + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + [aCoder encodeInt:self.lookinServerVersion forKey:@"lookinServerVersion"]; + [aCoder encodeObject:self.error forKey:@"error"]; + [aCoder encodeObject:@(self.dataTotalCount) forKey:@"dataTotalCount"]; + [aCoder encodeObject:@(self.currentDataCount) forKey:@"currentDataCount"]; + [aCoder encodeBool:self.appIsInBackground forKey:@"appIsInBackground"]; +} + +- (instancetype)init { + if (self = [super init]) { + self.lookinServerVersion = LOOKIN_SERVER_VERSION; + self.dataTotalCount = 0; + } + return self; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if (self = [super initWithCoder:aDecoder]) { + self.lookinServerVersion = [aDecoder decodeIntForKey:@"lookinServerVersion"]; + self.error = [aDecoder decodeObjectForKey:@"error"]; + self.dataTotalCount = [[aDecoder decodeObjectForKey:@"dataTotalCount"] unsignedIntegerValue]; + self.currentDataCount = [[aDecoder decodeObjectForKey:@"currentDataCount"] unsignedIntegerValue]; + self.appIsInBackground = [aDecoder decodeBoolForKey:@"appIsInBackground"]; + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + ++ (instancetype)attachmentWithError:(NSError *)error { + LookinConnectionResponseAttachment *attachment = [LookinConnectionResponseAttachment new]; + attachment.error = error; + return attachment; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinCustomAttrModification.h b/Pods/LookinServer/Src/Main/Shared/LookinCustomAttrModification.h new file mode 100644 index 0000000..1be7926 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinCustomAttrModification.h @@ -0,0 +1,20 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER +// +// LookinCustomAttrModification.h +// LookinShared +// +// Created by likaimacbookhome on 2023/11/4. +// + +#import +#import "LookinAttrType.h" + +@interface LookinCustomAttrModification : NSObject + +@property(nonatomic, assign) LookinAttrType attrType; +@property(nonatomic, copy) NSString *customSetterID; +@property(nonatomic, strong) id value; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinCustomAttrModification.m b/Pods/LookinServer/Src/Main/Shared/LookinCustomAttrModification.m new file mode 100644 index 0000000..6d49016 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinCustomAttrModification.m @@ -0,0 +1,34 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER +// +// LookinCustomAttrModification.m +// LookinShared +// +// Created by likaimacbookhome on 2023/11/4. +// + +#import "LookinCustomAttrModification.h" + +@implementation LookinCustomAttrModification + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeInteger:self.attrType forKey:@"attrType"]; + [aCoder encodeObject:self.value forKey:@"value"]; + [aCoder encodeObject:self.customSetterID forKey:@"customSetterID"]; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if (self = [super init]) { + self.attrType = [aDecoder decodeIntegerForKey:@"attrType"]; + self.value = [aDecoder decodeObjectForKey:@"value"]; + self.customSetterID = [aDecoder decodeObjectForKey:@"customSetterID"]; + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinCustomDisplayItemInfo.h b/Pods/LookinServer/Src/Main/Shared/LookinCustomDisplayItemInfo.h new file mode 100644 index 0000000..a74d6ed --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinCustomDisplayItemInfo.h @@ -0,0 +1,21 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER +// +// LookinCustomDisplayItemInfo.h +// LookinServer +// +// Created by likai.123 on 2023/11/1. +// + +#import + +@interface LookinCustomDisplayItemInfo : NSObject + +/// 该属性可能有值(CGRect)也可能是 nil(nil 时则表示无图像) +@property(nonatomic, strong) NSValue *frameInWindow; +@property(nonatomic, copy) NSString *title; +@property(nonatomic, copy) NSString *subtitle; +@property(nonatomic, copy) NSString *danceuiSource; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinCustomDisplayItemInfo.m b/Pods/LookinServer/Src/Main/Shared/LookinCustomDisplayItemInfo.m new file mode 100644 index 0000000..a59778a --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinCustomDisplayItemInfo.m @@ -0,0 +1,59 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinCustomDisplayItemInfo.m +// LookinServer +// +// Created by likai.123 on 2023/11/1. +// + +#import "LookinCustomDisplayItemInfo.h" +#if TARGET_OS_IPHONE +#import +#endif + +@implementation LookinCustomDisplayItemInfo + +- (id)copyWithZone:(NSZone *)zone { + LookinCustomDisplayItemInfo *newInstance = [[LookinCustomDisplayItemInfo allocWithZone:zone] init]; + + if (self.frameInWindow) { +#if TARGET_OS_IPHONE + CGRect rect = [self.frameInWindow CGRectValue]; + newInstance.frameInWindow = [NSValue valueWithCGRect:rect]; +#elif TARGET_OS_MAC + CGRect rect = [self.frameInWindow rectValue]; + newInstance.frameInWindow = [NSValue valueWithRect:rect]; +#endif + } + newInstance.title = self.title; + newInstance.subtitle = self.subtitle; + newInstance.danceuiSource = self.danceuiSource; + + return newInstance; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:self.frameInWindow forKey:@"frameInWindow"]; + [aCoder encodeObject:self.title forKey:@"title"]; + [aCoder encodeObject:self.subtitle forKey:@"subtitle"]; + [aCoder encodeObject:self.danceuiSource forKey:@"danceuiSource"]; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if (self = [super init]) { + self.frameInWindow = [aDecoder decodeObjectForKey:@"frameInWindow"]; + self.title = [aDecoder decodeObjectForKey:@"title"]; + self.subtitle = [aDecoder decodeObjectForKey:@"subtitle"]; + self.danceuiSource = [aDecoder decodeObjectForKey:@"danceuiSource"]; + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinDashboardBlueprint.h b/Pods/LookinServer/Src/Main/Shared/LookinDashboardBlueprint.h new file mode 100644 index 0000000..361789a --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinDashboardBlueprint.h @@ -0,0 +1,77 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinDashboardBlueprint.h +// Lookin +// +// Created by Li Kai on 2019/6/5. +// https://lookin.work +// + + + +#import +#import "LookinAttrIdentifiers.h" +#import "LookinAttrType.h" + +/** + 该对象定义了: + - 每一个 Attr 的信息 + - 哪些 GroupID, SectionID, AttrID 是合法的 + - 这些 ID 的父子顺序,比如 LookinAttrGroup_Frame 包含哪些 Section + - 这些 ID 展示顺序(比如哪个 Group 在前、哪个 Group 在后) + */ +@interface LookinDashboardBlueprint : NSObject + ++ (NSArray *)groupIDs; + ++ (NSArray *)sectionIDsForGroupID:(LookinAttrGroupIdentifier)groupID; + ++ (NSArray *)attrIDsForSectionID:(LookinAttrSectionIdentifier)sectionID; + +/// 返回包含目标 attr 的 groupID 和 sectionID ++ (void)getHostGroupID:(inout LookinAttrGroupIdentifier *)groupID sectionID:(inout LookinAttrSectionIdentifier *)sectionID fromAttrID:(LookinAttrIdentifier)attrID; + +/// 返回某个 group 的标题 ++ (NSString *)groupTitleWithGroupID:(LookinAttrGroupIdentifier)groupID; + +/// 返回某个 section 的标题,nil 则表示不显示标题 ++ (NSString *)sectionTitleWithSectionID:(LookinAttrSectionIdentifier)secID; + +/// 当某个 LookinAttribute 确定是 NSObject 类型时,该方法返回它具体是什么对象,比如 UIColor 等 ++ (LookinAttrType)objectAttrTypeWithAttrID:(LookinAttrIdentifier)attrID; + +/// 返回某个 LookinAttribute 代表的属性是哪一个类拥有的,比如 LookinAttrSec_UILabel_TextColor 是 UILabel 才有的 ++ (NSString *)classNameWithAttrID:(LookinAttrIdentifier)attrID; + +/// 一个 attr 要么属于 UIView 要么属于 CALayer,如果它属于 UIView 那么该方法返回 YES ++ (BOOL)isUIViewPropertyWithAttrID:(LookinAttrIdentifier)attrID; + +/// 如果某个 attribute 是 enum,则这里会返回相应的 enum 的名称(如 @"NSTextAlignment"),进而可通过这个名称查询可用的枚举值列表 ++ (NSString *)enumListNameWithAttrID:(LookinAttrIdentifier)attrID; + +/// 如果返回 YES,则说明用户在 Lookin 里修改了该 Attribute 的值后,应该重新拉取和更新相关图层的位置、截图等信息 ++ (BOOL)needPatchAfterModificationWithAttrID:(LookinAttrIdentifier)attrID; + +/// 完整的名字 ++ (NSString *)fullTitleWithAttrID:(LookinAttrIdentifier)attrID; + +/// 在某些 textField 和 checkbox 里会显示这里返回的 title ++ (NSString *)briefTitleWithAttrID:(LookinAttrIdentifier)attrID; + +/// 获取 getter 方法 ++ (SEL)getterWithAttrID:(LookinAttrIdentifier)attrID; + +/// 获取 setter 方法 ++ (SEL)setterWithAttrID:(LookinAttrIdentifier)attrID; + +/// 获取 “hideIfNil” 的值。如果为 YES,则当读取 getter 获取的 value 为 nil 时,Lookin 不会传输该 attr +/// 如果为 NO,则即使 value 为 nil 也会传输(比如 label 的 text 属性,即使它是 nil 我们也要显示,所以它的 hideIfNil 应该为 NO) ++ (BOOL)hideIfNilWithAttrID:(LookinAttrIdentifier)attrID; + +/// 该属性需要的最低的 iOS 版本,比如 safeAreaInsets 从 iOS 11.0 开始出现,则该方法返回 11,如果返回 0 则表示不限制 iOS 版本(注意 Lookin 项目仅支持 iOS 8.0+) ++ (NSInteger)minAvailableOSVersionWithAttrID:(LookinAttrIdentifier)attrID; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinDashboardBlueprint.m b/Pods/LookinServer/Src/Main/Shared/LookinDashboardBlueprint.m new file mode 100644 index 0000000..3daf035 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinDashboardBlueprint.m @@ -0,0 +1,1196 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinDashboardBlueprint.m +// Lookin +// +// Created by Li Kai on 2019/6/5. +// https://lookin.work +// + + + +#import "LookinDashboardBlueprint.h" + +@implementation LookinDashboardBlueprint + ++ (NSArray *)groupIDs { + static NSArray *array; + static dispatch_once_t onceToken; + dispatch_once(&onceToken,^{ + array = @[ + LookinAttrGroup_Class, + LookinAttrGroup_Relation, + LookinAttrGroup_Layout, + LookinAttrGroup_AutoLayout, + LookinAttrGroup_ViewLayer, + LookinAttrGroup_UIStackView, + LookinAttrGroup_UIVisualEffectView, + LookinAttrGroup_UIImageView, + LookinAttrGroup_UILabel, + LookinAttrGroup_UIControl, + LookinAttrGroup_UIButton, + LookinAttrGroup_UIScrollView, + LookinAttrGroup_UITableView, + LookinAttrGroup_UITextView, + LookinAttrGroup_UITextField + ]; + }); + return array; +} + ++ (NSArray *)sectionIDsForGroupID:(LookinAttrGroupIdentifier)groupID { + static NSDictionary *> *dict; + static dispatch_once_t onceToken; + dispatch_once(&onceToken,^{ + dict = @{ + LookinAttrGroup_Class: @[LookinAttrSec_Class_Class], + + LookinAttrGroup_Relation: @[LookinAttrSec_Relation_Relation], + + LookinAttrGroup_Layout: @[LookinAttrSec_Layout_Frame, + LookinAttrSec_Layout_Bounds, + LookinAttrSec_Layout_SafeArea, + LookinAttrSec_Layout_Position, + LookinAttrSec_Layout_AnchorPoint], + + LookinAttrGroup_AutoLayout: @[LookinAttrSec_AutoLayout_Constraints, + LookinAttrSec_AutoLayout_IntrinsicSize, + LookinAttrSec_AutoLayout_Hugging, + LookinAttrSec_AutoLayout_Resistance], + + LookinAttrGroup_ViewLayer: @[ + LookinAttrSec_ViewLayer_Visibility, + LookinAttrSec_ViewLayer_InterationAndMasks, + LookinAttrSec_ViewLayer_BgColor, + LookinAttrSec_ViewLayer_Border, + LookinAttrSec_ViewLayer_Corner, + LookinAttrSec_ViewLayer_Shadow, + LookinAttrSec_ViewLayer_ContentMode, + LookinAttrSec_ViewLayer_TintColor, + LookinAttrSec_ViewLayer_Tag + ], + + LookinAttrGroup_UIStackView: @[ + LookinAttrSec_UIStackView_Axis, + LookinAttrSec_UIStackView_Distribution, + LookinAttrSec_UIStackView_Alignment, + LookinAttrSec_UIStackView_Spacing + ], + + LookinAttrGroup_UIVisualEffectView: @[ + LookinAttrSec_UIVisualEffectView_Style, + LookinAttrSec_UIVisualEffectView_QMUIForegroundColor + ], + + LookinAttrGroup_UIImageView: @[LookinAttrSec_UIImageView_Name, + LookinAttrSec_UIImageView_Open], + + LookinAttrGroup_UILabel: @[ + LookinAttrSec_UILabel_Text, + LookinAttrSec_UILabel_Font, + LookinAttrSec_UILabel_NumberOfLines, + LookinAttrSec_UILabel_TextColor, + LookinAttrSec_UILabel_BreakMode, + LookinAttrSec_UILabel_Alignment, + LookinAttrSec_UILabel_CanAdjustFont], + + LookinAttrGroup_UIControl: @[LookinAttrSec_UIControl_EnabledSelected, + LookinAttrSec_UIControl_QMUIOutsideEdge, + LookinAttrSec_UIControl_VerAlignment, + LookinAttrSec_UIControl_HorAlignment], + + LookinAttrGroup_UIButton: @[LookinAttrSec_UIButton_ContentInsets, + LookinAttrSec_UIButton_TitleInsets, + LookinAttrSec_UIButton_ImageInsets], + + LookinAttrGroup_UIScrollView: @[LookinAttrSec_UIScrollView_ContentInset, + LookinAttrSec_UIScrollView_AdjustedInset, + LookinAttrSec_UIScrollView_QMUIInitialInset, + LookinAttrSec_UIScrollView_IndicatorInset, + LookinAttrSec_UIScrollView_Offset, + LookinAttrSec_UIScrollView_ContentSize, + LookinAttrSec_UIScrollView_Behavior, + LookinAttrSec_UIScrollView_ShowsIndicator, + LookinAttrSec_UIScrollView_Bounce, + LookinAttrSec_UIScrollView_ScrollPaging, + LookinAttrSec_UIScrollView_ContentTouches, + LookinAttrSec_UIScrollView_Zoom], + + LookinAttrGroup_UITableView: @[LookinAttrSec_UITableView_Style, + LookinAttrSec_UITableView_SectionsNumber, + LookinAttrSec_UITableView_RowsNumber, + LookinAttrSec_UITableView_SeparatorStyle, + LookinAttrSec_UITableView_SeparatorColor, + LookinAttrSec_UITableView_SeparatorInset], + + LookinAttrGroup_UITextView: @[LookinAttrSec_UITextView_Basic, + LookinAttrSec_UITextView_Text, + LookinAttrSec_UITextView_Font, + LookinAttrSec_UITextView_TextColor, + LookinAttrSec_UITextView_Alignment, + LookinAttrSec_UITextView_ContainerInset], + + LookinAttrGroup_UITextField: @[LookinAttrSec_UITextField_Text, + LookinAttrSec_UITextField_Placeholder, + LookinAttrSec_UITextField_Font, + LookinAttrSec_UITextField_TextColor, + LookinAttrSec_UITextField_Alignment, + LookinAttrSec_UITextField_Clears, + LookinAttrSec_UITextField_CanAdjustFont, + LookinAttrSec_UITextField_ClearButtonMode], + + }; + }); + return dict[groupID]; +} + ++ (NSArray *)attrIDsForSectionID:(LookinAttrSectionIdentifier)sectionID { + static NSDictionary *> *dict; + static dispatch_once_t onceToken; + dispatch_once(&onceToken,^{ + dict = @{ + LookinAttrSec_Class_Class: @[LookinAttr_Class_Class_Class], + + LookinAttrSec_Relation_Relation: @[LookinAttr_Relation_Relation_Relation], + + LookinAttrSec_Layout_Frame: @[LookinAttr_Layout_Frame_Frame], + LookinAttrSec_Layout_Bounds: @[LookinAttr_Layout_Bounds_Bounds], + LookinAttrSec_Layout_SafeArea: @[LookinAttr_Layout_SafeArea_SafeArea], + LookinAttrSec_Layout_Position: @[LookinAttr_Layout_Position_Position], + LookinAttrSec_Layout_AnchorPoint: @[LookinAttr_Layout_AnchorPoint_AnchorPoint], + + LookinAttrSec_AutoLayout_Hugging: @[LookinAttr_AutoLayout_Hugging_Hor, + LookinAttr_AutoLayout_Hugging_Ver], + LookinAttrSec_AutoLayout_Resistance: @[LookinAttr_AutoLayout_Resistance_Hor, + LookinAttr_AutoLayout_Resistance_Ver], + LookinAttrSec_AutoLayout_Constraints: @[LookinAttr_AutoLayout_Constraints_Constraints], + LookinAttrSec_AutoLayout_IntrinsicSize: @[LookinAttr_AutoLayout_IntrinsicSize_Size], + + LookinAttrSec_ViewLayer_Visibility: @[LookinAttr_ViewLayer_Visibility_Hidden, + LookinAttr_ViewLayer_Visibility_Opacity], + + LookinAttrSec_ViewLayer_InterationAndMasks: @[LookinAttr_ViewLayer_InterationAndMasks_Interaction, + LookinAttr_ViewLayer_InterationAndMasks_MasksToBounds], + + LookinAttrSec_ViewLayer_Corner: @[LookinAttr_ViewLayer_Corner_Radius], + + LookinAttrSec_ViewLayer_BgColor: @[LookinAttr_ViewLayer_BgColor_BgColor], + + LookinAttrSec_ViewLayer_Border: @[LookinAttr_ViewLayer_Border_Color, + LookinAttr_ViewLayer_Border_Width], + + LookinAttrSec_ViewLayer_Shadow: @[LookinAttr_ViewLayer_Shadow_Color, + LookinAttr_ViewLayer_Shadow_Opacity, + LookinAttr_ViewLayer_Shadow_Radius, + LookinAttr_ViewLayer_Shadow_OffsetW, + LookinAttr_ViewLayer_Shadow_OffsetH], + + LookinAttrSec_ViewLayer_ContentMode: @[LookinAttr_ViewLayer_ContentMode_Mode], + + LookinAttrSec_ViewLayer_TintColor: @[LookinAttr_ViewLayer_TintColor_Color, + LookinAttr_ViewLayer_TintColor_Mode], + + LookinAttrSec_ViewLayer_Tag: @[LookinAttr_ViewLayer_Tag_Tag], + + LookinAttrSec_UIStackView_Axis: @[LookinAttr_UIStackView_Axis_Axis], + + LookinAttrSec_UIStackView_Distribution: @[LookinAttr_UIStackView_Distribution_Distribution], + + LookinAttrSec_UIStackView_Alignment: @[LookinAttr_UIStackView_Alignment_Alignment], + + LookinAttrSec_UIStackView_Spacing: @[LookinAttr_UIStackView_Spacing_Spacing], + + LookinAttrSec_UIVisualEffectView_Style: @[LookinAttr_UIVisualEffectView_Style_Style], + + LookinAttrSec_UIVisualEffectView_QMUIForegroundColor: @[LookinAttr_UIVisualEffectView_QMUIForegroundColor_Color], + + LookinAttrSec_UIImageView_Name: @[LookinAttr_UIImageView_Name_Name], + + LookinAttrSec_UIImageView_Open: @[LookinAttr_UIImageView_Open_Open], + + LookinAttrSec_UILabel_Font: @[LookinAttr_UILabel_Font_Name, + LookinAttr_UILabel_Font_Size], + + LookinAttrSec_UILabel_NumberOfLines: @[LookinAttr_UILabel_NumberOfLines_NumberOfLines], + + LookinAttrSec_UILabel_Text: @[LookinAttr_UILabel_Text_Text], + + LookinAttrSec_UILabel_TextColor: @[LookinAttr_UILabel_TextColor_Color], + + LookinAttrSec_UILabel_BreakMode: @[LookinAttr_UILabel_BreakMode_Mode], + + LookinAttrSec_UILabel_Alignment: @[LookinAttr_UILabel_Alignment_Alignment], + + LookinAttrSec_UILabel_CanAdjustFont: @[LookinAttr_UILabel_CanAdjustFont_CanAdjustFont], + + LookinAttrSec_UIControl_EnabledSelected: @[LookinAttr_UIControl_EnabledSelected_Enabled, + LookinAttr_UIControl_EnabledSelected_Selected], + + LookinAttrSec_UIControl_QMUIOutsideEdge: @[LookinAttr_UIControl_QMUIOutsideEdge_Edge], + + LookinAttrSec_UIControl_VerAlignment: @[LookinAttr_UIControl_VerAlignment_Alignment], + + LookinAttrSec_UIControl_HorAlignment: @[LookinAttr_UIControl_HorAlignment_Alignment], + + LookinAttrSec_UIButton_ContentInsets: @[LookinAttr_UIButton_ContentInsets_Insets], + + LookinAttrSec_UIButton_TitleInsets: @[LookinAttr_UIButton_TitleInsets_Insets], + + LookinAttrSec_UIButton_ImageInsets: @[LookinAttr_UIButton_ImageInsets_Insets], + + LookinAttrSec_UIScrollView_ContentInset: @[LookinAttr_UIScrollView_ContentInset_Inset], + + LookinAttrSec_UIScrollView_AdjustedInset: @[LookinAttr_UIScrollView_AdjustedInset_Inset], + + LookinAttrSec_UIScrollView_QMUIInitialInset: @[LookinAttr_UIScrollView_QMUIInitialInset_Inset], + + LookinAttrSec_UIScrollView_IndicatorInset: @[LookinAttr_UIScrollView_IndicatorInset_Inset], + + LookinAttrSec_UIScrollView_Offset: @[LookinAttr_UIScrollView_Offset_Offset], + + LookinAttrSec_UIScrollView_ContentSize: @[LookinAttr_UIScrollView_ContentSize_Size], + + LookinAttrSec_UIScrollView_Behavior: @[LookinAttr_UIScrollView_Behavior_Behavior], + + LookinAttrSec_UIScrollView_ShowsIndicator: @[LookinAttr_UIScrollView_ShowsIndicator_Hor, + LookinAttr_UIScrollView_ShowsIndicator_Ver], + + LookinAttrSec_UIScrollView_Bounce: @[LookinAttr_UIScrollView_Bounce_Hor, + LookinAttr_UIScrollView_Bounce_Ver], + + LookinAttrSec_UIScrollView_ScrollPaging: @[LookinAttr_UIScrollView_ScrollPaging_ScrollEnabled, + LookinAttr_UIScrollView_ScrollPaging_PagingEnabled], + + LookinAttrSec_UIScrollView_ContentTouches: @[LookinAttr_UIScrollView_ContentTouches_Delay, + LookinAttr_UIScrollView_ContentTouches_CanCancel], + + LookinAttrSec_UIScrollView_Zoom: @[LookinAttr_UIScrollView_Zoom_Bounce, + LookinAttr_UIScrollView_Zoom_Scale, + LookinAttr_UIScrollView_Zoom_MinScale, + LookinAttr_UIScrollView_Zoom_MaxScale], + + LookinAttrSec_UITableView_Style: @[LookinAttr_UITableView_Style_Style], + + LookinAttrSec_UITableView_SectionsNumber: @[LookinAttr_UITableView_SectionsNumber_Number], + + LookinAttrSec_UITableView_RowsNumber: @[LookinAttr_UITableView_RowsNumber_Number], + + LookinAttrSec_UITableView_SeparatorInset: @[LookinAttr_UITableView_SeparatorInset_Inset], + + LookinAttrSec_UITableView_SeparatorColor: @[LookinAttr_UITableView_SeparatorColor_Color], + + LookinAttrSec_UITableView_SeparatorStyle: @[LookinAttr_UITableView_SeparatorStyle_Style], + + LookinAttrSec_UITextView_Basic: @[LookinAttr_UITextView_Basic_Editable, + LookinAttr_UITextView_Basic_Selectable], + + LookinAttrSec_UITextView_Text: @[LookinAttr_UITextView_Text_Text], + + LookinAttrSec_UITextView_Font: @[LookinAttr_UITextView_Font_Name, + LookinAttr_UITextView_Font_Size], + + LookinAttrSec_UITextView_TextColor: @[LookinAttr_UITextView_TextColor_Color], + + LookinAttrSec_UITextView_Alignment: @[LookinAttr_UITextView_Alignment_Alignment], + + LookinAttrSec_UITextView_ContainerInset: @[LookinAttr_UITextView_ContainerInset_Inset], + + LookinAttrSec_UITextField_Text: @[LookinAttr_UITextField_Text_Text], + + LookinAttrSec_UITextField_Placeholder: @[LookinAttr_UITextField_Placeholder_Placeholder], + + LookinAttrSec_UITextField_Font: @[LookinAttr_UITextField_Font_Name, + LookinAttr_UITextField_Font_Size], + + LookinAttrSec_UITextField_TextColor: @[LookinAttr_UITextField_TextColor_Color], + + LookinAttrSec_UITextField_Alignment: @[LookinAttr_UITextField_Alignment_Alignment], + + LookinAttrSec_UITextField_Clears: @[LookinAttr_UITextField_Clears_ClearsOnBeginEditing, + LookinAttr_UITextField_Clears_ClearsOnInsertion], + + LookinAttrSec_UITextField_CanAdjustFont: @[LookinAttr_UITextField_CanAdjustFont_CanAdjustFont, + LookinAttr_UITextField_CanAdjustFont_MinSize], + + LookinAttrSec_UITextField_ClearButtonMode: @[LookinAttr_UITextField_ClearButtonMode_Mode] + }; + }); + return dict[sectionID]; +} + ++ (void)getHostGroupID:(inout LookinAttrGroupIdentifier *)groupID_inout sectionID:(inout LookinAttrSectionIdentifier *)sectionID_inout fromAttrID:(LookinAttrIdentifier)targetAttrID { + __block LookinAttrGroupIdentifier targetGroupID = nil; + __block LookinAttrSectionIdentifier targetSecID = nil; + [[self groupIDs] enumerateObjectsUsingBlock:^(LookinAttrGroupIdentifier _Nonnull groupID, NSUInteger idx, BOOL * _Nonnull stop0) { + [[self sectionIDsForGroupID:groupID] enumerateObjectsUsingBlock:^(LookinAttrSectionIdentifier _Nonnull secID, NSUInteger idx, BOOL * _Nonnull stop1) { + [[self attrIDsForSectionID:secID] enumerateObjectsUsingBlock:^(LookinAttrIdentifier _Nonnull attrID, NSUInteger idx, BOOL * _Nonnull stop2) { + if ([attrID isEqualToString:targetAttrID]) { + targetGroupID = groupID; + targetSecID = secID; + *stop0 = YES; + *stop1 = YES; + *stop2 = YES; + } + }]; + }]; + }]; + + if (groupID_inout && targetGroupID) { + *groupID_inout = targetGroupID; + } + if (sectionID_inout && targetSecID) { + *sectionID_inout = targetSecID; + } +} + ++ (NSString *)groupTitleWithGroupID:(LookinAttrGroupIdentifier)groupID { + static dispatch_once_t onceToken; + static NSDictionary *rawInfo = nil; + dispatch_once(&onceToken,^{ + rawInfo = @{ + LookinAttrGroup_Class: @"Class", + LookinAttrGroup_Relation: @"Relation", + LookinAttrGroup_Layout: @"Layout", + LookinAttrGroup_AutoLayout: @"AutoLayout", + LookinAttrGroup_ViewLayer: @"CALayer / UIView", + LookinAttrGroup_UIImageView: @"UIImageView", + LookinAttrGroup_UILabel: @"UILabel", + LookinAttrGroup_UIControl: @"UIControl", + LookinAttrGroup_UIButton: @"UIButton", + LookinAttrGroup_UIScrollView: @"UIScrollView", + LookinAttrGroup_UITableView: @"UITableView", + LookinAttrGroup_UITextView: @"UITextView", + LookinAttrGroup_UITextField: @"UITextField", + LookinAttrGroup_UIVisualEffectView: @"UIVisualEffectView", + LookinAttrGroup_UIStackView: @"UIStackView" + }; + }); + NSString *title = rawInfo[groupID]; + NSAssert(title.length, @""); + return title; +} + ++ (NSString *)sectionTitleWithSectionID:(LookinAttrSectionIdentifier)secID { + static dispatch_once_t onceToken; + static NSDictionary *rawInfo = nil; + dispatch_once(&onceToken,^{ + rawInfo = @{ + LookinAttrSec_Layout_Frame: @"Frame", + LookinAttrSec_Layout_Bounds: @"Bounds", + LookinAttrSec_Layout_SafeArea: @"SafeArea", + LookinAttrSec_Layout_Position: @"Position", + LookinAttrSec_Layout_AnchorPoint: @"AnchorPoint", + LookinAttrSec_AutoLayout_Hugging: @"HuggingPriority", + LookinAttrSec_AutoLayout_Resistance: @"ResistancePriority", + LookinAttrSec_AutoLayout_IntrinsicSize: @"IntrinsicSize", + LookinAttrSec_ViewLayer_Corner: @"CornerRadius", + LookinAttrSec_ViewLayer_BgColor: @"BackgroundColor", + LookinAttrSec_ViewLayer_Border: @"Border", + LookinAttrSec_ViewLayer_Shadow: @"Shadow", + LookinAttrSec_ViewLayer_ContentMode: @"ContentMode", + LookinAttrSec_ViewLayer_TintColor: @"TintColor", + LookinAttrSec_ViewLayer_Tag: @"Tag", + LookinAttrSec_UIStackView_Axis: @"Axis", + LookinAttrSec_UIStackView_Distribution: @"Distribution", + LookinAttrSec_UIStackView_Alignment: @"Alignment", + LookinAttrSec_UIVisualEffectView_Style: @"Style", + LookinAttrSec_UIVisualEffectView_QMUIForegroundColor: @"ForegroundColor", + LookinAttrSec_UIImageView_Name: @"ImageName", + LookinAttrSec_UILabel_TextColor: @"TextColor", + LookinAttrSec_UITextView_TextColor: @"TextColor", + LookinAttrSec_UITextField_TextColor: @"TextColor", + LookinAttrSec_UILabel_BreakMode: @"LineBreakMode", + LookinAttrSec_UILabel_NumberOfLines: @"NumberOfLines", + LookinAttrSec_UILabel_Text: @"Text", + LookinAttrSec_UITextView_Text: @"Text", + LookinAttrSec_UITextField_Text: @"Text", + LookinAttrSec_UITextField_Placeholder: @"Placeholder", + LookinAttrSec_UILabel_Alignment: @"TextAlignment", + LookinAttrSec_UITextView_Alignment: @"TextAlignment", + LookinAttrSec_UITextField_Alignment: @"TextAlignment", + LookinAttrSec_UIControl_HorAlignment: @"HorizontalAlignment", + LookinAttrSec_UIControl_VerAlignment: @"VerticalAlignment", + LookinAttrSec_UIControl_QMUIOutsideEdge: @"QMUI_outsideEdge", + LookinAttrSec_UIButton_ContentInsets: @"ContentInsets", + LookinAttrSec_UIButton_TitleInsets: @"TitleInsets", + LookinAttrSec_UIButton_ImageInsets: @"ImageInsets", + LookinAttrSec_UIScrollView_QMUIInitialInset: @"QMUI_initialContentInset", + LookinAttrSec_UIScrollView_ContentInset: @"ContentInset", + LookinAttrSec_UIScrollView_AdjustedInset: @"AdjustedContentInset", + LookinAttrSec_UIScrollView_IndicatorInset: @"ScrollIndicatorInsets", + LookinAttrSec_UIScrollView_Offset: @"ContentOffset", + LookinAttrSec_UIScrollView_ContentSize: @"ContentSize", + LookinAttrSec_UIScrollView_Behavior: @"InsetAdjustmentBehavior", + LookinAttrSec_UIScrollView_ShowsIndicator: @"ShowsScrollIndicator", + LookinAttrSec_UIScrollView_Bounce: @"AlwaysBounce", + LookinAttrSec_UIScrollView_Zoom: @"Zoom", + LookinAttrSec_UITableView_Style: @"Style", + LookinAttrSec_UITableView_SectionsNumber: @"NumberOfSections", + LookinAttrSec_UITableView_RowsNumber: @"NumberOfRows", + LookinAttrSec_UITableView_SeparatorColor: @"SeparatorColor", + LookinAttrSec_UITableView_SeparatorInset: @"SeparatorInset", + LookinAttrSec_UITableView_SeparatorStyle: @"SeparatorStyle", + LookinAttrSec_UILabel_Font: @"Font", + LookinAttrSec_UITextField_Font: @"Font", + LookinAttrSec_UITextView_Font: @"Font", + LookinAttrSec_UITextView_ContainerInset: @"ContainerInset", + LookinAttrSec_UITextField_ClearButtonMode: @"ClearButtonMode", + }; + }); + return rawInfo[secID]; +} + +/** + className: 必填项,标识该属性是哪一个类拥有的 + + fullTitle: 完整的名字,将作为搜索的 keywords,也会展示在搜索结果中,如果为 nil 则不会被搜索到 + + briefTitle:简略的名字,仅 checkbox 和那种自带标题的 input 才需要这个属性,如果需要该属性但该属性又为空,则会读取 fullTitle + + setterString:用户试图修改属性值时会用到,若该字段为空字符串(即 @“”)则该属性不可修改,若该字段为 nil 则会在 fullTitle 的基础上自动生成(自动改首字母大小写、加前缀后缀,比如 alpha 会被转换为 setAlpha:) + + getterString:必填项,业务中读取属性值时会用到。如果该字段为 nil ,则会在 fullTitle 的基础上自动生成(自动把 fullTitle 的第一个字母改成小写,比如 Alpha 会被转换为 alpha)。如果该字段为空字符串(比如 image_open_open)则属性值会被固定为 nil,attrType 会被指为 LookinAttrTypeCustomObj + + typeIfObj:当某个 LookinAttribute 确定是 NSObject 类型时,该方法返回它具体是什么对象,比如 UIColor、NSString + + enumList:如果某个 attribute 是 enum,则这里标识了相应的 enum 的名称(如 "NSTextAlignment"),业务可通过这个名称进而查询可用的枚举值列表 + + patch:如果为 YES,则用户修改了该 Attribute 的值后,Lookin 会重新拉取和更新相关图层的位置、截图等信息,如果为 nil 则默认是 NO + + hideIfNil:如果为 YES,则当获取的 value 为 nil 时,Lookin 不会传输该 attr。如果为 NO,则即使 value 为 nil 也会传输(比如 label 的 text 属性,即使它是 nil 我们也要显示,所以它的 hideIfNil 应该为 NO)。如果该字段为 nil 则默认是 NO + + osVersion: 该属性需要的最低的 iOS 版本,比如 safeAreaInsets 从 iOS 11.0 开始出现,则该属性应该为 @11,如果为 nil 则表示不限制 iOS 版本 + + */ ++ (NSDictionary *)_infoForAttrID:(LookinAttrIdentifier)attrID { + static NSDictionary *> *dict; + static dispatch_once_t onceToken; + dispatch_once(&onceToken,^{ + dict = @{ + LookinAttr_Class_Class_Class: @{ + @"className": @"CALayer", + @"getterString": @"lks_relatedClassChainList", + @"setterString": @"", + @"typeIfObj": @(LookinAttrTypeCustomObj) + }, + + LookinAttr_Relation_Relation_Relation: @{ + @"className": @"CALayer", + @"getterString": @"lks_selfRelation", + @"setterString": @"", + @"typeIfObj": @(LookinAttrTypeCustomObj), + @"hideIfNil": @(YES) + }, + + LookinAttr_Layout_Frame_Frame: @{ + @"className": @"CALayer", + @"fullTitle": @"Frame", + @"patch": @(YES) + }, + LookinAttr_Layout_Bounds_Bounds: @{ + @"className": @"CALayer", + @"fullTitle": @"Bounds", + @"patch": @(YES) + }, + LookinAttr_Layout_SafeArea_SafeArea: @{ + @"className": @"UIView", + @"fullTitle": @"SafeAreaInsets", + @"setterString": @"", + @"osVersion": @(11) + }, + LookinAttr_Layout_Position_Position: @{ + @"className": @"CALayer", + @"fullTitle": @"Position", + @"patch": @(YES) + }, + LookinAttr_Layout_AnchorPoint_AnchorPoint: @{ + @"className": @"CALayer", + @"fullTitle": @"AnchorPoint", + @"patch": @(YES) + }, + + LookinAttr_AutoLayout_Hugging_Hor: @{ + @"className": @"UIView", + @"fullTitle": @"ContentHuggingPriority(Horizontal)", + @"getterString": @"lks_horizontalContentHuggingPriority", + @"setterString": @"setLks_horizontalContentHuggingPriority:", + @"briefTitle": @"H", + @"patch": @(YES) + }, + LookinAttr_AutoLayout_Hugging_Ver: @{ + @"className": @"UIView", + @"fullTitle": @"ContentHuggingPriority(Vertical)", + @"getterString": @"lks_verticalContentHuggingPriority", + @"setterString": @"setLks_verticalContentHuggingPriority:", + @"briefTitle": @"V", + @"patch": @(YES) + }, + LookinAttr_AutoLayout_Resistance_Hor: @{ + @"className": @"UIView", + @"fullTitle": @"ContentCompressionResistancePriority(Horizontal)", + @"getterString": @"lks_horizontalContentCompressionResistancePriority", + @"setterString": @"setLks_horizontalContentCompressionResistancePriority:", + @"briefTitle": @"H", + @"patch": @(YES) + }, + LookinAttr_AutoLayout_Resistance_Ver: @{ + @"className": @"UIView", + @"fullTitle": @"ContentCompressionResistancePriority(Vertical)", + @"getterString": @"lks_verticalContentCompressionResistancePriority", + @"setterString": @"setLks_verticalContentCompressionResistancePriority:", + @"briefTitle": @"V", + @"patch": @(YES) + }, + LookinAttr_AutoLayout_Constraints_Constraints: @{ + @"className": @"UIView", + @"getterString": @"lks_constraints", + @"setterString": @"", + @"typeIfObj": @(LookinAttrTypeCustomObj), + @"hideIfNil": @(YES) + }, + LookinAttr_AutoLayout_IntrinsicSize_Size: @{ + @"className": @"UIView", + @"fullTitle": @"IntrinsicContentSize", + @"setterString": @"" + }, + + LookinAttr_ViewLayer_Visibility_Hidden: @{ + @"className": @"CALayer", + @"fullTitle": @"Hidden", + @"getterString": @"isHidden", + @"patch": @(YES) + }, + LookinAttr_ViewLayer_Visibility_Opacity: @{ + @"className": @"CALayer", + @"fullTitle": @"Opacity / Alpha", + @"setterString": @"setOpacity:", + @"getterString": @"opacity", + @"patch": @(YES) + }, + LookinAttr_ViewLayer_InterationAndMasks_Interaction: @{ + @"className": @"UIView", + @"fullTitle": @"UserInteractionEnabled", + @"getterString": @"isUserInteractionEnabled", + @"patch": @(NO) + }, + LookinAttr_ViewLayer_InterationAndMasks_MasksToBounds: @{ + @"className": @"CALayer", + @"fullTitle": @"MasksToBounds / ClipsToBounds", + @"briefTitle": @"MasksToBounds", + @"setterString": @"setMasksToBounds:", + @"getterString": @"masksToBounds", + @"patch": @(YES) + }, + LookinAttr_ViewLayer_Corner_Radius: @{ + @"className": @"CALayer", + @"fullTitle": @"CornerRadius", + @"briefTitle": @"", + @"patch": @(YES) + }, + LookinAttr_ViewLayer_BgColor_BgColor: @{ + @"className": @"CALayer", + @"fullTitle": @"BackgroundColor", + @"setterString": @"setLks_backgroundColor:", + @"getterString": @"lks_backgroundColor", + @"typeIfObj": @(LookinAttrTypeUIColor), + @"patch": @(YES) + }, + LookinAttr_ViewLayer_Border_Color: @{ + @"className": @"CALayer", + @"fullTitle": @"BorderColor", + @"setterString": @"setLks_borderColor:", + @"getterString": @"lks_borderColor", + @"typeIfObj": @(LookinAttrTypeUIColor), + @"patch": @(YES) + }, + LookinAttr_ViewLayer_Border_Width: @{ + @"className": @"CALayer", + @"fullTitle": @"BorderWidth", + @"patch": @(YES) + }, + LookinAttr_ViewLayer_Shadow_Color: @{ + @"className": @"CALayer", + @"fullTitle": @"ShadowColor", + @"setterString": @"setLks_shadowColor:", + @"getterString": @"lks_shadowColor", + @"typeIfObj": @(LookinAttrTypeUIColor), + @"patch": @(YES) + }, + LookinAttr_ViewLayer_Shadow_Opacity: @{ + @"className": @"CALayer", + @"fullTitle": @"ShadowOpacity", + @"briefTitle": @"Opacity", + @"patch": @(YES) + }, + LookinAttr_ViewLayer_Shadow_Radius: @{ + @"className": @"CALayer", + @"fullTitle": @"ShadowRadius", + @"briefTitle": @"Radius", + @"patch": @(YES) + }, + LookinAttr_ViewLayer_Shadow_OffsetW: @{ + @"className": @"CALayer", + @"fullTitle": @"ShadowOffsetWidth", + @"briefTitle": @"OffsetW", + @"setterString": @"setLks_shadowOffsetWidth:", + @"getterString": @"lks_shadowOffsetWidth", + @"patch": @(YES) + }, + LookinAttr_ViewLayer_Shadow_OffsetH: @{ + @"className": @"CALayer", + @"fullTitle": @"ShadowOffsetHeight", + @"briefTitle": @"OffsetH", + @"setterString": @"setLks_shadowOffsetHeight:", + @"getterString": @"lks_shadowOffsetHeight", + @"patch": @(YES) + }, + LookinAttr_ViewLayer_ContentMode_Mode: @{ + @"className": @"UIView", + @"fullTitle": @"ContentMode", + @"enumList": @"UIViewContentMode", + @"patch": @(YES) + }, + LookinAttr_ViewLayer_TintColor_Color: @{ + @"className": @"UIView", + @"fullTitle": @"TintColor", + @"typeIfObj": @(LookinAttrTypeUIColor), + @"patch": @(YES) + }, + LookinAttr_ViewLayer_TintColor_Mode: @{ + @"className": @"UIView", + @"fullTitle": @"TintAdjustmentMode", + @"enumList": @"UIViewTintAdjustmentMode", + @"patch": @(YES) + }, + LookinAttr_ViewLayer_Tag_Tag: @{ + @"className": @"UIView", + @"fullTitle": @"Tag", + @"briefTitle": @"", + @"patch": @(NO) + }, + + LookinAttr_UIStackView_Axis_Axis: @{ + @"className": @"UIStackView", + @"fullTitle": @"Axis", + @"enumList": @"UILayoutConstraintAxis", + @"patch": @(YES) + }, + + LookinAttr_UIStackView_Distribution_Distribution: @{ + @"className": @"UIStackView", + @"fullTitle": @"Distribution", + @"enumList": @"UIStackViewDistribution", + @"patch": @(YES) + }, + + LookinAttr_UIStackView_Alignment_Alignment: @{ + @"className": @"UIStackView", + @"fullTitle": @"Alignment", + @"enumList": @"UIStackViewAlignment", + @"patch": @(YES) + }, + + LookinAttr_UIStackView_Spacing_Spacing: @{ + @"className": @"UIStackView", + @"fullTitle": @"Spacing", + @"patch": @(YES) + }, + + LookinAttr_UIVisualEffectView_Style_Style: @{ + @"className": @"UIVisualEffectView", + @"setterString": @"setLks_blurEffectStyleNumber:", + @"getterString": @"lks_blurEffectStyleNumber", + @"enumList": @"UIBlurEffectStyle", + @"typeIfObj": @(LookinAttrTypeCustomObj), + @"patch": @(YES), + @"hideIfNil": @(YES) + }, + + LookinAttr_UIVisualEffectView_QMUIForegroundColor_Color: @{ + @"className": @"QMUIVisualEffectView", + @"fullTitle": @"ForegroundColor", + @"typeIfObj": @(LookinAttrTypeUIColor), + @"patch": @(YES), + }, + + LookinAttr_UIImageView_Name_Name: @{ + @"className": @"UIImageView", + @"fullTitle": @"ImageName", + @"setterString": @"", + @"getterString": @"lks_imageSourceName", + @"typeIfObj": @(LookinAttrTypeNSString), + @"hideIfNil": @(YES) + }, + LookinAttr_UIImageView_Open_Open: @{ + @"className": @"UIImageView", + @"setterString": @"", + @"getterString": @"lks_imageViewOidIfHasImage", + @"typeIfObj": @(LookinAttrTypeCustomObj), + @"hideIfNil": @(YES) + }, + + LookinAttr_UILabel_Text_Text: @{ + @"className": @"UILabel", + @"fullTitle": @"Text", + @"typeIfObj": @(LookinAttrTypeNSString), + @"patch": @(YES) + }, + LookinAttr_UILabel_NumberOfLines_NumberOfLines: @{ + @"className": @"UILabel", + @"fullTitle": @"NumberOfLines", + @"briefTitle": @"", + @"patch": @(YES) + }, + LookinAttr_UILabel_Font_Size: @{ + @"className": @"UILabel", + @"fullTitle": @"FontSize", + @"briefTitle": @"FontSize", + @"setterString": @"setLks_fontSize:", + @"getterString": @"lks_fontSize", + @"patch": @(YES) + }, + LookinAttr_UILabel_Font_Name: @{ + @"className": @"UILabel", + @"fullTitle": @"FontName", + @"setterString": @"", + @"getterString": @"lks_fontName", + @"typeIfObj": @(LookinAttrTypeNSString), + @"patch": @(NO) + }, + LookinAttr_UILabel_TextColor_Color: @{ + @"className": @"UILabel", + @"fullTitle": @"TextColor", + @"typeIfObj": @(LookinAttrTypeUIColor), + @"patch": @(YES) + }, + LookinAttr_UILabel_Alignment_Alignment: @{ + @"className": @"UILabel", + @"fullTitle": @"TextAlignment", + @"enumList": @"NSTextAlignment", + @"patch": @(YES) + }, + LookinAttr_UILabel_BreakMode_Mode: @{ + @"className": @"UILabel", + @"fullTitle": @"LineBreakMode", + @"enumList": @"NSLineBreakMode", + @"patch": @(YES) + }, + LookinAttr_UILabel_CanAdjustFont_CanAdjustFont: @{ + @"className": @"UILabel", + @"fullTitle": @"AdjustsFontSizeToFitWidth", + @"patch": @(YES) + }, + + LookinAttr_UIControl_EnabledSelected_Enabled: @{ + @"className": @"UIControl", + @"fullTitle": @"Enabled", + @"getterString": @"isEnabled", + @"patch": @(NO) + }, + LookinAttr_UIControl_EnabledSelected_Selected: @{ + @"className": @"UIControl", + @"fullTitle": @"Selected", + @"getterString": @"isSelected", + @"patch": @(YES) + }, + LookinAttr_UIControl_VerAlignment_Alignment: @{ + @"className": @"UIControl", + @"fullTitle": @"ContentVerticalAlignment", + @"enumList": @"UIControlContentVerticalAlignment", + @"patch": @(YES) + }, + LookinAttr_UIControl_HorAlignment_Alignment: @{ + @"className": @"UIControl", + @"fullTitle": @"ContentHorizontalAlignment", + @"enumList": @"UIControlContentHorizontalAlignment", + @"patch": @(YES) + }, + LookinAttr_UIControl_QMUIOutsideEdge_Edge: @{ + @"className": @"UIControl", + @"fullTitle": @"qmui_outsideEdge" + }, + + LookinAttr_UIButton_ContentInsets_Insets: @{ + @"className": @"UIButton", + @"fullTitle": @"ContentEdgeInsets", + @"patch": @(YES) + }, + LookinAttr_UIButton_TitleInsets_Insets: @{ + @"className": @"UIButton", + @"fullTitle": @"TitleEdgeInsets", + @"patch": @(YES) + }, + LookinAttr_UIButton_ImageInsets_Insets: @{ + @"className": @"UIButton", + @"fullTitle": @"ImageEdgeInsets", + @"patch": @(YES) + }, + + LookinAttr_UIScrollView_Offset_Offset: @{ + @"className": @"UIScrollView", + @"fullTitle": @"ContentOffset", + @"patch": @(YES) + }, + LookinAttr_UIScrollView_ContentSize_Size: @{ + @"className": @"UIScrollView", + @"fullTitle": @"ContentSize", + @"patch": @(YES) + }, + LookinAttr_UIScrollView_ContentInset_Inset: @{ + @"className": @"UIScrollView", + @"fullTitle": @"ContentInset", + @"patch": @(YES) + }, + LookinAttr_UIScrollView_QMUIInitialInset_Inset: @{ + @"className": @"UIScrollView", + @"fullTitle": @"qmui_initialContentInset", + @"patch": @(YES) + }, + LookinAttr_UIScrollView_AdjustedInset_Inset: @{ + @"className": @"UIScrollView", + @"fullTitle": @"AdjustedContentInset", + @"setterString": @"", + @"osVersion": @(11) + }, + LookinAttr_UIScrollView_Behavior_Behavior: @{ + @"className": @"UIScrollView", + @"fullTitle": @"ContentInsetAdjustmentBehavior", + @"enumList": @"UIScrollViewContentInsetAdjustmentBehavior", + @"patch": @(YES), + @"osVersion": @(11) + }, + LookinAttr_UIScrollView_IndicatorInset_Inset: @{ + @"className": @"UIScrollView", + @"fullTitle": @"ScrollIndicatorInsets", + @"patch": @(NO) + }, + LookinAttr_UIScrollView_ScrollPaging_ScrollEnabled: @{ + @"className": @"UIScrollView", + @"fullTitle": @"ScrollEnabled", + @"getterString": @"isScrollEnabled", + @"patch": @(NO) + }, + LookinAttr_UIScrollView_ScrollPaging_PagingEnabled: @{ + @"className": @"UIScrollView", + @"fullTitle": @"PagingEnabled", + @"getterString": @"isPagingEnabled", + @"patch": @(NO) + }, + LookinAttr_UIScrollView_Bounce_Ver: @{ + @"className": @"UIScrollView", + @"fullTitle": @"AlwaysBounceVertical", + @"briefTitle": @"Vertical", + @"patch": @(NO) + }, + LookinAttr_UIScrollView_Bounce_Hor: @{ + @"className": @"UIScrollView", + @"fullTitle": @"AlwaysBounceHorizontal", + @"briefTitle": @"Horizontal", + @"patch": @(NO) + }, + LookinAttr_UIScrollView_ShowsIndicator_Hor: @{ + @"className": @"UIScrollView", + @"fullTitle": @"ShowsHorizontalScrollIndicator", + @"briefTitle": @"Horizontal", + @"patch": @(NO) + }, + LookinAttr_UIScrollView_ShowsIndicator_Ver: @{ + @"className": @"UIScrollView", + @"fullTitle": @"ShowsVerticalScrollIndicator", + @"briefTitle": @"Vertical", + @"patch": @(NO) + }, + LookinAttr_UIScrollView_ContentTouches_Delay: @{ + @"className": @"UIScrollView", + @"fullTitle": @"DelaysContentTouches", + @"patch": @(NO) + }, + LookinAttr_UIScrollView_ContentTouches_CanCancel: @{ + @"className": @"UIScrollView", + @"fullTitle": @"CanCancelContentTouches", + @"patch": @(NO) + }, + LookinAttr_UIScrollView_Zoom_MinScale: @{ + @"className": @"UIScrollView", + @"fullTitle": @"MinimumZoomScale", + @"briefTitle": @"MinScale", + @"patch": @(NO) + }, + LookinAttr_UIScrollView_Zoom_MaxScale: @{ + @"className": @"UIScrollView", + @"fullTitle": @"MaximumZoomScale", + @"briefTitle": @"MaxScale", + @"patch": @(NO) + }, + LookinAttr_UIScrollView_Zoom_Scale: @{ + @"className": @"UIScrollView", + @"fullTitle": @"ZoomScale", + @"briefTitle": @"Scale", + @"patch": @(YES) + }, + LookinAttr_UIScrollView_Zoom_Bounce: @{ + @"className": @"UIScrollView", + @"fullTitle": @"BouncesZoom", + @"patch": @(NO) + }, + + LookinAttr_UITableView_Style_Style: @{ + @"className": @"UITableView", + @"fullTitle": @"Style", + @"setterString": @"", + @"enumList": @"UITableViewStyle", + @"patch": @(YES) + }, + LookinAttr_UITableView_SectionsNumber_Number: @{ + @"className": @"UITableView", + @"fullTitle": @"NumberOfSections", + @"setterString": @"", + @"patch": @(YES) + }, + LookinAttr_UITableView_RowsNumber_Number: @{ + @"className": @"UITableView", + @"setterString": @"", + @"getterString": @"lks_numberOfRows", + @"typeIfObj": @(LookinAttrTypeCustomObj) + }, + LookinAttr_UITableView_SeparatorInset_Inset: @{ + @"className": @"UITableView", + @"fullTitle": @"SeparatorInset", + @"patch": @(NO) + }, + LookinAttr_UITableView_SeparatorColor_Color: @{ + @"className": @"UITableView", + @"fullTitle": @"SeparatorColor", + @"typeIfObj": @(LookinAttrTypeUIColor), + @"patch": @(YES) + }, + LookinAttr_UITableView_SeparatorStyle_Style: @{ + @"className": @"UITableView", + @"fullTitle": @"SeparatorStyle", + @"enumList": @"UITableViewCellSeparatorStyle", + @"patch": @(YES) + }, + + LookinAttr_UITextView_Text_Text: @{ + @"className": @"UITextView", + @"fullTitle": @"Text", + @"typeIfObj": @(LookinAttrTypeNSString), + @"patch": @(YES) + }, + LookinAttr_UITextView_Font_Name: @{ + @"className": @"UITextView", + @"fullTitle": @"FontName", + @"setterString": @"", + @"getterString": @"lks_fontName", + @"typeIfObj": @(LookinAttrTypeNSString), + @"patch": @(NO) + }, + LookinAttr_UITextView_Font_Size: @{ + @"className": @"UITextView", + @"fullTitle": @"FontSize", + @"setterString": @"setLks_fontSize:", + @"getterString": @"lks_fontSize", + @"patch": @(YES) + }, + LookinAttr_UITextView_Basic_Editable: @{ + @"className": @"UITextView", + @"fullTitle": @"Editable", + @"getterString": @"isEditable", + @"patch": @(NO) + }, + LookinAttr_UITextView_Basic_Selectable: @{ + @"className": @"UITextView", + @"fullTitle": @"Selectable", + @"getterString": @"isSelectable", + @"patch": @(NO) + }, + LookinAttr_UITextView_TextColor_Color: @{ + @"className": @"UITextView", + @"fullTitle": @"TextColor", + @"typeIfObj": @(LookinAttrTypeUIColor), + @"patch": @(YES) + }, + LookinAttr_UITextView_Alignment_Alignment: @{ + @"className": @"UITextView", + @"fullTitle": @"TextAlignment", + @"enumList": @"NSTextAlignment", + @"patch": @(YES) + }, + LookinAttr_UITextView_ContainerInset_Inset: @{ + @"className": @"UITextView", + @"fullTitle": @"TextContainerInset", + @"patch": @(YES) + }, + + LookinAttr_UITextField_Font_Name: @{ + @"className": @"UITextField", + @"fullTitle": @"FontName", + @"setterString": @"", + @"getterString": @"lks_fontName", + @"typeIfObj": @(LookinAttrTypeNSString), + @"patch": @(NO) + }, + LookinAttr_UITextField_Font_Size: @{ + @"className": @"UITextField", + @"fullTitle": @"FontSize", + @"setterString": @"setLks_fontSize:", + @"getterString": @"lks_fontSize", + @"patch": @(YES) + }, + LookinAttr_UITextField_TextColor_Color: @{ + @"className": @"UITextField", + @"fullTitle": @"TextColor", + @"typeIfObj": @(LookinAttrTypeUIColor), + @"patch": @(YES) + }, + LookinAttr_UITextField_Alignment_Alignment: @{ + @"className": @"UITextField", + @"fullTitle": @"TextAlignment", + @"enumList": @"NSTextAlignment", + @"patch": @(YES) + }, + LookinAttr_UITextField_Text_Text: @{ + @"className": @"UITextField", + @"fullTitle": @"Text", + @"typeIfObj": @(LookinAttrTypeNSString), + @"patch": @(YES) + }, + LookinAttr_UITextField_Placeholder_Placeholder: @{ + @"className": @"UITextField", + @"fullTitle": @"Placeholder", + @"typeIfObj": @(LookinAttrTypeNSString), + @"patch": @(YES) + }, + LookinAttr_UITextField_Clears_ClearsOnBeginEditing: @{ + @"className": @"UITextField", + @"fullTitle": @"ClearsOnBeginEditing", + @"patch": @(NO) + }, + LookinAttr_UITextField_Clears_ClearsOnInsertion: @{ + @"className": @"UITextField", + @"fullTitle": @"ClearsOnInsertion", + @"patch": @(NO) + }, + LookinAttr_UITextField_CanAdjustFont_CanAdjustFont: @{ + @"className": @"UITextField", + @"fullTitle": @"AdjustsFontSizeToFitWidth", + @"patch": @(YES) + }, + LookinAttr_UITextField_CanAdjustFont_MinSize: @{ + @"className": @"UITextField", + @"fullTitle": @"MinimumFontSize", + @"patch": @(YES) + }, + LookinAttr_UITextField_ClearButtonMode_Mode: @{ + @"className": @"UITextField", + @"fullTitle": @"ClearButtonMode", + @"enumList": @"UITextFieldViewMode", + @"patch": @(NO) + }, + }; + }); + + NSDictionary *targetInfo = dict[attrID]; + return targetInfo; +} + ++ (LookinAttrType)objectAttrTypeWithAttrID:(LookinAttrIdentifier)attrID { + NSDictionary *attrInfo = [self _infoForAttrID:attrID]; + NSNumber *typeIfObj = attrInfo[@"typeIfObj"]; + return [typeIfObj integerValue]; +} + ++ (NSString *)classNameWithAttrID:(LookinAttrIdentifier)attrID { + NSDictionary *attrInfo = [self _infoForAttrID:attrID]; + NSString *className = attrInfo[@"className"]; + + NSAssert(className.length > 0, @""); + + return className; +} + ++ (BOOL)isUIViewPropertyWithAttrID:(LookinAttrIdentifier)attrID { + NSString *className = [self classNameWithAttrID:attrID]; + + if ([className isEqualToString:@"CALayer"]) { + return NO; + } + return YES; +} + ++ (NSString *)enumListNameWithAttrID:(LookinAttrIdentifier)attrID { + NSDictionary *attrInfo = [self _infoForAttrID:attrID]; + NSString *name = attrInfo[@"enumList"]; + return name; +} + ++ (BOOL)needPatchAfterModificationWithAttrID:(LookinAttrIdentifier)attrID { + NSDictionary *attrInfo = [self _infoForAttrID:attrID]; + NSNumber *needPatch = attrInfo[@"patch"]; + return [needPatch boolValue]; +} + ++ (NSString *)fullTitleWithAttrID:(LookinAttrIdentifier)attrID { + NSDictionary *attrInfo = [self _infoForAttrID:attrID]; + NSString *fullTitle = attrInfo[@"fullTitle"]; + return fullTitle; +} + ++ (NSString *)briefTitleWithAttrID:(LookinAttrIdentifier)attrID { + NSDictionary *attrInfo = [self _infoForAttrID:attrID]; + NSString *briefTitle = attrInfo[@"briefTitle"]; + if (!briefTitle) { + briefTitle = attrInfo[@"fullTitle"]; + } + return briefTitle; +} + ++ (SEL)getterWithAttrID:(LookinAttrIdentifier)attrID { + NSDictionary *attrInfo = [self _infoForAttrID:attrID]; + NSString *getterString = attrInfo[@"getterString"]; + if (getterString && getterString.length == 0) { + // 空字符串,比如 image_open_open + return nil; + } + if (!getterString) { + NSString *fullTitle = attrInfo[@"fullTitle"]; + NSAssert(fullTitle.length > 0, @""); + + getterString = [NSString stringWithFormat:@"%@%@", [fullTitle substringToIndex:1].lowercaseString, [fullTitle substringFromIndex:1]].copy; + } + return NSSelectorFromString(getterString); +} + ++ (SEL)setterWithAttrID:(LookinAttrIdentifier)attrID { + NSDictionary *attrInfo = [self _infoForAttrID:attrID]; + NSString *setterString = attrInfo[@"setterString"]; + if ([setterString isEqualToString:@""]) { + // 该属性不可在 Lookin 客户端中被修改 + return nil; + } + if (!setterString) { + NSString *fullTitle = attrInfo[@"fullTitle"]; + NSAssert(fullTitle.length > 0, @""); + + setterString = [NSString stringWithFormat:@"set%@%@:", [fullTitle substringToIndex:1].uppercaseString, [fullTitle substringFromIndex:1]]; + } + return NSSelectorFromString(setterString); +} + ++ (BOOL)hideIfNilWithAttrID:(LookinAttrIdentifier)attrID { + NSDictionary *attrInfo = [self _infoForAttrID:attrID]; + NSNumber *boolValue = attrInfo[@"hideIfNil"]; + return boolValue.boolValue; +} + ++ (NSInteger)minAvailableOSVersionWithAttrID:(LookinAttrIdentifier)attrID { + NSDictionary *attrInfo = [self _infoForAttrID:attrID]; + NSNumber *minVerNum = attrInfo[@"osVersion"]; + NSInteger minVer = [minVerNum integerValue]; + return minVer; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinDefines.h b/Pods/LookinServer/Src/Main/Shared/LookinDefines.h new file mode 100644 index 0000000..f00540d --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinDefines.h @@ -0,0 +1,172 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinMessageProtocol.h +// Lookin +// +// Created by Li Kai on 2018/8/6. +// https://lookin.work +// + +#import "TargetConditionals.h" +#if TARGET_OS_IPHONE +#import +#elif TARGET_OS_MAC +#import +#endif + +#include + +#pragma mark - Version + +/// current connection protocol version of LookinServer +static const int LOOKIN_SERVER_VERSION = 7; + +/// current release version of LookinServer +static NSString * const LOOKIN_SERVER_READABLE_VERSION = @"1.2.8"; + +/// current connection protocol version of LookinClient +static const int LOOKIN_CLIENT_VERSION = 7; + +/// the minimum connection protocol version supported by current LookinClient +static const int LOOKIN_SUPPORTED_SERVER_MIN = 7; +/// the maximum connection protocol version supported by current LookinClient +static const int LOOKIN_SUPPORTED_SERVER_MAX = 7; + +#pragma mark - Connection + +/// LookinServer 在真机上会依次尝试监听 47175 ~ 47179 这几个端口 +static const int LookinUSBDeviceIPv4PortNumberStart = 47175; +static const int LookinUSBDeviceIPv4PortNumberEnd = 47179; + +/// LookinServer 在模拟器中会依次尝试监听 47164 ~ 47169 这几个端口 +static const int LookinSimulatorIPv4PortNumberStart = 47164; +static const int LookinSimulatorIPv4PortNumberEnd = 47169; + +enum { + /// 确认两端是否可以响应通讯 + LookinRequestTypePing = 200, + /// 请求 App 的截图、设备型号等信息 + LookinRequestTypeApp = 201, + /// 请求 Hierarchy 信息 + LookinRequestTypeHierarchy = 202, + /// 请求 screenshots 和 attrGroups 信息 + LookinRequestTypeHierarchyDetails = 203, + /// 请求修改某个内置的 Attribute 的值 + LookinRequestTypeInbuiltAttrModification = 204, + /// 修改某个 attr 后,请求一系列最新的 Screenshots、属性值等信息 + LookinRequestTypeAttrModificationPatch = 205, + /// 执行某个方法 + LookinRequestTypeInvokeMethod = 206, + /** + @request: @{@"oid":} + @response: LookinObject * + */ + LookinRequestTypeFetchObject = 207, + + LookinRequestTypeFetchImageViewImage = 208, + + LookinRequestTypeModifyRecognizerEnable = 209, + + /// 请求 attribute group list + LookinRequestTypeAllAttrGroups = 210, + + /// 请求 iOS App 里某个 class 的所有 selector 名字列表(包括 superclass) + LookinRequestTypeAllSelectorNames = 213, + + /// 请求修改某个自定义 Attribute 的值 + LookinRequestTypeCustomAttrModification = 214, + + /// 从 LookinServer 1.2.7 & Lookin 1.0.7 开始,该属性被废弃、不再使用 + LookinPush_BringForwardScreenshotTask = 303, + + // 用户在 Lookin 客户端取消了之前 HierarchyDetails 的拉取 + LookinPush_CanceHierarchyDetails = 304, +}; + +static NSString * const LookinParam_ViewLayerTag = @"tag"; + +static NSString * const LookinParam_SelectorName = @"sn"; +static NSString * const LookinParam_MethodType = @"mt"; +static NSString * const LookinParam_SelectorClassName = @"scn"; + +static NSString * const LookinStringFlag_VoidReturn = @"LOOKIN_TAG_RETURN_VALUE_VOID"; + +#pragma mark - Error + +static NSString * const LookinErrorDomain = @"LookinError"; + +enum { + LookinErrCode_Default = -400, + /// Lookin 内部业务逻辑错误 + LookinErrCode_Inner = -401, + /// PeerTalk 内部错误 + LookinErrCode_PeerTalk = -402, + /// 连接不存在或已断开 + LookinErrCode_NoConnect = -403, + /// ping 失败了,原因是 ping 请求超时 + LookinErrCode_PingFailForTimeout = -404, + /// 请求超时未返回 + LookinErrCode_Timeout = -405, + /// 有相同 Type 的新请求被发出,因此旧请求被丢弃 + LookinErrCode_Discard = -406, + /// ping 失败了,原因是 app 主动报告自身正处于后台模式 + LookinErrCode_PingFailForBackgroundState = -407, + + /// 没有找到对应的对象,可能已被释放 + LookinErrCode_ObjectNotFound = -500, + /// 不支持修改当前类型的 LookinCodingValueType + LookinErrCode_ModifyValueTypeInvalid = -501, + LookinErrCode_Exception = -502, + + // LookinServer 版本过高,要升级 client + LookinErrCode_ServerVersionTooHigh = -600, + // LookinServer 版本过低,要升级 server + LookinErrCode_ServerVersionTooLow = -601, + + // 不支持的文件类型 + LookinErrCode_UnsupportedFileType = -700, +}; + +#define LookinErr_ObjNotFound [NSError errorWithDomain:LookinErrorDomain code:LookinErrCode_ObjectNotFound userInfo:@{NSLocalizedDescriptionKey:NSLocalizedString(@"Failed to get target object in iOS app", nil), NSLocalizedRecoverySuggestionErrorKey:NSLocalizedString(@"Perhaps the related object was deallocated. You can reload Lookin to get newest data.", nil)}] + +#define LookinErr_NoConnect [NSError errorWithDomain:LookinErrorDomain code:LookinErrCode_NoConnect userInfo:@{NSLocalizedDescriptionKey:NSLocalizedString(@"The operation failed due to disconnection with the iOS app.", nil)}] + +#define LookinErr_Inner [NSError errorWithDomain:LookinErrorDomain code:LookinErrCode_Inner userInfo:@{NSLocalizedDescriptionKey:NSLocalizedString(@"The operation failed due to an inner error.", nil)}] + +#define LookinErrorMake(errorTitle, errorDetail) [NSError errorWithDomain:LookinErrorDomain code:LookinErrCode_Default userInfo:@{NSLocalizedDescriptionKey:errorTitle, NSLocalizedRecoverySuggestionErrorKey:errorDetail}] + +#define LookinErrorText_Timeout NSLocalizedString(@"Perhaps your iOS app is paused with breakpoint in Xcode, blocked by other tasks in main thread, or moved to background state.", nil) + +#pragma mark - Colors + +#if TARGET_OS_IPHONE +#define LookinColor UIColor +#define LookinInsets UIEdgeInsets +#define LookinImage UIImage +#elif TARGET_OS_MAC +#define LookinColor NSColor +#define LookinInsets NSEdgeInsets +#define LookinImage NSImage +#endif + +#define LookinColorRGBAMake(r, g, b, a) [LookinColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:a] +#define LookinColorMake(r, g, b) [LookinColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1] + +#pragma mark - Preview + +/// SCNNode 所允许的图片的最大的长和宽,单位是 px,这个值是 Scenekit 自身指定的 +/// Max pixel size of a SCNNode object. It is designated by SceneKit. +static const double LookinNodeImageMaxLengthInPx = 16384; + +typedef NS_OPTIONS(NSUInteger, LookinPreviewBitMask) { + LookinPreviewBitMask_None = 0, + + LookinPreviewBitMask_Selectable = 1 << 1, + LookinPreviewBitMask_Unselectable = 1 << 2, + + LookinPreviewBitMask_HasLight = 1 << 3, + LookinPreviewBitMask_NoLight = 1 << 4 +}; + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinDisplayItem.h b/Pods/LookinServer/Src/Main/Shared/LookinDisplayItem.h new file mode 100644 index 0000000..cea7247 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinDisplayItem.h @@ -0,0 +1,186 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinDisplayItem.h +// qmuidemo +// +// Created by Li Kai on 2018/11/15. +// Copyright © 2018 QMUI Team. All rights reserved. +// + +#import "TargetConditionals.h" +#import "LookinObject.h" +#import "LookinDefines.h" +#import "LookinCustomDisplayItemInfo.h" +#if TARGET_OS_IPHONE +#import +#elif TARGET_OS_MAC +#import +#endif + +@class LookinAttributesGroup, LookinIvarTrace, LookinPreviewItemLayer, LookinEventHandler, LKDisplayItemNode, LookinDisplayItem; + +typedef NS_ENUM(NSUInteger, LookinDisplayItemImageEncodeType) { + LookinDisplayItemImageEncodeTypeNone, // 不进行 encode + LookinDisplayItemImageEncodeTypeNSData, // 转换为 NSData + LookinDisplayItemImageEncodeTypeImage // 使用 NSImage / UIImage 自身的 encode 方法 +}; + +typedef NS_ENUM(NSUInteger, LookinDoNotFetchScreenshotReason) { + // can sync screenshot + LookinFetchScreenshotPermitted, + // layer is too large + LookinDoNotFetchScreenshotForTooLarge, + // refused by user config in LookinServer + LookinDoNotFetchScreenshotForUserConfig +}; + + +typedef NS_ENUM(NSUInteger, LookinDisplayItemProperty) { + // 当初次设置 delegate 对象时,会立即以该值触发一次 displayItem:propertyDidChange: + LookinDisplayItemProperty_None, + LookinDisplayItemProperty_FrameToRoot, + LookinDisplayItemProperty_DisplayingInHierarchy, + LookinDisplayItemProperty_InHiddenHierarchy, + LookinDisplayItemProperty_IsExpandable, + LookinDisplayItemProperty_IsExpanded, + LookinDisplayItemProperty_SoloScreenshot, + LookinDisplayItemProperty_GroupScreenshot, + LookinDisplayItemProperty_IsSelected, + LookinDisplayItemProperty_IsHovered, + LookinDisplayItemProperty_AvoidSyncScreenshot, + LookinDisplayItemProperty_InNoPreviewHierarchy, + LookinDisplayItemProperty_IsInSearch, + LookinDisplayItemProperty_HighlightedSearchString, +}; + +@protocol LookinDisplayItemDelegate + +- (void)displayItem:(LookinDisplayItem *)displayItem propertyDidChange:(LookinDisplayItemProperty)property; + +@end + +@interface LookinDisplayItem : NSObject + +/// 当 customInfo 不为 nil 时,意思是该 DisplayItem 为 UserCustom 配置的。此时,Encode 属性中仅 subitems 和 customAttrGroupList 属性有意义,其它几乎所有属性都无意义 +@property(nonatomic, strong) LookinCustomDisplayItemInfo *customInfo; + +@property(nonatomic, copy) NSArray *subitems; + +@property(nonatomic, assign) BOOL isHidden; + +@property(nonatomic, assign) float alpha; + +@property(nonatomic, assign) CGRect frame; + +@property(nonatomic, assign) CGRect bounds; + +/// 不存在 subitems 时,该属性的值为 nil +@property(nonatomic, strong) LookinImage *soloScreenshot; +/// 无论是否存在 subitems,该属性始终存在 +@property(nonatomic, strong) LookinImage *groupScreenshot; + +@property(nonatomic, strong) LookinObject *viewObject; +@property(nonatomic, strong) LookinObject *layerObject; +@property(nonatomic, strong) LookinObject *hostViewControllerObject; + +/// attrGroups 列表 +@property(nonatomic, copy) NSArray *attributesGroupList; +/// 通过 lookin_customDebugInfos 返回的属性列表 +@property(nonatomic, copy) NSArray *customAttrGroupList; +/// attributesGroupList + customAttrGroupList +- (NSArray *)queryAllAttrGroupList; + +@property(nonatomic, copy) NSArray *eventHandlers; + +// 如果当前 item 代表 UIWindow 且是 keyWindow,则该属性为 YES +@property(nonatomic, assign) BOOL representedAsKeyWindow; + + +/// view 或 layer 的 backgroundColor,利用该属性来提前渲染 node 的背景色,使得用户感觉加载的快一点 +/// 注意有一个缺点是,理论上应该像 screenshot 一样拆成 soloBackgroundColor 和 groupBackgroundColor,这里的 backgroundColor 实际上是 soloBackgroundColor,因此某些场景的显示会有瑕疵 +@property(nonatomic, strong) LookinColor *backgroundColor; + +/// 用户可以在 iOS 项目中添加 Lookin 自定义配置来显式地拒绝传输某些图层的图像,通常是屏蔽一些不重要的 View 以提升刷新速度。如果用户这么配置了,那么这个 shouldCaptureImage 就会被置为 NO +/// 默认为 YES +@property(nonatomic, assign) BOOL shouldCaptureImage; + +/// 用户通过重写 lookin_customDebugInfos 而自定义的该实例的名字 +/// 可能为 nil +@property(nonatomic, copy) NSString *customDisplayTitle; + +/// 为 DanceUI SDK 预留的内部字段,用于文件跳转 +/// 可能为 nil +@property(nonatomic, copy) NSString *danceuiSource; + +#pragma mark - No Encode/Decode + +@property(nonatomic, weak) id previewItemDelegate; +@property(nonatomic, weak) id rowViewDelegate; + +/// 父节点 +@property(nonatomic, weak) LookinDisplayItem *superItem; + +/// 如果存在 viewObject 则返回 viewObject,否则返回 layerObject +- (LookinObject *)displayingObject; + +/// 在 hierarchy 中的层级,比如顶层的 UIWindow.indentLevel 为 0,UIWindow 的 subitem 的 indentLevel 为 1 +- (NSInteger)indentLevel; + +/** + 该项是否被展开 + @note 假如自己没有被折叠,但是 superItem 被折叠了,则自己仍然不会被看到,但是 self.isExpanded 值仍然为 NO + @note 如果 item 没有 subitems(也就是 isExpandable 为 NO),则该值没有意义。换句话说,在获取该值之前,必须先判断一下 isExpandable + */ +@property(nonatomic, assign) BOOL isExpanded; + +/// 如果有 subitems,则该属性返回 YES,否则返回 NO +@property(nonatomic, assign, readonly) BOOL isExpandable; + +/** + 是否能在 hierarchy panel 上被看到,假如有任意一层的父级元素的 isExpanded 为 NO,则 displayingInHierarchy 为 NO。如果所有父级元素的 isExpanded 均为 YES,则 displayingInHierarchy 为 YES + */ +@property(nonatomic, assign, readonly) BOOL displayingInHierarchy; + +/** + 如果自身或任意一个上层元素的 isHidden 为 YES 或 alpha 为 0,则该属性返回 YES + */ +@property(nonatomic, assign, readonly) BOOL inHiddenHierarchy; + +@property(nonatomic, assign) LookinDisplayItemImageEncodeType screenshotEncodeType; + +/// Whether to fetch screenshot and why. Default to LookinFetchScreenshotPermitted. +@property(nonatomic, assign) LookinDoNotFetchScreenshotReason doNotFetchScreenshotReason; + +@property(nonatomic, weak) LookinPreviewItemLayer *previewLayer; + +@property(nonatomic, weak) LKDisplayItemNode *previewNode; + +/// 如果该值为 YES,则该 item 及所有子 item 均不会在 preview 中被显示出来,只能在 hierarchy 中选择。默认为 NO +@property(nonatomic, assign) BOOL noPreview; + +/// 如果自身或某个上级元素的 noPreview 值为 YES,则该方法返回 YES +/// 注意:当 userCustom 为 YES 时,该属性也可能返回 YES +@property(nonatomic, assign, readonly) BOOL inNoPreviewHierarchy; + +/// 当小于 0 时表示未被设置 +@property(nonatomic, assign) NSInteger previewZIndex; + +@property(nonatomic, assign) BOOL preferToBeCollapsed; + +- (void)notifySelectionChangeToDelegates; +- (void)notifyHoverChangeToDelegates; + +/// 根据 subItems 属性将 items 打平为一维数组 ++ (NSArray *)flatItemsFromHierarchicalItems:(NSArray *)items; + +@property(nonatomic, assign) BOOL hasDeterminedExpansion; + +/// 设置当前是否处于搜索状态 +@property(nonatomic, assign) BOOL isInSearch; +/// 因为搜索而应该被高亮的字符串 +@property(nonatomic, copy) NSString *highlightedSearchString; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinDisplayItem.m b/Pods/LookinServer/Src/Main/Shared/LookinDisplayItem.m new file mode 100644 index 0000000..82ef8d9 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinDisplayItem.m @@ -0,0 +1,450 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinDisplayItem.m +// qmuidemo +// +// Created by Li Kai on 2018/11/15. +// Copyright © 2018 QMUI Team. All rights reserved. +// + +#import "LookinDisplayItem.h" +#import "LookinAttributesGroup.h" +#import "LookinAttributesSection.h" +#import "LookinAttribute.h" +#import "LookinEventHandler.h" +#import "LookinIvarTrace.h" +#import "Color+Lookin.h" +#import "NSArray+Lookin.h" +#import "NSObject+Lookin.h" +#import "LookinDashboardBlueprint.h" + +#if TARGET_OS_IPHONE +#import "UIColor+LookinServer.h" +#import "UIImage+LookinServer.h" +#elif TARGET_OS_MAC +#endif + +@interface LookinDisplayItem () + +@property(nonatomic, assign, readwrite) CGRect frameToRoot; +@property(nonatomic, assign, readwrite) BOOL inNoPreviewHierarchy; +@property(nonatomic, assign) NSInteger indentLevel; +@property(nonatomic, assign, readwrite) BOOL isExpandable; +@property(nonatomic, assign, readwrite) BOOL inHiddenHierarchy; +@property(nonatomic, assign, readwrite) BOOL displayingInHierarchy; + +@end + +@implementation LookinDisplayItem + +#pragma mark - + +- (id)copyWithZone:(NSZone *)zone { + LookinDisplayItem *newDisplayItem = [[LookinDisplayItem allocWithZone:zone] init]; + newDisplayItem.subitems = [self.subitems lookin_map:^id(NSUInteger idx, LookinDisplayItem *value) { + return value.copy; + }]; + newDisplayItem.customInfo = self.customInfo.copy; + newDisplayItem.isHidden = self.isHidden; + newDisplayItem.alpha = self.alpha; + newDisplayItem.frame = self.frame; + newDisplayItem.bounds = self.bounds; + newDisplayItem.soloScreenshot = self.soloScreenshot; + newDisplayItem.groupScreenshot = self.groupScreenshot; + newDisplayItem.viewObject = self.viewObject.copy; + newDisplayItem.layerObject = self.layerObject.copy; + newDisplayItem.hostViewControllerObject = self.hostViewControllerObject.copy; + newDisplayItem.attributesGroupList = [self.attributesGroupList lookin_map:^id(NSUInteger idx, LookinAttributesGroup *value) { + return value.copy; + }]; + newDisplayItem.customAttrGroupList = [self.customAttrGroupList lookin_map:^id(NSUInteger idx, LookinAttributesGroup *value) { + return value.copy; + }]; + newDisplayItem.eventHandlers = [self.eventHandlers lookin_map:^id(NSUInteger idx, LookinEventHandler *value) { + return value.copy; + }]; + newDisplayItem.shouldCaptureImage = self.shouldCaptureImage; + newDisplayItem.representedAsKeyWindow = self.representedAsKeyWindow; + newDisplayItem.customDisplayTitle = self.customDisplayTitle; + newDisplayItem.danceuiSource = self.danceuiSource; + [newDisplayItem _updateDisplayingInHierarchyProperty]; + return newDisplayItem; +} +#pragma mark - + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:self.customInfo forKey:@"customInfo"]; + [aCoder encodeObject:self.subitems forKey:@"subitems"]; + [aCoder encodeBool:self.isHidden forKey:@"hidden"]; + [aCoder encodeFloat:self.alpha forKey:@"alpha"]; + [aCoder encodeObject:self.viewObject forKey:@"viewObject"]; + [aCoder encodeObject:self.layerObject forKey:@"layerObject"]; + [aCoder encodeObject:self.hostViewControllerObject forKey:@"hostViewControllerObject"]; + [aCoder encodeObject:self.attributesGroupList forKey:@"attributesGroupList"]; + [aCoder encodeObject:self.customAttrGroupList forKey:@"customAttrGroupList"]; + [aCoder encodeBool:self.representedAsKeyWindow forKey:@"representedAsKeyWindow"]; + [aCoder encodeObject:self.eventHandlers forKey:@"eventHandlers"]; + [aCoder encodeBool:self.shouldCaptureImage forKey:@"shouldCaptureImage"]; + if (self.screenshotEncodeType == LookinDisplayItemImageEncodeTypeNSData) { + [aCoder encodeObject:[self.soloScreenshot lookin_encodedObjectWithType:LookinCodingValueTypeImage] forKey:@"soloScreenshot"]; + [aCoder encodeObject:[self.groupScreenshot lookin_encodedObjectWithType:LookinCodingValueTypeImage] forKey:@"groupScreenshot"]; + } else if (self.screenshotEncodeType == LookinDisplayItemImageEncodeTypeImage) { + [aCoder encodeObject:self.soloScreenshot forKey:@"soloScreenshot"]; + [aCoder encodeObject:self.groupScreenshot forKey:@"groupScreenshot"]; + } + [aCoder encodeObject:self.customDisplayTitle forKey:@"customDisplayTitle"]; + [aCoder encodeObject:self.danceuiSource forKey:@"danceuiSource"]; +#if TARGET_OS_IPHONE + [aCoder encodeCGRect:self.frame forKey:@"frame"]; + [aCoder encodeCGRect:self.bounds forKey:@"bounds"]; + [aCoder encodeObject:self.backgroundColor.lks_rgbaComponents forKey:@"backgroundColor"]; + +#elif TARGET_OS_MAC + [aCoder encodeRect:self.frame forKey:@"frame"]; + [aCoder encodeRect:self.bounds forKey:@"bounds"]; + [aCoder encodeObject:self.backgroundColor.lookin_rgbaComponents forKey:@"backgroundColor"]; +#endif +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if (self = [super init]) { + self.customInfo = [aDecoder decodeObjectForKey:@"customInfo"]; + self.subitems = [aDecoder decodeObjectForKey:@"subitems"]; + self.isHidden = [aDecoder decodeBoolForKey:@"hidden"]; + self.alpha = [aDecoder decodeFloatForKey:@"alpha"]; + self.viewObject = [aDecoder decodeObjectForKey:@"viewObject"]; + self.layerObject = [aDecoder decodeObjectForKey:@"layerObject"]; + self.hostViewControllerObject = [aDecoder decodeObjectForKey:@"hostViewControllerObject"]; + self.attributesGroupList = [aDecoder decodeObjectForKey:@"attributesGroupList"]; + self.customAttrGroupList = [aDecoder decodeObjectForKey:@"customAttrGroupList"]; + self.representedAsKeyWindow = [aDecoder decodeBoolForKey:@"representedAsKeyWindow"]; + + id soloScreenshotObj = [aDecoder decodeObjectForKey:@"soloScreenshot"]; + if (soloScreenshotObj) { + if ([soloScreenshotObj isKindOfClass:[NSData class]]) { + self.soloScreenshot = [soloScreenshotObj lookin_decodedObjectWithType:LookinCodingValueTypeImage]; + } else if ([soloScreenshotObj isKindOfClass:[LookinImage class]]) { + self.soloScreenshot = soloScreenshotObj; + } else { + NSAssert(NO, @""); + } + } + + id groupScreenshotObj = [aDecoder decodeObjectForKey:@"groupScreenshot"]; + if (groupScreenshotObj) { + if ([groupScreenshotObj isKindOfClass:[NSData class]]) { + self.groupScreenshot = [groupScreenshotObj lookin_decodedObjectWithType:LookinCodingValueTypeImage]; + } else if ([groupScreenshotObj isKindOfClass:[LookinImage class]]) { + self.groupScreenshot = groupScreenshotObj; + } else { + NSAssert(NO, @""); + } + } + + self.eventHandlers = [aDecoder decodeObjectForKey:@"eventHandlers"]; + /// this property was added in LookinServer 1.1.3 + self.shouldCaptureImage = [aDecoder containsValueForKey:@"shouldCaptureImage"] ? [aDecoder decodeBoolForKey:@"shouldCaptureImage"] : YES; + self.customDisplayTitle = [aDecoder decodeObjectForKey:@"customDisplayTitle"]; + self.danceuiSource = [aDecoder decodeObjectForKey:@"danceuiSource"]; +#if TARGET_OS_IPHONE + self.frame = [aDecoder decodeCGRectForKey:@"frame"]; + self.bounds = [aDecoder decodeCGRectForKey:@"bounds"]; + self.backgroundColor = [UIColor lks_colorFromRGBAComponents:[aDecoder decodeObjectForKey:@"backgroundColor"]]; +#elif TARGET_OS_MAC + self.frame = [aDecoder decodeRectForKey:@"frame"]; + self.bounds = [aDecoder decodeRectForKey:@"bounds"]; + self.backgroundColor = [NSColor lookin_colorFromRGBAComponents:[aDecoder decodeObjectForKey:@"backgroundColor"]]; + +#endif + [self _updateDisplayingInHierarchyProperty]; + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)init { + if (self = [super init]) { + /// 在手机端,displayItem 被创建时会调用这个方法 + [self _updateDisplayingInHierarchyProperty]; + } + return self; +} + +- (LookinObject *)displayingObject { + return self.viewObject ? : self.layerObject; +} + +- (void)setAttributesGroupList:(NSArray *)attributesGroupList { + _attributesGroupList = attributesGroupList; + + [_attributesGroupList enumerateObjectsUsingBlock:^(LookinAttributesGroup * _Nonnull group, NSUInteger idx, BOOL * _Nonnull stop) { + [group.attrSections enumerateObjectsUsingBlock:^(LookinAttributesSection * _Nonnull section, NSUInteger idx, BOOL * _Nonnull stop) { + [section.attributes enumerateObjectsUsingBlock:^(LookinAttribute * _Nonnull attr, NSUInteger idx, BOOL * _Nonnull stop) { + attr.targetDisplayItem = self; + }]; + }]; + }]; +} + +- (void)setCustomAttrGroupList:(NSArray *)customAttrGroupList { + _customAttrGroupList = customAttrGroupList; + // 传进来的时候就已经排好序了 + [customAttrGroupList enumerateObjectsUsingBlock:^(LookinAttributesGroup * _Nonnull group, NSUInteger idx, BOOL * _Nonnull stop) { + [group.attrSections enumerateObjectsUsingBlock:^(LookinAttributesSection * _Nonnull section, NSUInteger idx, BOOL * _Nonnull stop) { + [section.attributes enumerateObjectsUsingBlock:^(LookinAttribute * _Nonnull attr, NSUInteger idx, BOOL * _Nonnull stop) { + attr.targetDisplayItem = self; + }]; + }]; + }]; +} + +- (void)setSubitems:(NSArray *)subitems { + [_subitems enumerateObjectsUsingBlock:^(LookinDisplayItem * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + obj.superItem = nil; + }]; + + _subitems = subitems; + + self.isExpandable = (subitems.count > 0); + + [subitems enumerateObjectsUsingBlock:^(LookinDisplayItem * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + NSAssert(!obj.superItem, @""); + obj.superItem = self; + + [obj _updateInHiddenHierarchyProperty]; + [obj _updateDisplayingInHierarchyProperty]; + }]; +} + +- (void)setIsExpandable:(BOOL)isExpandable { + if (_isExpandable == isExpandable) { + return; + } + _isExpandable = isExpandable; + [self _notifyDelegatesWith:LookinDisplayItemProperty_IsExpandable]; +} + +- (void)setIsExpanded:(BOOL)isExpanded { + if (_isExpanded == isExpanded) { + return; + } + _isExpanded = isExpanded; + [self.subitems enumerateObjectsUsingBlock:^(LookinDisplayItem * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + [obj _updateDisplayingInHierarchyProperty]; + }]; + [self _notifyDelegatesWith:LookinDisplayItemProperty_IsExpanded]; +} + +- (void)setSoloScreenshot:(LookinImage *)soloScreenshot { + if (_soloScreenshot == soloScreenshot) { + return; + } + _soloScreenshot = soloScreenshot; + [self _notifyDelegatesWith:LookinDisplayItemProperty_SoloScreenshot]; +} + +- (void)notifySelectionChangeToDelegates { + [self _notifyDelegatesWith:LookinDisplayItemProperty_IsSelected]; +} + +- (void)notifyHoverChangeToDelegates { + [self _notifyDelegatesWith:LookinDisplayItemProperty_IsHovered]; +} + +- (void)setDoNotFetchScreenshotReason:(LookinDoNotFetchScreenshotReason)doNotFetchScreenshotReason { + if (_doNotFetchScreenshotReason == doNotFetchScreenshotReason) { + return; + } + _doNotFetchScreenshotReason = doNotFetchScreenshotReason; + [self _notifyDelegatesWith:LookinDisplayItemProperty_AvoidSyncScreenshot]; +} + +- (void)setGroupScreenshot:(LookinImage *)groupScreenshot { + if (_groupScreenshot == groupScreenshot) { + return; + } + _groupScreenshot = groupScreenshot; + [self _notifyDelegatesWith:LookinDisplayItemProperty_GroupScreenshot]; +} + +- (void)setDisplayingInHierarchy:(BOOL)displayingInHierarchy { + if (_displayingInHierarchy == displayingInHierarchy) { + return; + } + _displayingInHierarchy = displayingInHierarchy; + [self.subitems enumerateObjectsUsingBlock:^(LookinDisplayItem * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + [obj _updateDisplayingInHierarchyProperty]; + }]; + + [self _notifyDelegatesWith:LookinDisplayItemProperty_DisplayingInHierarchy]; +} + +- (void)_updateDisplayingInHierarchyProperty { + if (self.superItem && (!self.superItem.displayingInHierarchy || !self.superItem.isExpanded)) { + self.displayingInHierarchy = NO; + } else { + self.displayingInHierarchy = YES; + } +} + +- (void)setIsHidden:(BOOL)isHidden { + _isHidden = isHidden; + [self _updateInHiddenHierarchyProperty]; +} + +- (void)setAlpha:(float)alpha { + _alpha = alpha; + [self _updateInHiddenHierarchyProperty]; +} + +- (void)setInHiddenHierarchy:(BOOL)inHiddenHierarchy { + if (_inHiddenHierarchy == inHiddenHierarchy) { + return; + } + _inHiddenHierarchy = inHiddenHierarchy; + [self.subitems enumerateObjectsUsingBlock:^(LookinDisplayItem * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + [obj _updateInHiddenHierarchyProperty]; + }]; + + [self _notifyDelegatesWith:LookinDisplayItemProperty_InHiddenHierarchy]; +} + +- (void)_updateInHiddenHierarchyProperty { + if (self.superItem.inHiddenHierarchy || self.isHidden || self.alpha <= 0) { + self.inHiddenHierarchy = YES; + } else { + self.inHiddenHierarchy = NO; + } +} + ++ (NSArray *)flatItemsFromHierarchicalItems:(NSArray *)items { + NSMutableArray *resultArray = [NSMutableArray array]; + + [items enumerateObjectsUsingBlock:^(LookinDisplayItem * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + if (obj.superItem) { + obj.indentLevel = obj.superItem.indentLevel + 1; + } + [resultArray addObject:obj]; + if (obj.subitems.count) { + [resultArray addObjectsFromArray:[self flatItemsFromHierarchicalItems:obj.subitems]]; + } + }]; + + return resultArray; +} + +- (NSString *)description { + if (self.viewObject) { + return self.viewObject.rawClassName; + } else if (self.layerObject) { + return self.layerObject.rawClassName; + } else { + return [super description]; + } +} + +- (void)setPreviewItemDelegate:(id)previewItemDelegate { + _previewItemDelegate = previewItemDelegate; + + if (![previewItemDelegate respondsToSelector:@selector(displayItem:propertyDidChange:)]) { + NSAssert(NO, @""); + _previewItemDelegate = nil; + return; + } + [self.previewItemDelegate displayItem:self propertyDidChange:LookinDisplayItemProperty_None]; +} + +- (void)setRowViewDelegate:(id)rowViewDelegate { + if (_rowViewDelegate == rowViewDelegate) { + return; + } + _rowViewDelegate = rowViewDelegate; + + if (![rowViewDelegate respondsToSelector:@selector(displayItem:propertyDidChange:)]) { + NSAssert(NO, @""); + _rowViewDelegate = nil; + return; + } + [self.rowViewDelegate displayItem:self propertyDidChange:LookinDisplayItemProperty_None]; +} + +- (void)setFrame:(CGRect)frame { + _frame = frame; + [self recursivelyNotifyFrameToRootMayChange]; +} + +- (void)recursivelyNotifyFrameToRootMayChange { + [self _notifyDelegatesWith:LookinDisplayItemProperty_FrameToRoot]; + + [self.subitems enumerateObjectsUsingBlock:^(LookinDisplayItem * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + [obj recursivelyNotifyFrameToRootMayChange]; + }]; +} + +- (void)setBounds:(CGRect)bounds { + _bounds = bounds; + [self recursivelyNotifyFrameToRootMayChange]; +} + +- (void)setInNoPreviewHierarchy:(BOOL)inNoPreviewHierarchy { + if (_inNoPreviewHierarchy == inNoPreviewHierarchy) { + return; + } + _inNoPreviewHierarchy = inNoPreviewHierarchy; + [self.subitems enumerateObjectsUsingBlock:^(LookinDisplayItem * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + [obj _updateInNoPreviewHierarchy]; + }]; + [self _notifyDelegatesWith:LookinDisplayItemProperty_InNoPreviewHierarchy]; +} + +- (void)setNoPreview:(BOOL)noPreview { + _noPreview = noPreview; + [self _updateInNoPreviewHierarchy]; +} + +- (void)_updateInNoPreviewHierarchy { + if (self.superItem.inNoPreviewHierarchy || self.noPreview) { + self.inNoPreviewHierarchy = YES; + } else { + self.inNoPreviewHierarchy = NO; + } +} + +- (void)_notifyDelegatesWith:(LookinDisplayItemProperty)property { + [self.previewItemDelegate displayItem:self propertyDidChange:property]; + [self.rowViewDelegate displayItem:self propertyDidChange:property]; +} + +- (void)setIsInSearch:(BOOL)isInSearch { + _isInSearch = isInSearch; + [self _notifyDelegatesWith:LookinDisplayItemProperty_IsInSearch]; +} + +- (void)setHighlightedSearchString:(NSString *)highlightedSearchString { + _highlightedSearchString = highlightedSearchString; + [self _notifyDelegatesWith:LookinDisplayItemProperty_HighlightedSearchString]; +} + +- (NSArray *)queryAllAttrGroupList { + NSMutableArray *array = [NSMutableArray array]; + if (self.attributesGroupList) { + [array addObjectsFromArray:self.attributesGroupList]; + } + if (self.customAttrGroupList) { + [array addObjectsFromArray:self.customAttrGroupList]; + } + return array; +} + +//- (void)dealloc +//{ +// NSLog(@"moss dealloc -%@", self); +//} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinDisplayItemDetail.h b/Pods/LookinServer/Src/Main/Shared/LookinDisplayItemDetail.h new file mode 100644 index 0000000..adb60c3 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinDisplayItemDetail.h @@ -0,0 +1,51 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinDisplayItemDetail.h +// Lookin +// +// Created by Li Kai on 2019/2/19. +// https://lookin.work +// + +#import "LookinDefines.h" + +@class LookinAttributesGroup; +@class LookinDisplayItem; + +@interface LookinDisplayItemDetail : NSObject + +@property(nonatomic, assign) unsigned long displayItemOid; + +@property(nonatomic, strong) LookinImage *groupScreenshot; + +@property(nonatomic, strong) LookinImage *soloScreenshot; + +@property(nonatomic, strong) NSValue *frameValue; + +@property(nonatomic, strong) NSValue *boundsValue; + +@property(nonatomic, strong) NSNumber *hiddenValue; + +@property(nonatomic, strong) NSNumber *alphaValue; + +@property(nonatomic, copy) NSString *customDisplayTitle; + +@property(nonatomic, copy) NSString *danceUISource; + +@property(nonatomic, copy) NSArray *attributesGroupList; +@property(nonatomic, copy) NSArray *customAttrGroupList; + +/// 注意 nil 和空数组的区别:nil 表示该属性无意义,空数组表示 subviews 为空 +/// Client 1.0.7 & Server 1.2.7 开始支持该属性 +/// 默认为 nil +@property(nonatomic, copy) NSArray *subitems; + +/// 当 Server 找不到 task 对应的图层时,会返回一个特殊的 LookinDisplayItemDetail 对象,这个对象会被设置 displayItemOid 和 failureCode,其中 failureCode 会被置为 -1 +/// Client 1.0.7 & Server 1.2.7 开始支持该属性 +/// 默认为 0 +@property(nonatomic, assign) NSInteger failureCode; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinDisplayItemDetail.m b/Pods/LookinServer/Src/Main/Shared/LookinDisplayItemDetail.m new file mode 100644 index 0000000..195c03c --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinDisplayItemDetail.m @@ -0,0 +1,71 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinDisplayItemDetail.m +// Lookin +// +// Created by Li Kai on 2019/2/19. +// https://lookin.work +// + +#import "LookinDisplayItemDetail.h" +#import "Image+Lookin.h" + +#if TARGET_OS_IPHONE +#import "UIImage+LookinServer.h" +#endif + +@implementation LookinDisplayItemDetail + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:@(self.displayItemOid) forKey:@"displayItemOid"]; + [aCoder encodeObject:self.groupScreenshot.lookin_data forKey:@"groupScreenshot"]; + [aCoder encodeObject:self.soloScreenshot.lookin_data forKey:@"soloScreenshot"]; + [aCoder encodeObject:self.frameValue forKey:@"frameValue"]; + [aCoder encodeObject:self.boundsValue forKey:@"boundsValue"]; + [aCoder encodeObject:self.hiddenValue forKey:@"hiddenValue"]; + [aCoder encodeObject:self.alphaValue forKey:@"alphaValue"]; + [aCoder encodeObject:self.attributesGroupList forKey:@"attributesGroupList"]; + [aCoder encodeObject:self.customAttrGroupList forKey:@"customAttrGroupList"]; + [aCoder encodeObject:self.customDisplayTitle forKey:@"customDisplayTitle"]; + [aCoder encodeObject:self.danceUISource forKey:@"danceUISource"]; + [aCoder encodeInteger:self.failureCode forKey:@"failureCode"]; + if (self.subitems) { + [aCoder encodeObject:self.subitems forKey:@"subitems"]; + } +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if (self = [super init]) { + self.displayItemOid = [[aDecoder decodeObjectForKey:@"displayItemOid"] unsignedLongValue]; + self.groupScreenshot = [[LookinImage alloc] initWithData:[aDecoder decodeObjectForKey:@"groupScreenshot"]]; + self.soloScreenshot = [[LookinImage alloc] initWithData:[aDecoder decodeObjectForKey:@"soloScreenshot"]]; + self.frameValue = [aDecoder decodeObjectForKey:@"frameValue"]; + self.boundsValue = [aDecoder decodeObjectForKey:@"boundsValue"]; + self.hiddenValue = [aDecoder decodeObjectForKey:@"hiddenValue"]; + self.alphaValue = [aDecoder decodeObjectForKey:@"alphaValue"]; + self.attributesGroupList = [aDecoder decodeObjectForKey:@"attributesGroupList"]; + self.customAttrGroupList = [aDecoder decodeObjectForKey:@"customAttrGroupList"]; + self.customDisplayTitle = [aDecoder decodeObjectForKey:@"customDisplayTitle"]; + self.danceUISource = [aDecoder decodeObjectForKey:@"danceUISource"]; + + if ([aDecoder containsValueForKey:@"failureCode"]) { + self.failureCode = [aDecoder decodeIntegerForKey:@"failureCode"]; + } else { + self.failureCode = 0; + } + + if ([aDecoder containsValueForKey:@"subitems"]) { + self.subitems = [aDecoder decodeObjectForKey:@"subitems"]; + } + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinEventHandler.h b/Pods/LookinServer/Src/Main/Shared/LookinEventHandler.h new file mode 100644 index 0000000..cf44b76 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinEventHandler.h @@ -0,0 +1,43 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinEventHandler.h +// Lookin +// +// Created by Li Kai on 2019/8/7. +// https://lookin.work +// + + + +#import + +@class LookinObject, LookinIvarTrace, LookinStringTwoTuple; + +typedef NS_ENUM(NSInteger, LookinEventHandlerType) { + LookinEventHandlerTypeTargetAction, + LookinEventHandlerTypeGesture +}; + +@interface LookinEventHandler : NSObject + +@property(nonatomic, assign) LookinEventHandlerType handlerType; + +/// 比如 "UIControlEventTouchUpInside", "UITapGestureRecognizer" +@property(nonatomic, copy) NSString *eventName; +/// tuple.first => @"",tuple.second => @"handleTap" +@property(nonatomic, copy) NSArray *targetActions; + +/// 返回当前 recognizer 是继承自哪一个基本款 recognizer。 +/// 基本款 recognizer 指的是 TapRecognizer, PinchRecognizer 之类的常见 recognizer +/// 如果当前 recognizer 本身就是基本款 recognizer,则该属性为 nil +@property(nonatomic, copy) NSString *inheritedRecognizerName; +@property(nonatomic, assign) BOOL gestureRecognizerIsEnabled; +@property(nonatomic, copy) NSString *gestureRecognizerDelegator; +@property(nonatomic, copy) NSArray *recognizerIvarTraces; +/// recognizer 对象 +@property(nonatomic, assign) unsigned long long recognizerOid; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinEventHandler.m b/Pods/LookinServer/Src/Main/Shared/LookinEventHandler.m new file mode 100644 index 0000000..8a1576c --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinEventHandler.m @@ -0,0 +1,71 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinEventHandler.m +// Lookin +// +// Created by Li Kai on 2019/8/7. +// https://lookin.work +// + + + +#import "LookinEventHandler.h" +#import "LookinObject.h" +#import "LookinTuple.h" + +#import "NSArray+Lookin.h" + +@implementation LookinEventHandler + +#pragma mark - + +- (id)copyWithZone:(NSZone *)zone { + LookinEventHandler *newHandler = [[LookinEventHandler allocWithZone:zone] init]; + newHandler.handlerType = self.handlerType; + newHandler.eventName = self.eventName; + newHandler.targetActions = [self.targetActions lookin_map:^id(NSUInteger idx, LookinStringTwoTuple *value) { + return value.copy; + }]; + newHandler.gestureRecognizerIsEnabled = self.gestureRecognizerIsEnabled; + newHandler.gestureRecognizerDelegator = self.gestureRecognizerDelegator; + newHandler.inheritedRecognizerName = self.inheritedRecognizerName; + newHandler.recognizerIvarTraces = self.recognizerIvarTraces.copy; + newHandler.recognizerOid = self.recognizerOid; + return newHandler; +} + +#pragma mark - + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeInteger:self.handlerType forKey:@"handlerType"]; + [aCoder encodeBool:self.gestureRecognizerIsEnabled forKey:@"gestureRecognizerIsEnabled"]; + [aCoder encodeObject:self.eventName forKey:@"eventName"]; + [aCoder encodeObject:self.gestureRecognizerDelegator forKey:@"gestureRecognizerDelegator"]; + [aCoder encodeObject:self.targetActions forKey:@"targetActions"]; + [aCoder encodeObject:self.inheritedRecognizerName forKey:@"inheritedRecognizerName"]; + [aCoder encodeObject:self.recognizerIvarTraces forKey:@"recognizerIvarTraces"]; + [aCoder encodeObject:@(self.recognizerOid) forKey:@"recognizerOid"]; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if (self = [super init]) { + self.handlerType = [aDecoder decodeIntegerForKey:@"handlerType"]; + self.gestureRecognizerIsEnabled = [aDecoder decodeBoolForKey:@"gestureRecognizerIsEnabled"]; + self.eventName = [aDecoder decodeObjectForKey:@"eventName"]; + self.gestureRecognizerDelegator = [aDecoder decodeObjectForKey:@"gestureRecognizerDelegator"]; + self.targetActions = [aDecoder decodeObjectForKey:@"targetActions"]; + self.inheritedRecognizerName = [aDecoder decodeObjectForKey:@"inheritedRecognizerName"]; + self.recognizerIvarTraces = [aDecoder decodeObjectForKey:@"recognizerIvarTraces"]; + self.recognizerOid = ((NSNumber *)[aDecoder decodeObjectForKey:@"recognizerOid"]).unsignedLongValue; + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinHierarchyFile.h b/Pods/LookinServer/Src/Main/Shared/LookinHierarchyFile.h new file mode 100644 index 0000000..afa02cd --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinHierarchyFile.h @@ -0,0 +1,32 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinHierarchyFile.h +// Lookin +// +// Created by Li Kai on 2019/5/12. +// https://lookin.work +// + + + +#import + +@class LookinHierarchyInfo; + +@interface LookinHierarchyFile : NSObject + +/// 记录创建该文件的 LookinServer 的版本 +@property(nonatomic, assign) int serverVersion; + +@property(nonatomic, strong) LookinHierarchyInfo *hierarchyInfo; + +@property(nonatomic, copy) NSDictionary *soloScreenshots; +@property(nonatomic, copy) NSDictionary *groupScreenshots; + +/// 验证 file 的版本之类的是否和当前 Lookin 客户端匹配,如果没有问题则返回 nil,如果有问题则返回 error ++ (NSError *)verifyHierarchyFile:(LookinHierarchyFile *)file; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinHierarchyFile.m b/Pods/LookinServer/Src/Main/Shared/LookinHierarchyFile.m new file mode 100644 index 0000000..4b07e4a --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinHierarchyFile.m @@ -0,0 +1,64 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinHierarchyFile.m +// Lookin +// +// Created by Li Kai on 2019/5/12. +// https://lookin.work +// + + + +#import "LookinHierarchyFile.h" + +#import "NSArray+Lookin.h" + +@implementation LookinHierarchyFile + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeInt:self.serverVersion forKey:@"serverVersion"]; + [aCoder encodeObject:self.hierarchyInfo forKey:@"hierarchyInfo"]; + [aCoder encodeObject:self.soloScreenshots forKey:@"soloScreenshots"]; + [aCoder encodeObject:self.groupScreenshots forKey:@"groupScreenshots"]; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if (self = [super init]) { + self.serverVersion = [aDecoder decodeIntForKey:@"serverVersion"]; + self.hierarchyInfo = [aDecoder decodeObjectForKey:@"hierarchyInfo"]; + self.soloScreenshots = [aDecoder decodeObjectForKey:@"soloScreenshots"]; + self.groupScreenshots = [aDecoder decodeObjectForKey:@"groupScreenshots"]; + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + ++ (NSError *)verifyHierarchyFile:(LookinHierarchyFile *)hierarchyFile { + if (![hierarchyFile isKindOfClass:[LookinHierarchyFile class]]) { + return LookinErr_Inner; + } + + if (hierarchyFile.serverVersion < LOOKIN_SUPPORTED_SERVER_MIN) { + // 文件版本太旧 + // 如果不存在 serverVersion 这个字段,说明版本是 6 + int fileVersion = hierarchyFile.serverVersion ? : 6; + NSString *detail = [NSString stringWithFormat:NSLocalizedString(@"The document was created by a Lookin app with too old version. Current Lookin app version is %@, but the document version is %@.", nil), @(LOOKIN_CLIENT_VERSION), @(fileVersion)]; + return [NSError errorWithDomain:LookinErrorDomain code:LookinErrCode_ServerVersionTooLow userInfo:@{NSLocalizedDescriptionKey:NSLocalizedString(@"Failed to open the document.", nil), NSLocalizedRecoverySuggestionErrorKey:detail}]; + } + + if (hierarchyFile.serverVersion > LOOKIN_SUPPORTED_SERVER_MAX) { + // 文件版本太新 + NSString *detail = [NSString stringWithFormat:NSLocalizedString(@"Current Lookin app is too old to open this document. Current Lookin app version is %@, but the document version is %@.", nil), @(LOOKIN_CLIENT_VERSION), @(hierarchyFile.serverVersion)]; + return [NSError errorWithDomain:LookinErrorDomain code:LookinErrCode_ServerVersionTooHigh userInfo:@{NSLocalizedDescriptionKey:NSLocalizedString(@"Failed to open the document.", nil), NSLocalizedRecoverySuggestionErrorKey:detail}]; + } + + return nil; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinHierarchyInfo.h b/Pods/LookinServer/Src/Main/Shared/LookinHierarchyInfo.h new file mode 100644 index 0000000..048d2f6 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinHierarchyInfo.h @@ -0,0 +1,47 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinDisplayInfo.h +// WeRead +// +// Created by Li Kai on 2018/10/22. +// Copyright © 2018年 tencent. All rights reserved. +// + + + +#import "LookinDefines.h" +#import "TargetConditionals.h" +#if TARGET_OS_IPHONE +#import +#elif TARGET_OS_MAC +#import +#endif + +@class LookinDisplayItem, LookinAttributesGroup, LookinAppInfo; + +@interface LookinHierarchyInfo : NSObject + +#if TARGET_OS_IPHONE + +/// version 可能为 nil,此时说明 Client 版本号 < 1.0.4 ++ (instancetype)staticInfoWithLookinVersion:(NSString *)version; + ++ (instancetype)exportedInfo; + +#endif + +/// 这里其实就是顶端的那几个 UIWindow +@property(nonatomic, copy) NSArray *displayItems; + +@property(nonatomic, copy) NSDictionary *colorAlias; + +@property(nonatomic, copy) NSArray *collapsedClassList; + +@property(nonatomic, strong) LookinAppInfo *appInfo; + +@property(nonatomic, assign) int serverVersion; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinHierarchyInfo.m b/Pods/LookinServer/Src/Main/Shared/LookinHierarchyInfo.m new file mode 100644 index 0000000..1048260 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinHierarchyInfo.m @@ -0,0 +1,106 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinDisplayInfo.m +// WeRead +// +// Created by Li Kai on 2018/10/22. +// Copyright © 2018年 tencent. All rights reserved. +// + +#import +#import "LookinHierarchyInfo.h" +#import "LookinAttributesGroup.h" +#import "LookinDisplayItem.h" +#import "LookinAppInfo.h" +#import "NSArray+Lookin.h" +#import "NSString+Lookin.h" + +#if TARGET_OS_IPHONE +#import "LKS_HierarchyDisplayItemsMaker.h" +#import "LKSConfigManager.h" +#import "LKS_CustomAttrSetterManager.h" +#endif + +@implementation LookinHierarchyInfo + +#if TARGET_OS_IPHONE + ++ (instancetype)staticInfoWithLookinVersion:(NSString *)version { + BOOL readCustomInfo = NO; + // Client 1.0.4 开始支持 customInfo + if (version && [version lookin_numbericOSVersion] >= 10004) { + readCustomInfo = YES; + } + + [[LKS_CustomAttrSetterManager sharedInstance] removeAll]; + + LookinHierarchyInfo *info = [LookinHierarchyInfo new]; + info.serverVersion = LOOKIN_SERVER_VERSION; + info.displayItems = [LKS_HierarchyDisplayItemsMaker itemsWithScreenshots:NO attrList:NO lowImageQuality:NO readCustomInfo:readCustomInfo saveCustomSetter:YES]; + info.appInfo = [LookinAppInfo currentInfoWithScreenshot:NO icon:YES localIdentifiers:nil]; + info.collapsedClassList = [LKSConfigManager collapsedClassList]; + info.colorAlias = [LKSConfigManager colorAlias]; + return info; +} + ++ (instancetype)exportedInfo { + LookinHierarchyInfo *info = [LookinHierarchyInfo new]; + info.serverVersion = LOOKIN_SERVER_VERSION; + info.displayItems = [LKS_HierarchyDisplayItemsMaker itemsWithScreenshots:YES attrList:YES lowImageQuality:YES readCustomInfo:YES saveCustomSetter:NO]; + info.appInfo = [LookinAppInfo currentInfoWithScreenshot:NO icon:YES localIdentifiers:nil]; + info.collapsedClassList = [LKSConfigManager collapsedClassList]; + info.colorAlias = [LKSConfigManager colorAlias]; + return info; +} + +#endif + +#pragma mark - + +static NSString * const LookinHierarchyInfoCodingKey_DisplayItems = @"1"; +static NSString * const LookinHierarchyInfoCodingKey_AppInfo = @"2"; +static NSString * const LookinHierarchyInfoCodingKey_ColorAlias = @"3"; +static NSString * const LookinHierarchyInfoCodingKey_CollapsedClassList = @"4"; + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:self.displayItems forKey:LookinHierarchyInfoCodingKey_DisplayItems]; + [aCoder encodeObject:self.colorAlias forKey:LookinHierarchyInfoCodingKey_ColorAlias]; + [aCoder encodeObject:self.collapsedClassList forKey:LookinHierarchyInfoCodingKey_CollapsedClassList]; + [aCoder encodeObject:self.appInfo forKey:LookinHierarchyInfoCodingKey_AppInfo]; + [aCoder encodeInt:self.serverVersion forKey:@"serverVersion"]; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if (self = [super init]) { + self.displayItems = [aDecoder decodeObjectForKey:LookinHierarchyInfoCodingKey_DisplayItems]; + self.colorAlias = [aDecoder decodeObjectForKey:LookinHierarchyInfoCodingKey_ColorAlias]; + self.collapsedClassList = [aDecoder decodeObjectForKey:LookinHierarchyInfoCodingKey_CollapsedClassList]; + self.appInfo = [aDecoder decodeObjectForKey:LookinHierarchyInfoCodingKey_AppInfo]; + self.serverVersion = [aDecoder decodeIntForKey:@"serverVersion"]; + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +#pragma mark - + +- (id)copyWithZone:(NSZone *)zone { + LookinHierarchyInfo *newAppInfo = [[LookinHierarchyInfo allocWithZone:zone] init]; + newAppInfo.serverVersion = self.serverVersion; + newAppInfo.appInfo = self.appInfo.copy; + newAppInfo.collapsedClassList = self.collapsedClassList; + newAppInfo.colorAlias = self.colorAlias; + newAppInfo.displayItems = [self.displayItems lookin_map:^id(NSUInteger idx, LookinDisplayItem *oldItem) { + return oldItem.copy; + }]; + + return newAppInfo; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinObject.h b/Pods/LookinServer/Src/Main/Shared/LookinObject.h new file mode 100644 index 0000000..285749d --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinObject.h @@ -0,0 +1,42 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinObject.h +// Lookin +// +// Created by Li Kai on 2019/4/20. +// https://lookin.work +// + + + +#import + +@class LookinObjectIvar, LookinIvarTrace; + +@interface LookinObject : NSObject + +#if TARGET_OS_IPHONE ++ (instancetype)instanceWithObject:(NSObject *)object; +#endif + +@property(nonatomic, assign) unsigned long oid; + +@property(nonatomic, copy) NSString *memoryAddress; + +/** + 比如有一个 UILabel 对象,则它的 classChainList 为 @[@"UILabel", @"UIView", @"UIResponder", @"NSObject"],而它的 ivarList 长度为 4,idx 从小到大分别是 UILabel 层级的 ivars, UIView 层级的 ivars..... + */ +@property(nonatomic, copy) NSArray *classChainList; + +@property(nonatomic, copy) NSString *specialTrace; + +@property(nonatomic, copy) NSArray *ivarTraces; + +/// 没有 demangle,会包含 Swift Module Name +/// 在 Lookin 的展示中,绝大多数情况下应该使用 lk_demangledSwiftName +- (NSString *)rawClassName; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinObject.m b/Pods/LookinServer/Src/Main/Shared/LookinObject.m new file mode 100644 index 0000000..89d8fed --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinObject.m @@ -0,0 +1,82 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinObject.m +// Lookin +// +// Created by Li Kai on 2019/4/20. +// https://lookin.work +// + +#import "LookinObject.h" +#import "LookinIvarTrace.h" +#import "NSArray+Lookin.h" +#import "NSString+Lookin.h" + +#if TARGET_OS_IPHONE +#import "NSObject+LookinServer.h" +#endif + +@implementation LookinObject + +#if TARGET_OS_IPHONE ++ (instancetype)instanceWithObject:(NSObject *)object { + LookinObject *lookinObj = [LookinObject new]; + lookinObj.oid = [object lks_registerOid]; + + lookinObj.memoryAddress = [NSString stringWithFormat:@"%p", object]; + lookinObj.classChainList = [object lks_classChainList]; + + lookinObj.specialTrace = object.lks_specialTrace; + lookinObj.ivarTraces = object.lks_ivarTraces; + + return lookinObj; +} +#endif + +#pragma mark - + +- (id)copyWithZone:(NSZone *)zone { + LookinObject *newObject = [[LookinObject allocWithZone:zone] init]; + newObject.oid = self.oid; + newObject.memoryAddress = self.memoryAddress; + newObject.classChainList = self.classChainList; + newObject.specialTrace = self.specialTrace; + newObject.ivarTraces = [self.ivarTraces lookin_map:^id(NSUInteger idx, LookinIvarTrace *value) { + return value.copy; + }]; + return newObject; +} + +#pragma mark - + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:@(self.oid) forKey:@"oid"]; + [aCoder encodeObject:self.memoryAddress forKey:@"memoryAddress"]; + [aCoder encodeObject:self.classChainList forKey:@"classChainList"]; + [aCoder encodeObject:self.specialTrace forKey:@"specialTrace"]; + [aCoder encodeObject:self.ivarTraces forKey:@"ivarTraces"]; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if (self = [super init]) { + self.oid = [(NSNumber *)[aDecoder decodeObjectForKey:@"oid"] unsignedLongValue]; + self.memoryAddress = [aDecoder decodeObjectForKey:@"memoryAddress"]; + self.classChainList = [aDecoder decodeObjectForKey:@"classChainList"]; + self.specialTrace = [aDecoder decodeObjectForKey:@"specialTrace"]; + self.ivarTraces = [aDecoder decodeObjectForKey:@"ivarTraces"]; + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (NSString *)rawClassName { + return self.classChainList.firstObject; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinStaticAsyncUpdateTask.h b/Pods/LookinServer/Src/Main/Shared/LookinStaticAsyncUpdateTask.h new file mode 100644 index 0000000..85e1925 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinStaticAsyncUpdateTask.h @@ -0,0 +1,67 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinStaticAsyncUpdateTask.h +// Lookin +// +// Created by Li Kai on 2019/6/21. +// https://lookin.work +// + + + +#import "LookinDefines.h" + +typedef NS_ENUM(NSInteger, LookinStaticAsyncUpdateTaskType) { + LookinStaticAsyncUpdateTaskTypeNoScreenshot, + LookinStaticAsyncUpdateTaskTypeSoloScreenshot, + LookinStaticAsyncUpdateTaskTypeGroupScreenshot +}; + +typedef NS_ENUM(NSInteger, LookinDetailUpdateTaskAttrRequest) { + /// 由 Server 端自己决定:同一批 task 里,server 端会保证同一个 layer 只会构造一次 attr + /// 在 Lookin turbo 模式下,由于同一个 layer 的 task 可能位于不同批的 task 里,因此这会导致冗余的 attr 构造行为、浪费一定时间 + LookinDetailUpdateTaskAttrRequest_Automatic, + /// 需要返回 attr + LookinDetailUpdateTaskAttrRequest_Need, + /// 不需要返回 attr + LookinDetailUpdateTaskAttrRequest_NotNeed +}; + +/// 业务重写了 isEqual +@interface LookinStaticAsyncUpdateTask : NSObject + +@property(nonatomic, assign) unsigned long oid; + +@property(nonatomic, assign) LookinStaticAsyncUpdateTaskType taskType; + +/// 是否需要返回 attr 数据,默认为 Automatic +/// Client 1.0.7 & Server 1.2.7 开始支持这个参数 +@property(nonatomic, assign) LookinDetailUpdateTaskAttrRequest attrRequest; + +/// 如果置为 YES,则 server 侧会返回这些基础信息:frameValue, boundsValue, hiddenValue, alphaValue +/// 默认为 NO +/// Client 1.0.7 & Server 1.2.7 开始支持这个参数 +@property(nonatomic, assign) BOOL needBasisVisualInfo; + +/// 如果置为 YES,则 server 侧会返回 subitems +/// 默认为 NO +/// Client 1.0.7 & Server 1.2.7 开始支持这个参数 +@property(nonatomic, assign) BOOL needSubitems; + +/// Client 1.0.4 开始加入这个参数 +@property(nonatomic, copy) NSString *clientReadableVersion; + +#pragma mark - Non Coding + +@property(nonatomic, assign) CGSize frameSize; + +@end + +@interface LookinStaticAsyncUpdateTasksPackage : NSObject + +@property(nonatomic, copy) NSArray *tasks; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinStaticAsyncUpdateTask.m b/Pods/LookinServer/Src/Main/Shared/LookinStaticAsyncUpdateTask.m new file mode 100644 index 0000000..aef73a1 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinStaticAsyncUpdateTask.m @@ -0,0 +1,105 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinStaticAsyncUpdateTask.m +// Lookin +// +// Created by Li Kai on 2019/6/21. +// https://lookin.work +// + + + +#import "LookinStaticAsyncUpdateTask.h" + +@implementation LookinStaticAsyncUpdateTask + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:@(self.oid) forKey:@"oid"]; + [aCoder encodeInteger:self.taskType forKey:@"taskType"]; + [aCoder encodeObject:self.clientReadableVersion forKey:@"clientReadableVersion"]; + [aCoder encodeInteger:self.attrRequest forKey:@"attrRequest"]; + [aCoder encodeBool:self.needBasisVisualInfo forKey:@"needBasisVisualInfo"]; + [aCoder encodeBool:self.needSubitems forKey:@"needSubitems"]; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if (self = [super init]) { + self.oid = [[aDecoder decodeObjectForKey:@"oid"] unsignedLongValue]; + self.taskType = [aDecoder decodeIntegerForKey:@"taskType"]; + self.clientReadableVersion = [aDecoder decodeObjectForKey:@"clientReadableVersion"]; + if ([aDecoder containsValueForKey:@"attrRequest"]) { + NSInteger value = [aDecoder decodeIntegerForKey:@"attrRequest"]; + if (value >= LookinDetailUpdateTaskAttrRequest_Automatic && value <= LookinDetailUpdateTaskAttrRequest_NotNeed) { + self.attrRequest = value; + } else { + self.attrRequest = LookinDetailUpdateTaskAttrRequest_Automatic; + } + } else { + self.attrRequest = LookinDetailUpdateTaskAttrRequest_Automatic; + } + + if ([aDecoder containsValueForKey:@"needBasisVisualInfo"]) { + self.needBasisVisualInfo = [aDecoder decodeBoolForKey:@"needBasisVisualInfo"]; + } else { + self.needBasisVisualInfo = NO; + } + + if ([aDecoder containsValueForKey:@"needSubitems"]) { + self.needSubitems = [aDecoder decodeBoolForKey:@"needSubitems"]; + } else { + self.needSubitems = NO; + } + + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (NSUInteger)hash { + return self.oid ^ self.taskType ^ self.attrRequest ^ self.needBasisVisualInfo ^ self.needSubitems; +} + +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[LookinStaticAsyncUpdateTask class]]) { + return NO; + } + LookinStaticAsyncUpdateTask *targetTask = object; + if (self.oid == targetTask.oid + && self.taskType == targetTask.taskType + && self.attrRequest == targetTask.attrRequest + && self.needBasisVisualInfo == targetTask.needBasisVisualInfo + && self.needSubitems == targetTask.needSubitems) { + return YES; + } + return NO; +} + +@end + +@implementation LookinStaticAsyncUpdateTasksPackage + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:self.tasks forKey:@"tasks"]; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if (self = [super init]) { + self.tasks = [aDecoder decodeObjectForKey:@"tasks"]; + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinTuple.h b/Pods/LookinServer/Src/Main/Shared/LookinTuple.h new file mode 100644 index 0000000..296a4b8 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinTuple.h @@ -0,0 +1,31 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinTuples.h +// Lookin +// +// Created by Li Kai on 2019/8/14. +// https://lookin.work +// + + + +#import + +@interface LookinTwoTuple : NSObject + +@property(nonatomic, strong) NSObject *first; +@property(nonatomic, strong) NSObject *second; + +@end + +@interface LookinStringTwoTuple : NSObject + ++ (instancetype)tupleWithFirst:(NSString *)firstString second:(NSString *)secondString; + +@property(nonatomic, copy) NSString *first; +@property(nonatomic, copy) NSString *second; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinTuple.m b/Pods/LookinServer/Src/Main/Shared/LookinTuple.m new file mode 100644 index 0000000..b84a960 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinTuple.m @@ -0,0 +1,93 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinTuples.m +// Lookin +// +// Created by Li Kai on 2019/8/14. +// https://lookin.work +// + + + +#import "LookinTuple.h" + +@implementation LookinTwoTuple + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:self.first forKey:@"first"]; + [aCoder encodeObject:self.second forKey:@"second"]; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if (self = [super init]) { + self.first = [aDecoder decodeObjectForKey:@"first"]; + self.second = [aDecoder decodeObjectForKey:@"second"]; + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (NSUInteger)hash { + return self.first.hash ^ self.second.hash; +} + +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[LookinTwoTuple class]]) { + return NO; + } + LookinTwoTuple *comparedObj = object; + if ([self.first isEqual:comparedObj.first] && [self.second isEqual:comparedObj.second]) { + return YES; + } + return NO; +} + +@end + +@implementation LookinStringTwoTuple + ++ (instancetype)tupleWithFirst:(NSString *)firstString second:(NSString *)secondString { + LookinStringTwoTuple *tuple = [LookinStringTwoTuple new]; + tuple.first = firstString; + tuple.second = secondString; + return tuple; +} + +#pragma mark - + +- (id)copyWithZone:(NSZone *)zone { + LookinStringTwoTuple *newTuple = [[LookinStringTwoTuple allocWithZone:zone] init]; + newTuple.first = self.first; + newTuple.second = self.second; + return newTuple; +} + +#pragma mark - + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:self.first forKey:@"first"]; + [aCoder encodeObject:self.second forKey:@"second"]; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if (self = [super init]) { + self.first = [aDecoder decodeObjectForKey:@"first"]; + self.second = [aDecoder decodeObjectForKey:@"second"]; + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinWeakContainer.h b/Pods/LookinServer/Src/Main/Shared/LookinWeakContainer.h new file mode 100644 index 0000000..af7b2ff --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinWeakContainer.h @@ -0,0 +1,23 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinWeakContainer.h +// Lookin +// +// Created by Li Kai on 2019/8/14. +// https://lookin.work +// + + + +#import + +@interface LookinWeakContainer : NSObject + ++ (instancetype)containerWithObject:(id)object; + +@property (nonatomic, weak) id object; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/LookinWeakContainer.m b/Pods/LookinServer/Src/Main/Shared/LookinWeakContainer.m new file mode 100644 index 0000000..ff9d2aa --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/LookinWeakContainer.m @@ -0,0 +1,43 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// LookinWeakContainer.m +// Lookin +// +// Created by Li Kai on 2019/8/14. +// https://lookin.work +// + + + +#import "LookinWeakContainer.h" + +@implementation LookinWeakContainer + ++ (instancetype)containerWithObject:(id)object { + LookinWeakContainer *container = [LookinWeakContainer new]; + container.object = object; + return container; +} + +- (NSUInteger)hash { + return [self.object hash]; +} + +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[LookinWeakContainer class]]) { + return NO; + } + LookinWeakContainer *comparedObj = object; + if ([self.object isEqual:comparedObj.object]) { + return YES; + } + return NO; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/Peertalk/Lookin_PTChannel.h b/Pods/LookinServer/Src/Main/Shared/Peertalk/Lookin_PTChannel.h new file mode 100644 index 0000000..498a604 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/Peertalk/Lookin_PTChannel.h @@ -0,0 +1,136 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + + + +// +// Represents a communication channel between two endpoints talking the same +// Lookin_PTProtocol. +// +#import +#import +#import +#import + +#import "Lookin_PTProtocol.h" +#import "Lookin_PTUSBHub.h" + +@class Lookin_PTData, Lookin_PTAddress; +@protocol Lookin_PTChannelDelegate; + +@interface Lookin_PTChannel : NSObject + +// Delegate +@property (strong) id delegate; + +// Communication protocol. Must not be nil. +@property Lookin_PTProtocol *protocol; + +// YES if this channel is a listening server +@property (readonly) BOOL isListening; + +// YES if this channel is a connected peer +@property (readonly) BOOL isConnected; + +// Arbitrary attachment. Note that if you set this, the object will grow by +// 8 bytes (64 bits). +@property (strong) id userInfo; + +@property(nonatomic, assign) int uniqueID; +@property(nonatomic, assign) NSInteger targetPort; +- (NSString *)debugTag; + +// Create a new channel using the shared Lookin_PTProtocol for the current dispatch +// queue, with *delegate*. ++ (Lookin_PTChannel*)channelWithDelegate:(id)delegate; + + +// Initialize a new frame channel, configuring it to use the calling queue's +// protocol instance (as returned by [Lookin_PTProtocol sharedProtocolForQueue: +// dispatch_get_current_queue()]) +- (id)init; + +// Initialize a new frame channel with a specific protocol. +- (id)initWithProtocol:(Lookin_PTProtocol*)protocol; + +// Initialize a new frame channel with a specific protocol and delegate. +- (id)initWithProtocol:(Lookin_PTProtocol*)protocol delegate:(id)delegate; + + +// Connect to a TCP port on a device connected over USB +- (void)connectToPort:(int)port overUSBHub:(Lookin_PTUSBHub*)usbHub deviceID:(NSNumber*)deviceID callback:(void(^)(NSError *error))callback; + +// Connect to a TCP port at IPv4 address. Provided port must NOT be in network +// byte order. Provided in_addr_t must NOT be in network byte order. A value returned +// from inet_aton() will be in network byte order. You can use a value of inet_aton() +// as the address parameter here, but you must flip the byte order before passing the +// in_addr_t to this function. +- (void)connectToPort:(in_port_t)port IPv4Address:(in_addr_t)address callback:(void(^)(NSError *error, Lookin_PTAddress *address))callback; + +// Listen for connections on port and address, effectively starting a socket +// server. Provided port must NOT be in network byte order. Provided in_addr_t +// must NOT be in network byte order. +// For this to make sense, you should provide a onAccept block handler +// or a delegate implementing ioFrameChannel:didAcceptConnection:. +- (void)listenOnPort:(in_port_t)port IPv4Address:(in_addr_t)address callback:(void(^)(NSError *error))callback; + +// Send a frame with an optional payload and optional callback. +// If *callback* is not NULL, the block is invoked when either an error occured +// or when the frame (and payload, if any) has been completely sent. +- (void)sendFrameOfType:(uint32_t)frameType tag:(uint32_t)tag withPayload:(dispatch_data_t)payload callback:(void(^)(NSError *error))callback; + +// Lower-level method to assign a connected dispatch IO channel to this channel +- (BOOL)startReadingFromConnectedChannel:(dispatch_io_t)channel error:(__autoreleasing NSError**)error; + +// Close the channel, preventing further reading and writing. Any ongoing and +// queued reads and writes will be aborted. +- (void)close; + +// "graceful" close -- any ongoing and queued reads and writes will complete +// before the channel ends. +- (void)cancel; + +@end + + +// Wraps a mapped dispatch_data_t object. The memory pointed to by *data* is +// valid until *dispatchData* is deallocated (normally when the receiver is +// deallocated). +@interface Lookin_PTData : NSObject +@property (readonly) dispatch_data_t dispatchData; +@property (readonly) void *data; +@property (readonly) size_t length; +@end + + +// Represents a peer's address +@interface Lookin_PTAddress : NSObject +// For network addresses, this is the IP address in textual format +@property (readonly) NSString *name; +// For network addresses, this is the port number. Otherwise 0 (zero). +@property (readonly) NSInteger port; +@end + + +// Protocol for Lookin_PTChannel delegates +@protocol Lookin_PTChannelDelegate + +@required +// Invoked when a new frame has arrived on a channel. +- (void)ioFrameChannel:(Lookin_PTChannel*)channel didReceiveFrameOfType:(uint32_t)type tag:(uint32_t)tag payload:(Lookin_PTData*)payload; + +@optional +// Invoked to accept an incoming frame on a channel. Reply NO ignore the +// incoming frame. If not implemented by the delegate, all frames are accepted. +- (BOOL)ioFrameChannel:(Lookin_PTChannel*)channel shouldAcceptFrameOfType:(uint32_t)type tag:(uint32_t)tag payloadSize:(uint32_t)payloadSize; + +// Invoked when the channel closed. If it closed because of an error, *error* is +// a non-nil NSError object. +- (void)ioFrameChannel:(Lookin_PTChannel*)channel didEndWithError:(NSError*)error; + +// For listening channels, this method is invoked when a new connection has been +// accepted. +- (void)ioFrameChannel:(Lookin_PTChannel*)channel didAcceptConnection:(Lookin_PTChannel*)otherChannel fromAddress:(Lookin_PTAddress*)address; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/Peertalk/Lookin_PTChannel.m b/Pods/LookinServer/Src/Main/Shared/Peertalk/Lookin_PTChannel.m new file mode 100644 index 0000000..bb8529e --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/Peertalk/Lookin_PTChannel.m @@ -0,0 +1,675 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +#import "Lookin_PTChannel.h" +#import "Lookin_PTPrivate.h" +#include +#include +#include +#include +#include +#import + +// Read member of sockaddr_in without knowing the family +#define PT_SOCKADDR_ACCESS(ss, member4, member6) \ + (((ss)->ss_family == AF_INET) ? ( \ + ((const struct sockaddr_in *)(ss))->member4 \ + ) : ( \ + ((const struct sockaddr_in6 *)(ss))->member6 \ + )) + +// Connection state (storage: uint8_t) +#define kConnStateNone 0 +#define kConnStateConnecting 1 +#define kConnStateConnected 2 +#define kConnStateListening 3 + +// Delegate support optimization (storage: uint8_t) +#define kDelegateFlagImplements_ioFrameChannel_shouldAcceptFrameOfType_tag_payloadSize 1 +#define kDelegateFlagImplements_ioFrameChannel_didEndWithError 2 +#define kDelegateFlagImplements_ioFrameChannel_didAcceptConnection_fromAddress 4 + + +static int ChannelInstanceCount = 0; +static int ChannelUniqueID = 0; + +#pragma mark - +// Note: We are careful about the size of this struct as each connected peer +// implies one allocation of this struct. +@interface Lookin_PTChannel () { + dispatch_io_t dispatchObj_channel_; + dispatch_source_t dispatchObj_source_; + NSError *endError_; // 64 bit +@public // here be hacks + id delegate_; // 64 bit + uint8_t delegateFlags_; // 8 bit +@private + uint8_t connState_; // 8 bit + //char padding_[6]; // 48 bit -- only if allocation speed is important +} +- (id)initWithProtocol:(Lookin_PTProtocol*)protocol delegate:(id)delegate; +- (BOOL)acceptIncomingConnection:(dispatch_fd_t)serverSocketFD; +@end +static const uint8_t kUserInfoKey; + +#pragma mark - +@interface Lookin_PTData () +- (id)initWithMappedDispatchData:(dispatch_data_t)mappedContiguousData data:(void*)data length:(size_t)length; +@end + +#pragma mark - +@interface Lookin_PTAddress () { + struct sockaddr_storage sockaddr_; +} +- (id)initWithSockaddr:(const struct sockaddr_storage*)addr; +@end + +#pragma mark - +@implementation Lookin_PTChannel + +@synthesize protocol = protocol_; + + ++ (Lookin_PTChannel*)channelWithDelegate:(id)delegate { + return [[Lookin_PTChannel alloc] initWithProtocol:[Lookin_PTProtocol sharedProtocolForQueue:dispatch_get_main_queue()] delegate:delegate]; +} + + +- (id)initWithProtocol:(Lookin_PTProtocol*)protocol delegate:(id)delegate { + if (!(self = [super init])) return nil; + protocol_ = protocol; + self.delegate = delegate; + + [self didInit]; + + return self; +} + + +- (id)initWithProtocol:(Lookin_PTProtocol*)protocol { + if (!(self = [super init])) return nil; + protocol_ = protocol; + + [self didInit]; + + return self; +} + + +- (id)init { + [self didInit]; + + return [self initWithProtocol:[Lookin_PTProtocol sharedProtocolForQueue:dispatch_get_main_queue()]]; +} + +- (void)didInit { + ChannelUniqueID++; + ChannelInstanceCount++; + self.uniqueID = ChannelUniqueID; +// NSLog(@"LookinServer - Init channel(ID: %@). Total count: %@", @(self.uniqueID), @(ChannelInstanceCount)); +} + +- (void)dealloc { + ChannelInstanceCount--; +// NSLog(@"LookinServer - Dealloc channel%@. Still lives count: %@", self.debugTag, @(ChannelInstanceCount)); +#if PT_DISPATCH_RETAIN_RELEASE + if (dispatchObj_channel_) dispatch_release(dispatchObj_channel_); + else if (dispatchObj_source_) dispatch_release(dispatchObj_source_); +#endif +} + + +- (BOOL)isConnected { + return connState_ == kConnStateConnecting || connState_ == kConnStateConnected; +} + + +- (BOOL)isListening { + return connState_ == kConnStateListening; +} + + +- (id)userInfo { + return objc_getAssociatedObject(self, (void*)&kUserInfoKey); +} + +- (void)setUserInfo:(id)userInfo { + objc_setAssociatedObject(self, (const void*)&kUserInfoKey, userInfo, OBJC_ASSOCIATION_RETAIN); +} + + +- (void)setConnState:(char)connState { + connState_ = connState; +} + + +- (void)setDispatchChannel:(dispatch_io_t)channel { + assert(connState_ == kConnStateConnecting || connState_ == kConnStateConnected || connState_ == kConnStateNone); + dispatch_io_t prevChannel = dispatchObj_channel_; + if (prevChannel != channel) { + dispatchObj_channel_ = channel; +#if PT_DISPATCH_RETAIN_RELEASE + if (dispatchObj_channel_) dispatch_retain(dispatchObj_channel_); + if (prevChannel) dispatch_release(prevChannel); +#endif + if (!dispatchObj_channel_ && !dispatchObj_source_) { + connState_ = kConnStateNone; + } + } +} + + +- (void)setDispatchSource:(dispatch_source_t)source { + assert(connState_ == kConnStateListening || connState_ == kConnStateNone); + dispatch_source_t prevSource = dispatchObj_source_; + if (prevSource != source) { + dispatchObj_source_ = source; +#if PT_DISPATCH_RETAIN_RELEASE + if (dispatchObj_source_) dispatch_retain(dispatchObj_source_); + if (prevSource) dispatch_release(prevSource); +#endif + if (!dispatchObj_channel_ && !dispatchObj_source_) { + connState_ = kConnStateNone; + } + } +} + + +- (id)delegate { + return delegate_; +} + + +- (void)setDelegate:(id)delegate { + delegate_ = delegate; + delegateFlags_ = 0; + if (!delegate_) { + return; + } + + if ([delegate respondsToSelector:@selector(ioFrameChannel:shouldAcceptFrameOfType:tag:payloadSize:)]) { + delegateFlags_ |= kDelegateFlagImplements_ioFrameChannel_shouldAcceptFrameOfType_tag_payloadSize; + } + + if (delegate_ && [delegate respondsToSelector:@selector(ioFrameChannel:didEndWithError:)]) { + delegateFlags_ |= kDelegateFlagImplements_ioFrameChannel_didEndWithError; + } + + if (delegate_ && [delegate respondsToSelector:@selector(ioFrameChannel:didAcceptConnection:fromAddress:)]) { + delegateFlags_ |= kDelegateFlagImplements_ioFrameChannel_didAcceptConnection_fromAddress; + } +} + +- (NSString *)debugTag { + NSString *state = @""; + if (connState_ == kConnStateNone) { + state = @"None"; + } else if (connState_ == kConnStateConnecting) { + state = @"Connecting"; + } else if (connState_ == kConnStateConnected) { + state = @"Connected"; + } else if (connState_ == kConnStateListening) { + state = @"Listening"; + } else { + state = @"Undefined"; + } + return [NSString stringWithFormat:@"[%@-%@,%@]", @(self.uniqueID), @(self.targetPort), state]; +} + + +//- (void)setFileDescriptor:(dispatch_fd_t)fd { +// [self setDispatchChannel:dispatch_io_create(DISPATCH_IO_STREAM, fd, protocol_.queue, ^(int error) { +// close(fd); +// })]; +//} + + +#pragma mark - Connecting + + +- (void)connectToPort:(int)port overUSBHub:(Lookin_PTUSBHub*)usbHub deviceID:(NSNumber*)deviceID callback:(void(^)(NSError *error))callback { + assert(protocol_ != NULL); + if (connState_ != kConnStateNone) { + if (callback) callback([NSError errorWithDomain:NSPOSIXErrorDomain code:EPERM userInfo:nil]); + return; + } + connState_ = kConnStateConnecting; + [usbHub connectToDevice:deviceID port:port onStart:^(NSError *err, dispatch_io_t dispatchChannel) { + NSError *error = err; + if (!error) { + [self startReadingFromConnectedChannel:dispatchChannel error:&error]; + } else { + self->connState_ = kConnStateNone; + } + if (callback) callback(error); + } onEnd:^(NSError *error) { + if (self->delegateFlags_ & kDelegateFlagImplements_ioFrameChannel_didEndWithError) { + [self->delegate_ ioFrameChannel:self didEndWithError:error]; + } + self->endError_ = nil; + }]; +} + + +- (void)connectToPort:(in_port_t)port IPv4Address:(in_addr_t)address callback:(void(^)(NSError *error, Lookin_PTAddress *address))callback { + assert(protocol_ != NULL); + if (connState_ != kConnStateNone) { + if (callback) callback([NSError errorWithDomain:NSPOSIXErrorDomain code:EPERM userInfo:nil], nil); + return; + } + connState_ = kConnStateConnecting; + + int error = 0; + + // Create socket + dispatch_fd_t fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd == -1) { + perror("socket(AF_INET, SOCK_STREAM, 0) failed"); + error = errno; + if (callback) callback([[NSError alloc] initWithDomain:NSPOSIXErrorDomain code:errno userInfo:nil], nil); + return; + } + + // Connect socket + struct sockaddr_in addr; + bzero((char *)&addr, sizeof(addr)); + + addr.sin_len = sizeof(addr); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + //addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + //addr.sin_addr.s_addr = htonl(INADDR_ANY); + addr.sin_addr.s_addr = htonl(address); + + // prevent SIGPIPE + int on = 1; + setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof(on)); + + // int socket, const struct sockaddr *address, socklen_t address_len + if (connect(fd, (const struct sockaddr *)&addr, addr.sin_len) == -1) { + //perror("connect"); + error = errno; + close(fd); + if (callback) callback([[NSError alloc] initWithDomain:NSPOSIXErrorDomain code:error userInfo:nil], nil); + return; + } + + // get actual address + //if (getsockname(fd, (struct sockaddr*)&addr, (socklen_t*)&addr.sin_len) == -1) { + // error = errno; + // close(fd); + // if (callback) callback([[NSError alloc] initWithDomain:NSPOSIXErrorDomain code:error userInfo:nil], nil); + // return; + //} + + dispatch_io_t dispatchChannel = dispatch_io_create(DISPATCH_IO_STREAM, fd, protocol_.queue, ^(int error) { + close(fd); + if (self->delegateFlags_ & kDelegateFlagImplements_ioFrameChannel_didEndWithError) { + NSError *err = error == 0 ? self->endError_ : [[NSError alloc] initWithDomain:NSPOSIXErrorDomain code:error userInfo:nil]; + [self->delegate_ ioFrameChannel:self didEndWithError:err]; + self->endError_ = nil; + } + }); + + if (!dispatchChannel) { + close(fd); + if (callback) callback([[NSError alloc] initWithDomain:@"PTError" code:0 userInfo:nil], nil); + return; + } + + // Success + NSError *err = nil; + Lookin_PTAddress *ptAddr = [[Lookin_PTAddress alloc] initWithSockaddr:(struct sockaddr_storage*)&addr]; + [self startReadingFromConnectedChannel:dispatchChannel error:&err]; + if (callback) callback(err, ptAddr); +} + + +#pragma mark - Listening and serving + + +- (void)listenOnPort:(in_port_t)port IPv4Address:(in_addr_t)address callback:(void(^)(NSError *error))callback { + assert(dispatchObj_source_ == nil); + + // Create socket + dispatch_fd_t fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd == -1) { + if (callback) callback([NSError errorWithDomain:NSPOSIXErrorDomain code:errno userInfo:nil]); + return; + } + + // Connect socket + struct sockaddr_in addr; + bzero((char *)&addr, sizeof(addr)); + + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + //addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + //addr.sin_addr.s_addr = htonl(INADDR_ANY); + addr.sin_addr.s_addr = htonl(address); + + socklen_t socklen = sizeof(addr); + + int on = 1; + + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) { + close(fd); + if (callback) callback([NSError errorWithDomain:NSPOSIXErrorDomain code:errno userInfo:nil]); + return; + } + + if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) { + close(fd); + if (callback) callback([NSError errorWithDomain:NSPOSIXErrorDomain code:errno userInfo:nil]); + return; + } + + if (bind(fd, (struct sockaddr*)&addr, socklen) != 0) { + close(fd); + if (callback) callback([NSError errorWithDomain:NSPOSIXErrorDomain code:errno userInfo:nil]); + return; + } + + if (listen(fd, 512) != 0) { + close(fd); + if (callback) callback([NSError errorWithDomain:NSPOSIXErrorDomain code:errno userInfo:nil]); + return; + } + + [self setDispatchSource:dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, fd, 0, protocol_.queue)]; + + dispatch_source_set_event_handler(dispatchObj_source_, ^{ + unsigned long nconns = dispatch_source_get_data(self->dispatchObj_source_); + while ([self acceptIncomingConnection:fd] && --nconns); + }); + + dispatch_source_set_cancel_handler(dispatchObj_source_, ^{ + // Captures *self*, effectively holding a reference to *self* until cancelled. + self->dispatchObj_source_ = nil; + close(fd); + if (self->delegateFlags_ & kDelegateFlagImplements_ioFrameChannel_didEndWithError) { + [self->delegate_ ioFrameChannel:self didEndWithError:self->endError_]; + self->endError_ = nil; + } + }); + + dispatch_resume(dispatchObj_source_); + //NSLog(@"%@ opened on fd #%d", self, fd); + + connState_ = kConnStateListening; + if (callback) callback(nil); +} + + +- (BOOL)acceptIncomingConnection:(dispatch_fd_t)serverSocketFD { + struct sockaddr_in addr; + socklen_t addrLen = sizeof(addr); + dispatch_fd_t clientSocketFD = accept(serverSocketFD, (struct sockaddr*)&addr, &addrLen); + + if (clientSocketFD == -1) { + perror("accept()"); + return NO; + } + + // prevent SIGPIPE + int on = 1; + setsockopt(clientSocketFD, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof(on)); + + if (fcntl(clientSocketFD, F_SETFL, O_NONBLOCK) == -1) { + perror("fcntl(.. O_NONBLOCK)"); + close(clientSocketFD); + return NO; + } + + if (delegateFlags_ & kDelegateFlagImplements_ioFrameChannel_didAcceptConnection_fromAddress) { + Lookin_PTChannel *peerChannel = [[Lookin_PTChannel alloc] initWithProtocol:protocol_ delegate:delegate_]; + __block Lookin_PTChannel *localChannelRef = self; + dispatch_io_t dispatchChannel = dispatch_io_create(DISPATCH_IO_STREAM, clientSocketFD, protocol_.queue, ^(int error) { + // Important note: This block captures *self*, thus a reference is held to + // *self* until the fd is truly closed. + localChannelRef = nil; + + close(clientSocketFD); + + if (peerChannel->delegateFlags_ & kDelegateFlagImplements_ioFrameChannel_didEndWithError) { + NSError *err = error == 0 ? peerChannel->endError_ : [[NSError alloc] initWithDomain:NSPOSIXErrorDomain code:error userInfo:nil]; + [peerChannel->delegate_ ioFrameChannel:peerChannel didEndWithError:err]; + peerChannel->endError_ = nil; + } + }); + + [peerChannel setConnState:kConnStateConnected]; + [peerChannel setDispatchChannel:dispatchChannel]; + + assert(((struct sockaddr_storage*)&addr)->ss_len == addrLen); + Lookin_PTAddress *address = [[Lookin_PTAddress alloc] initWithSockaddr:(struct sockaddr_storage*)&addr]; + [delegate_ ioFrameChannel:self didAcceptConnection:peerChannel fromAddress:address]; + + NSError *err = nil; + if (![peerChannel startReadingFromConnectedChannel:dispatchChannel error:&err]) { +// NSLog(@"startReadingFromConnectedChannel failed in accept: %@", err); + } + } else { + close(clientSocketFD); + } + return YES; +} + + +#pragma mark - Closing the channel + + +- (void)close { +// NSLog(@"LookinServer - Will close chanel: %@", self.debugTag); + + if ((connState_ == kConnStateConnecting || connState_ == kConnStateConnected) && dispatchObj_channel_) { + dispatch_io_close(dispatchObj_channel_, DISPATCH_IO_STOP); + [self setDispatchChannel:NULL]; + } else if (connState_ == kConnStateListening && dispatchObj_source_) { + dispatch_source_cancel(dispatchObj_source_); + } +} + +/// 曾经连接上 Client,然后 Client 端关闭时,Peertalk 内部会对之前 connect 的 channel 调用该方法 +- (void)cancel { +// NSLog(@"LookinServer - Will cancel chanel: %@", self.debugTag); + + if ((connState_ == kConnStateConnecting || connState_ == kConnStateConnected) && dispatchObj_channel_) { + dispatch_io_close(dispatchObj_channel_, 0); + [self setDispatchChannel:NULL]; + } else if (connState_ == kConnStateListening && dispatchObj_source_) { + dispatch_source_cancel(dispatchObj_source_); + } +} + + +#pragma mark - Reading + + +- (BOOL)startReadingFromConnectedChannel:(dispatch_io_t)channel error:(__autoreleasing NSError**)error { + if (connState_ != kConnStateNone && connState_ != kConnStateConnecting && connState_ != kConnStateConnected) { + if (error) *error = [NSError errorWithDomain:NSPOSIXErrorDomain code:EPERM userInfo:nil]; + return NO; + } + + if (dispatchObj_channel_ != channel) { + [self close]; + [self setDispatchChannel:channel]; + } + + connState_ = kConnStateConnected; + + // helper + BOOL(^handleError)(NSError*,BOOL) = ^BOOL(NSError *error, BOOL isEOS) { + if (error) { + //NSLog(@"Error while communicating: %@", error); + self->endError_ = error; + [self close]; + return YES; + } else if (isEOS) { + [self cancel]; + return YES; + } + return NO; + }; + + [protocol_ readFramesOverChannel:channel onFrame:^(NSError *error, uint32_t type, uint32_t tag, uint32_t payloadSize, dispatch_block_t resumeReadingFrames) { + if (handleError(error, type == PTFrameTypeEndOfStream)) { + return; + } + + BOOL accepted = (channel == self->dispatchObj_channel_); + if (accepted && (self->delegateFlags_ & kDelegateFlagImplements_ioFrameChannel_shouldAcceptFrameOfType_tag_payloadSize)) { + accepted = [self->delegate_ ioFrameChannel:self shouldAcceptFrameOfType:type tag:tag payloadSize:payloadSize]; + } + + if (payloadSize == 0) { + if (accepted && self->delegate_) { + [self->delegate_ ioFrameChannel:self didReceiveFrameOfType:type tag:tag payload:nil]; + } else { + // simply ignore the frame + } + resumeReadingFrames(); + } else { + // has payload + if (!accepted) { + // Read and discard payload, ignoring frame + [self->protocol_ readAndDiscardDataOfSize:payloadSize overChannel:channel callback:^(NSError *error, BOOL endOfStream) { + if (!handleError(error, endOfStream)) { + resumeReadingFrames(); + } + }]; + } else { + [self->protocol_ readPayloadOfSize:payloadSize overChannel:channel callback:^(NSError *error, dispatch_data_t contiguousData, const uint8_t *buffer, size_t bufferSize) { + if (handleError(error, bufferSize == 0)) { + return; + } + + if (self->delegate_) { + Lookin_PTData *payload = [[Lookin_PTData alloc] initWithMappedDispatchData:contiguousData data:(void*)buffer length:bufferSize]; + [self->delegate_ ioFrameChannel:self didReceiveFrameOfType:type tag:tag payload:payload]; + } + + resumeReadingFrames(); + }]; + } + } + }]; + + return YES; +} + + +#pragma mark - Sending + +- (void)sendFrameOfType:(uint32_t)frameType tag:(uint32_t)tag withPayload:(dispatch_data_t)payload callback:(void(^)(NSError *error))callback { + if (connState_ == kConnStateConnecting || connState_ == kConnStateConnected) { + [protocol_ sendFrameOfType:frameType tag:tag withPayload:payload overChannel:dispatchObj_channel_ callback:callback]; + } else if (callback) { + callback([NSError errorWithDomain:NSPOSIXErrorDomain code:EPERM userInfo:nil]); + } +} + +#pragma mark - NSObject + +- (NSString*)description { + id userInfo = objc_getAssociatedObject(self, (void*)&kUserInfoKey); + return [NSString stringWithFormat:@"", self, ( connState_ == kConnStateConnecting ? @"connecting" + : connState_ == kConnStateConnected ? @"connected" + : connState_ == kConnStateListening ? @"listening" + : @"closed"), + userInfo ? " " : "", userInfo ? userInfo : @""]; +} + + +@end + + +#pragma mark - +@implementation Lookin_PTAddress + +- (id)initWithSockaddr:(const struct sockaddr_storage*)addr { + if (!(self = [super init])) return nil; + assert(addr); + memcpy((void*)&sockaddr_, (const void*)addr, addr->ss_len); + return self; +} + + +- (NSString*)name { + if (sockaddr_.ss_len) { + const void *sin_addr = NULL; + size_t bufsize = 0; + if (sockaddr_.ss_family == AF_INET6) { + bufsize = INET6_ADDRSTRLEN; + sin_addr = (const void *)&((const struct sockaddr_in6*)&sockaddr_)->sin6_addr; + } else { + bufsize = INET_ADDRSTRLEN; + sin_addr = (const void *)&((const struct sockaddr_in*)&sockaddr_)->sin_addr; + } + char *buf = CFAllocatorAllocate(kCFAllocatorDefault, bufsize+1, 0); + if (inet_ntop(sockaddr_.ss_family, sin_addr, buf, (unsigned int)bufsize-1) == NULL) { + CFAllocatorDeallocate(kCFAllocatorDefault, buf); + return nil; + } + return [[NSString alloc] initWithBytesNoCopy:(void*)buf length:strlen(buf) encoding:NSUTF8StringEncoding freeWhenDone:YES]; + } else { + return nil; + } +} + + +- (NSInteger)port { + if (sockaddr_.ss_len) { + return ntohs(PT_SOCKADDR_ACCESS(&sockaddr_, sin_port, sin6_port)); + } else { + return 0; + } +} + + +- (NSString*)description { + if (sockaddr_.ss_len) { + return [NSString stringWithFormat:@"%@:%u", self.name, (unsigned)self.port]; + } else { + return @"(?)"; + } +} + +@end + + +#pragma mark - +@implementation Lookin_PTData + +@synthesize dispatchData = dispatchData_; +@synthesize data = data_; +@synthesize length = length_; + +- (id)initWithMappedDispatchData:(dispatch_data_t)mappedContiguousData data:(void*)data length:(size_t)length { + if (!(self = [super init])) return nil; + dispatchData_ = mappedContiguousData; +#if PT_DISPATCH_RETAIN_RELEASE + if (dispatchData_) dispatch_retain(dispatchData_); +#endif + data_ = data; + length_ = length; + return self; +} + +- (void)dealloc { +#if PT_DISPATCH_RETAIN_RELEASE + if (dispatchData_) dispatch_release(dispatchData_); +#endif + data_ = NULL; + length_ = 0; +} + +#pragma mark - NSObject + +- (NSString*)description { + return [NSString stringWithFormat:@"", self, length_]; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/Peertalk/Lookin_PTPrivate.h b/Pods/LookinServer/Src/Main/Shared/Peertalk/Lookin_PTPrivate.h new file mode 100644 index 0000000..6480de8 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/Peertalk/Lookin_PTPrivate.h @@ -0,0 +1,20 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + + + +#if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && (!defined(__IPHONE_6_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_6_0)) || \ + (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && (!defined(__MAC_10_8) || __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_8)) +#define PT_DISPATCH_RETAIN_RELEASE 1 +#else +#define PT_DISPATCH_RETAIN_RELEASE 0 +#endif + +#if PT_DISPATCH_RETAIN_RELEASE +#define PT_PRECISE_LIFETIME +#define PT_PRECISE_LIFETIME_UNUSED +#else +#define PT_PRECISE_LIFETIME __attribute__((objc_precise_lifetime)) +#define PT_PRECISE_LIFETIME_UNUSED __attribute__((objc_precise_lifetime, unused)) +#endif + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/Peertalk/Lookin_PTProtocol.h b/Pods/LookinServer/Src/Main/Shared/Peertalk/Lookin_PTProtocol.h new file mode 100644 index 0000000..b0207d3 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/Peertalk/Lookin_PTProtocol.h @@ -0,0 +1,122 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + + + +// +// A universal frame-based communication protocol which can be used to exchange +// arbitrary structured data. +// +// In short: +// +// - Each transmission is comprised by one fixed-size frame. +// - Each frame contains a protocol version number. +// - Each frame contains an application frame type. +// - Each frame can contain an identifying tag. +// - Each frame can have application-specific data of up to UINT32_MAX size. +// - Transactions style messaging can be modeled on top using frame tags. +// - Lightweight API on top of libdispatch (aka GCD) -- close to the metal. +// +#include +#import + +// Special frame tag that signifies "no tag". Your implementation should never +// create a reply for a frame with this tag. +static const uint32_t PTFrameNoTag = 0; + +// Special frame type that signifies that the stream has ended. +static const uint32_t PTFrameTypeEndOfStream = 0; + +// NSError domain +FOUNDATION_EXPORT NSString * const Lookin_PTProtocolErrorDomain; + + +@interface Lookin_PTProtocol : NSObject + +// Queue on which to run data processing blocks. +@property dispatch_queue_t queue; + +// Get the shared protocol object for *queue* ++ (Lookin_PTProtocol*)sharedProtocolForQueue:(dispatch_queue_t)queue; + +// Initialize a new protocol object to use a specific queue. +- (id)initWithDispatchQueue:(dispatch_queue_t)queue; + +// Initialize a new protocol object to use the current calling queue. +- (id)init; + +#pragma mark Sending frames + +// Generate a new tag that is unique within this protocol object. +- (uint32_t)newTag; + +// Send a frame over *channel* with an optional payload and optional callback. +// If *callback* is not NULL, the block is invoked when either an error occured +// or when the frame (and payload, if any) has been completely sent. +- (void)sendFrameOfType:(uint32_t)frameType + tag:(uint32_t)tag + withPayload:(dispatch_data_t)payload + overChannel:(dispatch_io_t)channel + callback:(void(^)(NSError *error))callback; + +#pragma mark Receiving frames + +// Read frames over *channel* as they arrive. +// The onFrame handler is responsible for reading (or discarding) any payload +// and call *resumeReadingFrames* afterwards to resume reading frames. +// To stop reading frames, simply do not invoke *resumeReadingFrames*. +// When the stream ends, a frame of type PTFrameTypeEndOfStream is received. +- (void)readFramesOverChannel:(dispatch_io_t)channel + onFrame:(void(^)(NSError *error, + uint32_t type, + uint32_t tag, + uint32_t payloadSize, + dispatch_block_t resumeReadingFrames))onFrame; + +// Read a single frame over *channel*. A frame of type PTFrameTypeEndOfStream +// denotes the stream has ended. +- (void)readFrameOverChannel:(dispatch_io_t)channel + callback:(void(^)(NSError *error, + uint32_t frameType, + uint32_t frameTag, + uint32_t payloadSize))callback; + +#pragma mark Receiving frame payloads + +// Read a complete payload. It's the callers responsibility to make sure +// payloadSize is not too large since memory will be automatically allocated +// where only payloadSize is the limit. +// The returned dispatch_data_t object owns *buffer* and thus you need to call +// dispatch_retain on *contiguousData* if you plan to keep *buffer* around after +// returning from the callback. +- (void)readPayloadOfSize:(size_t)payloadSize + overChannel:(dispatch_io_t)channel + callback:(void(^)(NSError *error, + dispatch_data_t contiguousData, + const uint8_t *buffer, + size_t bufferSize))callback; + +// Discard data of *size* waiting on *channel*. *callback* can be NULL. +- (void)readAndDiscardDataOfSize:(size_t)size + overChannel:(dispatch_io_t)channel + callback:(void(^)(NSError *error, BOOL endOfStream))callback; + +@end + +@interface NSData (Lookin_PTProtocol) +// Creates a new dispatch_data_t object which references the receiver and uses +// the receivers bytes as its backing data. The returned dispatch_data_t object +// holds a reference to the recevier. It's the callers responsibility to call +// dispatch_release on the returned object when done. +- (dispatch_data_t)createReferencingDispatchData; ++ (NSData *)dataWithContentsOfDispatchData:(dispatch_data_t)data; +@end + +@interface NSDictionary (Lookin_PTProtocol) +// See description of -[NSData(Lookin_PTProtocol) createReferencingDispatchData] +- (dispatch_data_t)createReferencingDispatchData; + +// Decode *data* as a peroperty list-encoded dictionary. Returns nil on failure. ++ (NSDictionary*)dictionaryWithContentsOfDispatchData:(dispatch_data_t)data; +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/Peertalk/Lookin_PTProtocol.m b/Pods/LookinServer/Src/Main/Shared/Peertalk/Lookin_PTProtocol.m new file mode 100644 index 0000000..72e85f8 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/Peertalk/Lookin_PTProtocol.m @@ -0,0 +1,428 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +#import "Lookin_PTProtocol.h" +#import "Lookin_PTPrivate.h" +#import + +static const uint32_t PTProtocolVersion1 = 1; + +NSString * const Lookin_PTProtocolErrorDomain = @"PTProtocolError"; + +// This is what we send as the header for each frame. +typedef struct _PTFrame { + // The version of the frame and protocol. + uint32_t version; + + // Type of frame + uint32_t type; + + // Unless zero, a tag is retained in frames that are responses to previous + // frames. Applications can use this to build transactions or request-response + // logic. + uint32_t tag; + + // If payloadSize is larger than zero, *payloadSize* number of bytes are + // following, constituting application-specific data. + uint32_t payloadSize; + +} PTFrame; + + +@interface Lookin_PTProtocol () { + uint32_t nextFrameTag_; + @public + dispatch_queue_t queue_; +} +- (dispatch_data_t)createDispatchDataWithFrameOfType:(uint32_t)type frameTag:(uint32_t)frameTag payload:(dispatch_data_t)payload; +@end + + +static void _release_queue_local_protocol(void *objcobj) { + if (objcobj) { + Lookin_PTProtocol *protocol = (__bridge_transfer id)objcobj; + protocol->queue_ = NULL; + } +} + + +@interface Lookin_RQueueLocalIOFrameProtocol : Lookin_PTProtocol +@end +@implementation Lookin_RQueueLocalIOFrameProtocol +- (void)setQueue:(dispatch_queue_t)queue { +} +@end + + +@implementation Lookin_PTProtocol + + ++ (Lookin_PTProtocol*)sharedProtocolForQueue:(dispatch_queue_t)queue { + static const char currentQueueFrameProtocolKey; + //dispatch_queue_t queue = dispatch_get_current_queue(); + Lookin_PTProtocol *currentQueueFrameProtocol = (__bridge Lookin_PTProtocol*)dispatch_queue_get_specific(queue, ¤tQueueFrameProtocolKey); + if (!currentQueueFrameProtocol) { + currentQueueFrameProtocol = [[Lookin_RQueueLocalIOFrameProtocol alloc] initWithDispatchQueue:NULL]; + currentQueueFrameProtocol->queue_ = queue; // reference, no retain, since we would create cyclic references + dispatch_queue_set_specific(queue, ¤tQueueFrameProtocolKey, (__bridge_retained void*)currentQueueFrameProtocol, &_release_queue_local_protocol); + return (__bridge Lookin_PTProtocol*)dispatch_queue_get_specific(queue, ¤tQueueFrameProtocolKey); // to avoid race conds + } else { + return currentQueueFrameProtocol; + } +} + + +- (id)initWithDispatchQueue:(dispatch_queue_t)queue { + if (!(self = [super init])) return nil; + queue_ = queue; +#if PT_DISPATCH_RETAIN_RELEASE + if (queue_) dispatch_retain(queue_); +#endif + return self; +} + +- (id)init { + return [self initWithDispatchQueue:dispatch_get_main_queue()]; +} + +- (void)dealloc { + if (queue_) { +#if PT_DISPATCH_RETAIN_RELEASE + dispatch_release(queue_); +#endif + } +} + +- (dispatch_queue_t)queue { + return queue_; +} + +- (void)setQueue:(dispatch_queue_t)queue { +#if PT_DISPATCH_RETAIN_RELEASE + dispatch_queue_t prev_queue = queue_; + queue_ = queue; + if (queue_) dispatch_retain(queue_); + if (prev_queue) dispatch_release(prev_queue); +#else + queue_ = queue; +#endif +} + + +- (uint32_t)newTag { + return ++nextFrameTag_; +} + + +#pragma mark - +#pragma mark Creating frames + + +- (dispatch_data_t)createDispatchDataWithFrameOfType:(uint32_t)type frameTag:(uint32_t)frameTag payload:(dispatch_data_t)payload { + PTFrame *frame = CFAllocatorAllocate(kCFAllocatorDefault, sizeof(PTFrame), 0); + frame->version = htonl(PTProtocolVersion1); + frame->type = htonl(type); + frame->tag = htonl(frameTag); + + if (payload) { + size_t payloadSize = dispatch_data_get_size(payload); + assert(payloadSize <= UINT32_MAX); + frame->payloadSize = htonl((uint32_t)payloadSize); + } else { + frame->payloadSize = 0; + } + + dispatch_data_t frameData = dispatch_data_create((const void*)frame, sizeof(PTFrame), queue_, ^{ + CFAllocatorDeallocate(kCFAllocatorDefault, (void*)frame); + }); + + if (payload && frame->payloadSize != 0) { + // chain frame + payload + dispatch_data_t data = dispatch_data_create_concat(frameData, payload); +#if PT_DISPATCH_RETAIN_RELEASE + dispatch_release(frameData); +#endif + frameData = data; + } + + return frameData; +} + + +#pragma mark - +#pragma mark Sending frames + + +- (void)sendFrameOfType:(uint32_t)frameType tag:(uint32_t)tag withPayload:(dispatch_data_t)payload overChannel:(dispatch_io_t)channel callback:(void(^)(NSError*))callback { + dispatch_data_t frame = [self createDispatchDataWithFrameOfType:frameType frameTag:tag payload:payload]; + dispatch_io_write(channel, 0, frame, queue_, ^(bool done, dispatch_data_t data, int _errno) { + if (done && callback) { + callback(_errno == 0 ? nil : [[NSError alloc] initWithDomain:NSPOSIXErrorDomain code:_errno userInfo:nil]); + } + }); +#if PT_DISPATCH_RETAIN_RELEASE + dispatch_release(frame); +#endif +} + + +#pragma mark - +#pragma mark Receiving frames + + +- (void)readFrameOverChannel:(dispatch_io_t)channel callback:(void(^)(NSError *error, uint32_t frameType, uint32_t frameTag, uint32_t payloadSize))callback { + __block dispatch_data_t allData = NULL; + + dispatch_io_read(channel, 0, sizeof(PTFrame), queue_, ^(bool done, dispatch_data_t data, int error) { + //NSLog(@"dispatch_io_read: done=%d data=%p error=%d", done, data, error); + size_t dataSize = data ? dispatch_data_get_size(data) : 0; + + if (dataSize) { + if (!allData) { + allData = data; +#if PT_DISPATCH_RETAIN_RELEASE + dispatch_retain(allData); +#endif + } else { +#if PT_DISPATCH_RETAIN_RELEASE + dispatch_data_t allDataPrev = allData; + allData = dispatch_data_create_concat(allData, data); + dispatch_release(allDataPrev); +#else + allData = dispatch_data_create_concat(allData, data); +#endif + } + } + + if (done) { + if (error != 0) { + callback([[NSError alloc] initWithDomain:NSPOSIXErrorDomain code:error userInfo:nil], 0, 0, 0); + return; + } + + if (dataSize == 0) { + callback(nil, PTFrameTypeEndOfStream, 0, 0); + return; + } + + if (!allData || dispatch_data_get_size(allData) < sizeof(PTFrame)) { +#if PT_DISPATCH_RETAIN_RELEASE + if (allData) dispatch_release(allData); +#endif + callback([[NSError alloc] initWithDomain:Lookin_PTProtocolErrorDomain code:0 userInfo:nil], 0, 0, 0); + return; + } + + PTFrame *frame = NULL; + size_t size = 0; + + PT_PRECISE_LIFETIME dispatch_data_t contiguousData = dispatch_data_create_map(allData, (const void **)&frame, &size); // precise lifetime guarantees bytes in frame will stay valid till the end of scope +#if PT_DISPATCH_RETAIN_RELEASE + dispatch_release(allData); +#endif + if (!contiguousData) { + callback([[NSError alloc] initWithDomain:NSPOSIXErrorDomain code:ENOMEM userInfo:nil], 0, 0, 0); + return; + } + + frame->version = ntohl(frame->version); + if (frame->version != PTProtocolVersion1) { + callback([[NSError alloc] initWithDomain:Lookin_PTProtocolErrorDomain code:0 userInfo:nil], 0, 0, 0); + } else { + frame->type = ntohl(frame->type); + frame->tag = ntohl(frame->tag); + frame->payloadSize = ntohl(frame->payloadSize); + callback(nil, frame->type, frame->tag, frame->payloadSize); + } + +#if PT_DISPATCH_RETAIN_RELEASE + dispatch_release(contiguousData); +#endif + } + }); +} + + +- (void)readPayloadOfSize:(size_t)payloadSize overChannel:(dispatch_io_t)channel callback:(void(^)(NSError *error, dispatch_data_t contiguousData, const uint8_t *buffer, size_t bufferSize))callback { + __block dispatch_data_t allData = NULL; + dispatch_io_read(channel, 0, payloadSize, queue_, ^(bool done, dispatch_data_t data, int error) { + //NSLog(@"dispatch_io_read: done=%d data=%p error=%d", done, data, error); + size_t dataSize = dispatch_data_get_size(data); + + if (dataSize) { + if (!allData) { + allData = data; +#if PT_DISPATCH_RETAIN_RELEASE + dispatch_retain(allData); +#endif + } else { +#if PT_DISPATCH_RETAIN_RELEASE + dispatch_data_t allDataPrev = allData; + allData = dispatch_data_create_concat(allData, data); + dispatch_release(allDataPrev); +#else + allData = dispatch_data_create_concat(allData, data); +#endif + } + } + + if (done) { + if (error != 0) { +#if PT_DISPATCH_RETAIN_RELEASE + if (allData) dispatch_release(allData); +#endif + callback([[NSError alloc] initWithDomain:NSPOSIXErrorDomain code:error userInfo:nil], NULL, NULL, 0); + return; + } + + if (dataSize == 0) { +#if PT_DISPATCH_RETAIN_RELEASE + if (allData) dispatch_release(allData); +#endif + callback(nil, NULL, NULL, 0); + return; + } + + uint8_t *buffer = NULL; + size_t bufferSize = 0; + PT_PRECISE_LIFETIME dispatch_data_t contiguousData = NULL; + + if (allData) { + contiguousData = dispatch_data_create_map(allData, (const void **)&buffer, &bufferSize); +#if PT_DISPATCH_RETAIN_RELEASE + dispatch_release(allData); allData = NULL; +#endif + if (!contiguousData) { + callback([[NSError alloc] initWithDomain:NSPOSIXErrorDomain code:ENOMEM userInfo:nil], NULL, NULL, 0); + return; + } + } + + callback(nil, contiguousData, buffer, bufferSize); +#if PT_DISPATCH_RETAIN_RELEASE + if (contiguousData) dispatch_release(contiguousData); +#endif + } + }); +} + + +- (void)readAndDiscardDataOfSize:(size_t)size overChannel:(dispatch_io_t)channel callback:(void(^)(NSError*, BOOL))callback { + dispatch_io_read(channel, 0, size, queue_, ^(bool done, dispatch_data_t data, int error) { + if (done && callback) { + size_t dataSize = data ? dispatch_data_get_size(data) : 0; + callback(error == 0 ? nil : [[NSError alloc] initWithDomain:NSPOSIXErrorDomain code:error userInfo:nil], dataSize == 0); + } + }); +} + + +- (void)readFramesOverChannel:(dispatch_io_t)channel onFrame:(void(^)(NSError*, uint32_t, uint32_t, uint32_t, dispatch_block_t))onFrame { + [self readFrameOverChannel:channel callback:^(NSError *error, uint32_t type, uint32_t tag, uint32_t payloadSize) { + onFrame(error, type, tag, payloadSize, ^{ + if (type != PTFrameTypeEndOfStream) { + [self readFramesOverChannel:channel onFrame:onFrame]; + } + }); + }]; +} + + +@end + + +@interface Lookin_PTDispatchData : NSObject { + dispatch_data_t dispatchData_; +} +@end +@implementation Lookin_PTDispatchData +- (id)initWithDispatchData:(dispatch_data_t)dispatchData { + if (!(self = [super init])) return nil; + dispatchData_ = dispatchData; +#if PT_DISPATCH_RETAIN_RELEASE + dispatch_retain(dispatchData_); +#endif + return self; +} +- (void)dealloc { +#if PT_DISPATCH_RETAIN_RELEASE + if (dispatchData_) dispatch_release(dispatchData_); +#endif +} +@end + +@implementation NSData (Lookin_PTProtocol) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-getter-return-value" + +- (dispatch_data_t)createReferencingDispatchData { + // Note: The queue is used to submit the destructor. Since we only perform an + // atomic release of self, it doesn't really matter which queue is used, thus + // we use the current calling queue. + return dispatch_data_create((const void*)self.bytes, self.length, dispatch_get_main_queue(), ^{ + // trick to have the block capture the data, thus retain/releasing + [self length]; + }); +} + +#pragma clang diagnostic pop + ++ (NSData *)dataWithContentsOfDispatchData:(dispatch_data_t)data { + if (!data) { + return nil; + } + uint8_t *buffer = NULL; + size_t bufferSize = 0; + PT_PRECISE_LIFETIME dispatch_data_t contiguousData = dispatch_data_create_map(data, (const void **)&buffer, &bufferSize); + if (!contiguousData) { + return nil; + } + + Lookin_PTDispatchData *dispatchDataRef = [[Lookin_PTDispatchData alloc] initWithDispatchData:contiguousData]; + NSData *newData = [NSData dataWithBytesNoCopy:(void*)buffer length:bufferSize freeWhenDone:NO]; +#if PT_DISPATCH_RETAIN_RELEASE + dispatch_release(contiguousData); +#endif + static const bool kDispatchDataRefKey; + objc_setAssociatedObject(newData, (const void*)kDispatchDataRefKey, dispatchDataRef, OBJC_ASSOCIATION_RETAIN); + + return newData; +} + +@end + + +@implementation NSDictionary (Lookin_PTProtocol) + +- (dispatch_data_t)createReferencingDispatchData { + NSError *error = nil; + NSData *plistData = [NSPropertyListSerialization dataWithPropertyList:self format:NSPropertyListBinaryFormat_v1_0 options:0 error:&error]; + if (!plistData) { + NSLog(@"Failed to serialize property list: %@", error); + return nil; + } else { + return [plistData createReferencingDispatchData]; + } +} + +// Decode *data* as a peroperty list-encoded dictionary. Returns nil on failure. ++ (NSDictionary*)dictionaryWithContentsOfDispatchData:(dispatch_data_t)data { + if (!data) { + return nil; + } + uint8_t *buffer = NULL; + size_t bufferSize = 0; + PT_PRECISE_LIFETIME dispatch_data_t contiguousData = dispatch_data_create_map(data, (const void **)&buffer, &bufferSize); + if (!contiguousData) { + return nil; + } + NSDictionary *dict = [NSPropertyListSerialization propertyListWithData:[NSData dataWithBytesNoCopy:(void*)buffer length:bufferSize freeWhenDone:NO] options:NSPropertyListImmutable format:NULL error:nil]; +#if PT_DISPATCH_RETAIN_RELEASE + dispatch_release(contiguousData); +#endif + return dict; +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/Peertalk/Lookin_PTUSBHub.h b/Pods/LookinServer/Src/Main/Shared/Peertalk/Lookin_PTUSBHub.h new file mode 100644 index 0000000..30c97a7 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/Peertalk/Lookin_PTUSBHub.h @@ -0,0 +1,88 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + + + +#include +#import + +// Lookin_PTUSBDeviceDidAttachNotification +// Posted when a device has been attached. Also posted for each device that is +// already attached when the Lookin_PTUSBHub starts listening. +// +// .userInfo = { +// DeviceID = 3; +// MessageType = Attached; +// Properties = { +// ConnectionSpeed = 480000000; +// ConnectionType = USB; +// DeviceID = 3; +// LocationID = 1234567890; +// ProductID = 1234; +// SerialNumber = 0123456789abcdef0123456789abcdef01234567; +// }; +// } +// +FOUNDATION_EXPORT NSString * const Lookin_PTUSBDeviceDidAttachNotification; + +// Lookin_PTUSBDeviceDidDetachNotification +// Posted when a device has been detached. +// +// .userInfo = { +// DeviceID = 3; +// MessageType = Detached; +// } +// +FOUNDATION_EXPORT NSString * const Lookin_PTUSBDeviceDidDetachNotification; + +// NSError domain +FOUNDATION_EXPORT NSString * const Lookin_PTUSBHubErrorDomain; + +// Error codes returned with NSError.code for NSError domain Lookin_PTUSBHubErrorDomain +typedef enum { + PTUSBHubErrorBadDevice = 2, + PTUSBHubErrorConnectionRefused = 3, +} PTUSBHubError; + +@interface Lookin_PTUSBHub : NSObject + +// Shared, implicitly opened hub. ++ (Lookin_PTUSBHub*)sharedHub; + +// Connect to a TCP *port* on a device, while the actual transport is over USB. +// Upon success, *error* is nil and *channel* is a duplex I/O channel. +// You can retrieve the underlying file descriptor using +// dispatch_io_get_descriptor(channel). The dispatch_io_t channel behaves just +// like any stream type dispatch_io_t, making it possible to use the same logic +// for both USB bridged connections and e.g. ethernet-based connections. +// +// *onStart* is called either when a connection failed, in which case the error +// argument is non-nil, or when the connection was successfully established (the +// error argument is nil). Must not be NULL. +// +// *onEnd* is called when a connection was open and just did close. If the error +// argument is non-nil, the channel closed because of an error. Pass NULL for no +// callback. +// +- (void)connectToDevice:(NSNumber*)deviceID + port:(int)port + onStart:(void(^)(NSError *error, dispatch_io_t channel))onStart + onEnd:(void(^)(NSError *error))onEnd; + +// Start listening for devices. You only need to invoke this method on custom +// instances to start receiving notifications. The shared instance returned from +// +sharedHub is always in listening mode. +// +// *onStart* is called either when the system failed to start listening, in +// which case the error argument is non-nil, or when the receiver is listening. +// Pass NULL for no callback. +// +// *onEnd* is called when listening stopped. If the error argument is non-nil, +// listening stopped because of an error. Pass NULL for no callback. +// +- (void)listenOnQueue:(dispatch_queue_t)queue + onStart:(void(^)(NSError*))onStart + onEnd:(void(^)(NSError*))onEnd; + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/Peertalk/Lookin_PTUSBHub.m b/Pods/LookinServer/Src/Main/Shared/Peertalk/Lookin_PTUSBHub.m new file mode 100644 index 0000000..cde0dd7 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/Peertalk/Lookin_PTUSBHub.m @@ -0,0 +1,674 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +#import "Lookin_PTUSBHub.h" + + + +#import "Lookin_PTPrivate.h" + +#include +#include +#include +#include +#include + +NSString * const Lookin_PTUSBHubErrorDomain = @"PTUSBHubError"; + +typedef uint32_t USBMuxPacketType; +enum { + USBMuxPacketTypeResult = 1, + USBMuxPacketTypeConnect = 2, + USBMuxPacketTypeListen = 3, + USBMuxPacketTypeDeviceAdd = 4, + USBMuxPacketTypeDeviceRemove = 5, + // ? = 6, + // ? = 7, + USBMuxPacketTypePlistPayload = 8, +}; + +typedef uint32_t USBMuxPacketProtocol; +enum { + USBMuxPacketProtocolBinary = 0, + USBMuxPacketProtocolPlist = 1, +}; + +typedef uint32_t USBMuxReplyCode; +enum { + USBMuxReplyCodeOK = 0, + USBMuxReplyCodeBadCommand = 1, + USBMuxReplyCodeBadDevice = 2, + USBMuxReplyCodeConnectionRefused = 3, + // ? = 4, + // ? = 5, + USBMuxReplyCodeBadVersion = 6, +}; + + +typedef struct usbmux_packet { + uint32_t size; + USBMuxPacketProtocol protocol; + USBMuxPacketType type; + uint32_t tag; + char data[0]; +} __attribute__((__packed__)) usbmux_packet_t; + +static const uint32_t kUsbmuxPacketMaxPayloadSize = UINT32_MAX - (uint32_t)sizeof(usbmux_packet_t); + + +static uint32_t usbmux_packet_payload_size(usbmux_packet_t *upacket) { + return upacket->size - sizeof(usbmux_packet_t); +} + + +static void *usbmux_packet_payload(usbmux_packet_t *upacket) { + return (void*)upacket->data; +} + + +static void usbmux_packet_set_payload(usbmux_packet_t *upacket, + const void *payload, + uint32_t payloadLength) +{ + memcpy(usbmux_packet_payload(upacket), payload, payloadLength); +} + + +static usbmux_packet_t *usbmux_packet_alloc(uint32_t payloadSize) { + assert(payloadSize <= kUsbmuxPacketMaxPayloadSize); + uint32_t upacketSize = sizeof(usbmux_packet_t) + payloadSize; + usbmux_packet_t *upacket = CFAllocatorAllocate(kCFAllocatorDefault, upacketSize, 0); + memset(upacket, 0, sizeof(usbmux_packet_t)); + upacket->size = upacketSize; + return upacket; +} + + +static usbmux_packet_t *usbmux_packet_create(USBMuxPacketProtocol protocol, + USBMuxPacketType type, + uint32_t tag, + const void *payload, + uint32_t payloadSize) +{ + usbmux_packet_t *upacket = usbmux_packet_alloc(payloadSize); + if (!upacket) { + return NULL; + } + + upacket->protocol = protocol; + upacket->type = type; + upacket->tag = tag; + + if (payload && payloadSize) { + usbmux_packet_set_payload(upacket, payload, (uint32_t)payloadSize); + } + + return upacket; +} + + +static void usbmux_packet_free(usbmux_packet_t *upacket) { + CFAllocatorDeallocate(kCFAllocatorDefault, upacket); +} + + +NSString * const Lookin_PTUSBDeviceDidAttachNotification = @"Lookin_PTUSBDeviceDidAttachNotification"; +NSString * const Lookin_PTUSBDeviceDidDetachNotification = @"Lookin_PTUSBDeviceDidDetachNotification"; + +static NSString *kPlistPacketTypeListen = @"Listen"; +static NSString *kPlistPacketTypeConnect = @"Connect"; + + +// Represents a channel of communication between the host process and a remote +// (device) system. In practice, a Lookin_PTUSBChannel is connected to a usbmuxd +// endpoint which is configured to either listen for device changes (the +// PTUSBHub's channel is usually configured as a device notification listener) or +// configured as a TCP bridge (e.g. channels returned from PTUSBHub's +// connectToDevice:port:callback:). You should not create channels yourself, but +// let Lookin_PTUSBHub provide you with already configured channels. +@interface Lookin_PTUSBChannel : NSObject { + dispatch_io_t channel_; + dispatch_queue_t queue_; + uint32_t nextPacketTag_; + NSMutableDictionary *responseQueue_; + BOOL autoReadPackets_; + BOOL isReadingPackets_; +} + +// The underlying dispatch I/O channel. This is handy if you want to handle your +// own I/O logic without Lookin_PTUSBChannel. Remember to dispatch_retain() the channel +// if you plan on using it as it might be released from the Lookin_PTUSBChannel at any +// point in time. +@property (readonly) dispatch_io_t dispatchChannel; + +// The underlying file descriptor. +@property (readonly) dispatch_fd_t fileDescriptor; + +// Send data +- (void)sendDispatchData:(dispatch_data_t)data callback:(void(^)(NSError*))callback; +- (void)sendData:(NSData*)data callback:(void(^)(NSError*))callback; + +// Read data +- (void)readFromOffset:(off_t)offset length:(size_t)length callback:(void(^)(NSError *error, dispatch_data_t data))callback; + +// Close the channel, preventing further reads and writes, but letting currently +// queued reads and writes finish. +- (void)cancel; + +// Close the channel, preventing further reads and writes, immediately +// terminating any ongoing reads and writes. +- (void)stop; + +@end + + +@interface Lookin_PTUSBChannel (Private) + ++ (NSDictionary*)packetDictionaryWithPacketType:(NSString*)messageType payload:(NSDictionary*)payload; +- (BOOL)openOnQueue:(dispatch_queue_t)queue error:(NSError**)error onEnd:(void(^)(NSError *error))onEnd; +- (void)listenWithBroadcastHandler:(void(^)(NSDictionary *packet))broadcastHandler callback:(void(^)(NSError*))callback; +- (BOOL)errorFromPlistResponse:(NSDictionary*)packet error:(NSError**)error; +- (uint32_t)nextPacketTag; +- (void)sendPacketOfType:(USBMuxPacketType)type overProtocol:(USBMuxPacketProtocol)protocol tag:(uint32_t)tag payload:(NSData*)payload callback:(void(^)(NSError*))callback; +- (void)sendPacket:(NSDictionary*)packet tag:(uint32_t)tag callback:(void(^)(NSError *error))callback; +- (void)sendRequest:(NSDictionary*)packet callback:(void(^)(NSError *error, NSDictionary *responsePacket))callback; +- (void)scheduleReadPacketWithCallback:(void(^)(NSError *error, NSDictionary *packet, uint32_t packetTag))callback; +- (void)scheduleReadPacketWithBroadcastHandler:(void(^)(NSDictionary *packet))broadcastHandler; +- (void)setNeedsReadingPacket; +@end + + +@interface Lookin_PTUSBHub () { + Lookin_PTUSBChannel *channel_; +} +- (void)handleBroadcastPacket:(NSDictionary*)packet; +@end + + +@implementation Lookin_PTUSBHub + + ++ (Lookin_PTUSBHub*)sharedHub { + static Lookin_PTUSBHub *gSharedHub; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + gSharedHub = [Lookin_PTUSBHub new]; + [gSharedHub listenOnQueue:dispatch_get_main_queue() onStart:^(NSError *error) { + if (error) { + NSLog(@"Lookin_PTUSBHub failed to initialize: %@", error); + } + } onEnd:nil]; + }); + return gSharedHub; +} + + +- (id)init { + if (!(self = [super init])) return nil; + + return self; +} + + +- (void)listenOnQueue:(dispatch_queue_t)queue onStart:(void(^)(NSError*))onStart onEnd:(void(^)(NSError*))onEnd { + if (channel_) { + if (onStart) onStart(nil); + return; + } + channel_ = [Lookin_PTUSBChannel new]; + NSError *error = nil; + if ([channel_ openOnQueue:queue error:&error onEnd:onEnd]) { + [channel_ listenWithBroadcastHandler:^(NSDictionary *packet) { [self handleBroadcastPacket:packet]; } callback:onStart]; + } else if (onStart) { + onStart(error); + } +} + + +- (void)connectToDevice:(NSNumber*)deviceID port:(int)port onStart:(void(^)(NSError*, dispatch_io_t))onStart onEnd:(void(^)(NSError*))onEnd { + Lookin_PTUSBChannel *channel = [Lookin_PTUSBChannel new]; + NSError *error = nil; + + if (![channel openOnQueue:dispatch_get_main_queue() error:&error onEnd:onEnd]) { + onStart(error, nil); + return; + } + + port = ((port<<8) & 0xFF00) | (port>>8); // limit + + NSDictionary *packet = [Lookin_PTUSBChannel packetDictionaryWithPacketType:kPlistPacketTypeConnect + payload:[NSDictionary dictionaryWithObjectsAndKeys: + deviceID, @"DeviceID", + [NSNumber numberWithInt:port], @"PortNumber", + nil]]; + + [channel sendRequest:packet callback:^(NSError *error_, NSDictionary *responsePacket) { + NSError *error = error_; + [channel errorFromPlistResponse:responsePacket error:&error]; + onStart(error, (error ? nil : channel.dispatchChannel) ); + }]; +} + + +- (void)handleBroadcastPacket:(NSDictionary*)packet { + NSString *messageType = [packet objectForKey:@"MessageType"]; + + if ([@"Attached" isEqualToString:messageType]) { + [[NSNotificationCenter defaultCenter] postNotificationName:Lookin_PTUSBDeviceDidAttachNotification object:self userInfo:packet]; + } else if ([@"Detached" isEqualToString:messageType]) { + [[NSNotificationCenter defaultCenter] postNotificationName:Lookin_PTUSBDeviceDidDetachNotification object:self userInfo:packet]; + } else { + NSLog(@"Warning: Unhandled broadcast message: %@", packet); + } +} + + +@end + +#pragma mark - + +@implementation Lookin_PTUSBChannel + ++ (NSDictionary*)packetDictionaryWithPacketType:(NSString*)messageType payload:(NSDictionary*)payload { + NSDictionary *packet = nil; + + static NSString *bundleName = nil; + static NSString *bundleVersion = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSDictionary *infoDict = [NSBundle mainBundle].infoDictionary; + if (infoDict) { + bundleName = [infoDict objectForKey:@"CFBundleName"]; + bundleVersion = [[infoDict objectForKey:@"CFBundleVersion"] description]; + } + }); + + if (bundleName) { + packet = [NSDictionary dictionaryWithObjectsAndKeys: + messageType, @"MessageType", + bundleName, @"ProgName", + bundleVersion, @"ClientVersionString", + nil]; + } else { + packet = [NSDictionary dictionaryWithObjectsAndKeys:messageType, @"MessageType", nil]; + } + + if (payload) { + NSMutableDictionary *mpacket = [NSMutableDictionary dictionaryWithDictionary:payload]; + [mpacket addEntriesFromDictionary:packet]; + packet = mpacket; + } + + return packet; +} + + +- (id)init { + if (!(self = [super init])) return nil; + + return self; +} + + +- (void)dealloc { + //NSLog(@"dealloc %@", self); + if (channel_) { +#if PT_DISPATCH_RETAIN_RELEASE + dispatch_release(channel_); +#endif + channel_ = nil; + } +} + + +- (BOOL)valid { + return !!channel_; +} + + +- (dispatch_io_t)dispatchChannel { + return channel_; +} + + +- (dispatch_fd_t)fileDescriptor { + return dispatch_io_get_descriptor(channel_); +} + + +- (BOOL)openOnQueue:(dispatch_queue_t)queue error:(NSError**)error onEnd:(void(^)(NSError*))onEnd { + assert(queue != nil); + assert(channel_ == nil); + queue_ = queue; + + // Create socket + dispatch_fd_t fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd == -1) { + if (error) *error = [[NSError alloc] initWithDomain:NSPOSIXErrorDomain code:errno userInfo:nil]; + return NO; + } + + // prevent SIGPIPE + int on = 1; + setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof(on)); + + // Connect socket + struct sockaddr_un addr; + addr.sun_family = AF_UNIX; + strcpy(addr.sun_path, "/var/run/usbmuxd"); + socklen_t socklen = sizeof(addr); + if (connect(fd, (struct sockaddr*)&addr, socklen) == -1) { + if (error) *error = [[NSError alloc] initWithDomain:NSPOSIXErrorDomain code:errno userInfo:nil]; + return NO; + } + + channel_ = dispatch_io_create(DISPATCH_IO_STREAM, fd, queue_, ^(int error) { + close(fd); + if (onEnd) { + onEnd(error == 0 ? nil : [[NSError alloc] initWithDomain:NSPOSIXErrorDomain code:error userInfo:nil]); + } + }); + + return YES; +} + + +- (void)listenWithBroadcastHandler:(void(^)(NSDictionary *packet))broadcastHandler callback:(void(^)(NSError*))callback { + autoReadPackets_ = YES; + [self scheduleReadPacketWithBroadcastHandler:broadcastHandler]; + + NSDictionary *packet = [Lookin_PTUSBChannel packetDictionaryWithPacketType:kPlistPacketTypeListen payload:nil]; + + [self sendRequest:packet callback:^(NSError *error_, NSDictionary *responsePacket) { + if (!callback) + return; + + NSError *error = error_; + [self errorFromPlistResponse:responsePacket error:&error]; + + callback(error); + }]; +} + + +- (BOOL)errorFromPlistResponse:(NSDictionary*)packet error:(NSError**)error { + if (!*error) { + NSNumber *n = [packet objectForKey:@"Number"]; + + if (!n) { + *error = [NSError errorWithDomain:Lookin_PTUSBHubErrorDomain code:(n ? n.integerValue : 0) userInfo:nil]; + return NO; + } + + USBMuxReplyCode replyCode = (USBMuxReplyCode)n.integerValue; + if (replyCode != 0) { + NSString *errmessage = @"Unspecified error"; + switch (replyCode) { + case USBMuxReplyCodeBadCommand: errmessage = @"illegal command"; break; + case USBMuxReplyCodeBadDevice: errmessage = @"unknown device"; break; + case USBMuxReplyCodeConnectionRefused: errmessage = @"connection refused"; break; + case USBMuxReplyCodeBadVersion: errmessage = @"invalid version"; break; + default: break; + } + *error = [NSError errorWithDomain:Lookin_PTUSBHubErrorDomain code:replyCode userInfo:[NSDictionary dictionaryWithObject:errmessage forKey:NSLocalizedDescriptionKey]]; + return NO; + } + } + return YES; +} + + +- (uint32_t)nextPacketTag { + return ++nextPacketTag_; +} + + +- (void)sendRequest:(NSDictionary*)packet callback:(void(^)(NSError*, NSDictionary*))callback { + uint32_t tag = [self nextPacketTag]; + [self sendPacket:packet tag:tag callback:^(NSError *error) { + if (error) { + callback(error, nil); + return; + } + // TODO: timeout un-triggered callbacks in responseQueue_ + if (!self->responseQueue_) self->responseQueue_ = [NSMutableDictionary new]; + [self->responseQueue_ setObject:callback forKey:[NSNumber numberWithUnsignedInt:tag]]; + }]; + + // We are awaiting a response + [self setNeedsReadingPacket]; +} + + +- (void)setNeedsReadingPacket { + if (!isReadingPackets_) { + [self scheduleReadPacketWithBroadcastHandler:nil]; + } +} + + +- (void)scheduleReadPacketWithBroadcastHandler:(void(^)(NSDictionary *packet))broadcastHandler { + assert(isReadingPackets_ == NO); + + [self scheduleReadPacketWithCallback:^(NSError *error, NSDictionary *packet, uint32_t packetTag) { + // Interpret the package we just received + if (packetTag == 0) { + // Broadcast message + //NSLog(@"Received broadcast: %@", packet); + if (broadcastHandler) broadcastHandler(packet); + } else if (self->responseQueue_) { + // Reply + NSNumber *key = [NSNumber numberWithUnsignedInt:packetTag]; + void(^requestCallback)(NSError*,NSDictionary*) = [self->responseQueue_ objectForKey:key]; + if (requestCallback) { + [self->responseQueue_ removeObjectForKey:key]; + requestCallback(error, packet); + } else { + NSLog(@"Warning: Ignoring reply packet for which there is no registered callback. Packet => %@", packet); + } + } + + // Schedule reading another incoming package + if (self->autoReadPackets_) { + [self scheduleReadPacketWithBroadcastHandler:broadcastHandler]; + } + }]; +} + + +- (void)scheduleReadPacketWithCallback:(void(^)(NSError*, NSDictionary*, uint32_t))callback { + static usbmux_packet_t ref_upacket; + isReadingPackets_ = YES; + + // Read the first `sizeof(ref_upacket.size)` bytes off the channel_ + dispatch_io_read(channel_, 0, sizeof(ref_upacket.size), queue_, ^(bool done, dispatch_data_t data, int error) { + //NSLog(@"dispatch_io_read 0,4: done=%d data=%p error=%d", done, data, error); + + if (!done) + return; + + if (error) { + self->isReadingPackets_ = NO; + callback([[NSError alloc] initWithDomain:NSPOSIXErrorDomain code:error userInfo:nil], nil, 0); + return; + } + + // Read size of incoming usbmux_packet_t + uint32_t upacket_len = 0; + char *buffer = NULL; + size_t buffer_size = 0; + PT_PRECISE_LIFETIME_UNUSED dispatch_data_t map_data = dispatch_data_create_map(data, (const void **)&buffer, &buffer_size); // objc_precise_lifetime guarantees 'map_data' isn't released before memcpy has a chance to do its thing + assert(buffer_size == sizeof(ref_upacket.size)); + assert(sizeof(upacket_len) == sizeof(ref_upacket.size)); + memcpy((void *)&(upacket_len), (const void *)buffer, buffer_size); +#if PT_DISPATCH_RETAIN_RELEASE + dispatch_release(map_data); +#endif + + // Allocate a new usbmux_packet_t for the expected size + uint32_t payloadLength = upacket_len - (uint32_t)sizeof(usbmux_packet_t); + usbmux_packet_t *upacket = usbmux_packet_alloc(payloadLength); + + // Read rest of the incoming usbmux_packet_t + off_t offset = sizeof(ref_upacket.size); + dispatch_io_read(self->channel_, offset, (size_t)(upacket->size - offset), self->queue_, ^(bool done, dispatch_data_t data, int error) { + //NSLog(@"dispatch_io_read X,Y: done=%d data=%p error=%d", done, data, error); + + if (!done) { + return; + } + + self->isReadingPackets_ = NO; + + if (error) { + callback([[NSError alloc] initWithDomain:NSPOSIXErrorDomain code:error userInfo:nil], nil, 0); + usbmux_packet_free(upacket); + return; + } + + if (upacket_len > kUsbmuxPacketMaxPayloadSize) { + callback( + [[NSError alloc] initWithDomain:Lookin_PTUSBHubErrorDomain code:1 userInfo:@{ + NSLocalizedDescriptionKey:@"Received a packet that is too large"}], + nil, + 0 + ); + usbmux_packet_free(upacket); + return; + } + + // Copy read bytes onto our usbmux_packet_t + char *buffer = NULL; + size_t buffer_size = 0; + PT_PRECISE_LIFETIME_UNUSED dispatch_data_t map_data = dispatch_data_create_map(data, (const void **)&buffer, &buffer_size); + assert(buffer_size == upacket->size - offset); + memcpy(((void *)(upacket))+offset, (const void *)buffer, buffer_size); +#if PT_DISPATCH_RETAIN_RELEASE + dispatch_release(map_data); +#endif + + // We only support plist protocol + if (upacket->protocol != USBMuxPacketProtocolPlist) { + callback([[NSError alloc] initWithDomain:Lookin_PTUSBHubErrorDomain code:0 userInfo:[NSDictionary dictionaryWithObject:@"Unexpected package protocol" forKey:NSLocalizedDescriptionKey]], nil, upacket->tag); + usbmux_packet_free(upacket); + return; + } + + // Only one type of packet in the plist protocol + if (upacket->type != USBMuxPacketTypePlistPayload) { + callback([[NSError alloc] initWithDomain:Lookin_PTUSBHubErrorDomain code:0 userInfo:[NSDictionary dictionaryWithObject:@"Unexpected package type" forKey:NSLocalizedDescriptionKey]], nil, upacket->tag); + usbmux_packet_free(upacket); + return; + } + + // Try to decode any payload as plist + NSError *err = nil; + NSDictionary *dict = nil; + if (usbmux_packet_payload_size(upacket)) { + dict = [NSPropertyListSerialization propertyListWithData:[NSData dataWithBytesNoCopy:usbmux_packet_payload(upacket) length:usbmux_packet_payload_size(upacket) freeWhenDone:NO] options:NSPropertyListImmutable format:NULL error:&err]; + } + + // Invoke callback + callback(err, dict, upacket->tag); + usbmux_packet_free(upacket); + }); + }); +} + + +- (void)sendPacketOfType:(USBMuxPacketType)type + overProtocol:(USBMuxPacketProtocol)protocol + tag:(uint32_t)tag + payload:(NSData*)payload + callback:(void(^)(NSError*))callback +{ + assert(payload.length <= kUsbmuxPacketMaxPayloadSize); + usbmux_packet_t *upacket = usbmux_packet_create( + protocol, + type, + tag, + payload ? payload.bytes : nil, + (uint32_t)(payload ? payload.length : 0) + ); + dispatch_data_t data = dispatch_data_create((const void*)upacket, upacket->size, queue_, ^{ + // Free packet when data is freed + usbmux_packet_free(upacket); + }); + //NSData *data1 = [NSData dataWithBytesNoCopy:(void*)upacket length:upacket->size freeWhenDone:NO]; + //[data1 writeToFile:[NSString stringWithFormat:@"/Users/rsms/c-packet-%u.data", tag] atomically:NO]; + [self sendDispatchData:data callback:callback]; +} + + +- (void)sendPacket:(NSDictionary*)packet tag:(uint32_t)tag callback:(void(^)(NSError*))callback { + NSError *error = nil; + // NSPropertyListBinaryFormat_v1_0 + NSData *plistData = [NSPropertyListSerialization dataWithPropertyList:packet format:NSPropertyListXMLFormat_v1_0 options:0 error:&error]; + if (!plistData) { + callback(error); + } else { + [self sendPacketOfType:USBMuxPacketTypePlistPayload overProtocol:USBMuxPacketProtocolPlist tag:tag payload:plistData callback:callback]; + } +} + + +- (void)sendDispatchData:(dispatch_data_t)data callback:(void(^)(NSError*))callback { + off_t offset = 0; + dispatch_io_write(channel_, offset, data, queue_, ^(bool done, dispatch_data_t data, int _errno) { + //NSLog(@"dispatch_io_write: done=%d data=%p error=%d", done, data, error); + if (!done) + return; + if (callback) { + NSError *err = nil; + if (_errno) err = [[NSError alloc] initWithDomain:NSPOSIXErrorDomain code:_errno userInfo:nil]; + callback(err); + } + }); +#if PT_DISPATCH_RETAIN_RELEASE + dispatch_release(data); // Release our ref. A ref is still held by dispatch_io_write +#endif +} + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-getter-return-value" + +- (void)sendData:(NSData*)data callback:(void(^)(NSError*))callback { + dispatch_data_t ddata = dispatch_data_create((const void*)data.bytes, data.length, queue_, ^{ + // trick to have the block capture and retain the data + [data length]; + }); + [self sendDispatchData:ddata callback:callback]; +} + +#pragma clang diagnostic pop + +- (void)readFromOffset:(off_t)offset length:(size_t)length callback:(void(^)(NSError *error, dispatch_data_t data))callback { + dispatch_io_read(channel_, offset, length, queue_, ^(bool done, dispatch_data_t data, int _errno) { + if (!done) + return; + + NSError *error = nil; + if (_errno != 0) { + error = [[NSError alloc] initWithDomain:NSPOSIXErrorDomain code:_errno userInfo:nil]; + } + + callback(error, data); + }); +} + + +- (void)cancel { + if (channel_) { + dispatch_io_close(channel_, 0); + } +} + + +- (void)stop { + if (channel_) { + dispatch_io_close(channel_, DISPATCH_IO_STOP); + } +} + +@end + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/Pods/LookinServer/Src/Main/Shared/Peertalk/Peertalk.h b/Pods/LookinServer/Src/Main/Shared/Peertalk/Peertalk.h new file mode 100644 index 0000000..8249329 --- /dev/null +++ b/Pods/LookinServer/Src/Main/Shared/Peertalk/Peertalk.h @@ -0,0 +1,28 @@ +#ifdef SHOULD_COMPILE_LOOKIN_SERVER + +// +// Peertalk.h +// Peertalk +// +// Created by Marek Cirkos on 12/04/2016. +// +// + + + +#import + +//! Project version number for Peertalk. +FOUNDATION_EXPORT double PeertalkVersionNumber; + +//! Project version string for Peertalk. +FOUNDATION_EXPORT const unsigned char PeertalkVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + + +#import "Lookin_PTChannel.h" +#import "Lookin_PTProtocol.h" +#import "Lookin_PTUSBHub.h" + +#endif /* SHOULD_COMPILE_LOOKIN_SERVER */ diff --git a/CustomKeyboard/Masonry/LICENSE b/Pods/MBProgressHUD/LICENSE old mode 100755 new mode 100644 similarity index 93% rename from CustomKeyboard/Masonry/LICENSE rename to Pods/MBProgressHUD/LICENSE index a843c00..d7f0647 --- a/CustomKeyboard/Masonry/LICENSE +++ b/Pods/MBProgressHUD/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2011-2012 Masonry Team - https://github.com/Masonry +Copyright © 2009-2020 Matej Bukovinski Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Pods/MBProgressHUD/MBProgressHUD.h b/Pods/MBProgressHUD/MBProgressHUD.h new file mode 100644 index 0000000..38b5004 --- /dev/null +++ b/Pods/MBProgressHUD/MBProgressHUD.h @@ -0,0 +1,411 @@ +// +// MBProgressHUD.h +// Version 1.2.0 +// Created by Matej Bukovinski on 2.4.09. +// + +// This code is distributed under the terms and conditions of the MIT license. + +// Copyright © 2009-2016 Matej Bukovinski +// +// 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 +#import +#import + +@class MBBackgroundView; +@protocol MBProgressHUDDelegate; + + +extern CGFloat const MBProgressMaxOffset; + +typedef NS_ENUM(NSInteger, MBProgressHUDMode) { + /// UIActivityIndicatorView. + MBProgressHUDModeIndeterminate, + /// A round, pie-chart like, progress view. + MBProgressHUDModeDeterminate, + /// Horizontal progress bar. + MBProgressHUDModeDeterminateHorizontalBar, + /// Ring-shaped progress view. + MBProgressHUDModeAnnularDeterminate, + /// Shows a custom view. + MBProgressHUDModeCustomView, + /// Shows only labels. + MBProgressHUDModeText +}; + +typedef NS_ENUM(NSInteger, MBProgressHUDAnimation) { + /// Opacity animation + MBProgressHUDAnimationFade, + /// Opacity + scale animation (zoom in when appearing zoom out when disappearing) + MBProgressHUDAnimationZoom, + /// Opacity + scale animation (zoom out style) + MBProgressHUDAnimationZoomOut, + /// Opacity + scale animation (zoom in style) + MBProgressHUDAnimationZoomIn +}; + +typedef NS_ENUM(NSInteger, MBProgressHUDBackgroundStyle) { + /// Solid color background + MBProgressHUDBackgroundStyleSolidColor, + /// UIVisualEffectView or UIToolbar.layer background view + MBProgressHUDBackgroundStyleBlur +}; + +typedef void (^MBProgressHUDCompletionBlock)(void); + + +NS_ASSUME_NONNULL_BEGIN + + +/** + * Displays a simple HUD window containing a progress indicator and two optional labels for short messages. + * + * This is a simple drop-in class for displaying a progress HUD view similar to Apple's private UIProgressHUD class. + * The MBProgressHUD window spans over the entire space given to it by the initWithFrame: constructor and catches all + * user input on this region, thereby preventing the user operations on components below the view. + * + * @note To still allow touches to pass through the HUD, you can set hud.userInteractionEnabled = NO. + * @attention MBProgressHUD is a UI class and should therefore only be accessed on the main thread. + */ +@interface MBProgressHUD : UIView + +/** + * Creates a new HUD, adds it to provided view and shows it. The counterpart to this method is hideHUDForView:animated:. + * + * @note This method sets removeFromSuperViewOnHide. The HUD will automatically be removed from the view hierarchy when hidden. + * + * @param view The view that the HUD will be added to + * @param animated If set to YES the HUD will appear using the current animationType. If set to NO the HUD will not use + * animations while appearing. + * @return A reference to the created HUD. + * + * @see hideHUDForView:animated: + * @see animationType + */ ++ (instancetype)showHUDAddedTo:(UIView *)view animated:(BOOL)animated; + +/// @name Showing and hiding + +/** + * Finds the top-most HUD subview that hasn't finished and hides it. The counterpart to this method is showHUDAddedTo:animated:. + * + * @note This method sets removeFromSuperViewOnHide. The HUD will automatically be removed from the view hierarchy when hidden. + * + * @param view The view that is going to be searched for a HUD subview. + * @param animated If set to YES the HUD will disappear using the current animationType. If set to NO the HUD will not use + * animations while disappearing. + * @return YES if a HUD was found and removed, NO otherwise. + * + * @see showHUDAddedTo:animated: + * @see animationType + */ ++ (BOOL)hideHUDForView:(UIView *)view animated:(BOOL)animated; + +/** + * Finds the top-most HUD subview that hasn't finished and returns it. + * + * @param view The view that is going to be searched. + * @return A reference to the last HUD subview discovered. + */ ++ (nullable MBProgressHUD *)HUDForView:(UIView *)view NS_SWIFT_NAME(forView(_:)); + +/** + * A convenience constructor that initializes the HUD with the view's bounds. Calls the designated constructor with + * view.bounds as the parameter. + * + * @param view The view instance that will provide the bounds for the HUD. Should be the same instance as + * the HUD's superview (i.e., the view that the HUD will be added to). + */ +- (instancetype)initWithView:(UIView *)view; + +/** + * Displays the HUD. + * + * @note You need to make sure that the main thread completes its run loop soon after this method call so that + * the user interface can be updated. Call this method when your task is already set up to be executed in a new thread + * (e.g., when using something like NSOperation or making an asynchronous call like NSURLRequest). + * + * @param animated If set to YES the HUD will appear using the current animationType. If set to NO the HUD will not use + * animations while appearing. + * + * @see animationType + */ +- (void)showAnimated:(BOOL)animated; + +/** + * Hides the HUD. This still calls the hudWasHidden: delegate. This is the counterpart of the show: method. Use it to + * hide the HUD when your task completes. + * + * @param animated If set to YES the HUD will disappear using the current animationType. If set to NO the HUD will not use + * animations while disappearing. + * + * @see animationType + */ +- (void)hideAnimated:(BOOL)animated; + +/** + * Hides the HUD after a delay. This still calls the hudWasHidden: delegate. This is the counterpart of the show: method. Use it to + * hide the HUD when your task completes. + * + * @param animated If set to YES the HUD will disappear using the current animationType. If set to NO the HUD will not use + * animations while disappearing. + * @param delay Delay in seconds until the HUD is hidden. + * + * @see animationType + */ +- (void)hideAnimated:(BOOL)animated afterDelay:(NSTimeInterval)delay; + +/** + * The HUD delegate object. Receives HUD state notifications. + */ +@property (weak, nonatomic) id delegate; + +/** + * Called after the HUD is hidden. + */ +@property (copy, nullable) MBProgressHUDCompletionBlock completionBlock; + +/** + * Grace period is the time (in seconds) that the invoked method may be run without + * showing the HUD. If the task finishes before the grace time runs out, the HUD will + * not be shown at all. + * This may be used to prevent HUD display for very short tasks. + * Defaults to 0 (no grace time). + * @note The graceTime needs to be set before the hud is shown. You thus can't use `showHUDAddedTo:animated:`, + * but instead need to alloc / init the HUD, configure the grace time and than show it manually. + */ +@property (assign, nonatomic) NSTimeInterval graceTime; + +/** + * The minimum time (in seconds) that the HUD is shown. + * This avoids the problem of the HUD being shown and than instantly hidden. + * Defaults to 0 (no minimum show time). + */ +@property (assign, nonatomic) NSTimeInterval minShowTime; + +/** + * Removes the HUD from its parent view when hidden. + * Defaults to NO. + */ +@property (assign, nonatomic) BOOL removeFromSuperViewOnHide; + +/// @name Appearance + +/** + * MBProgressHUD operation mode. The default is MBProgressHUDModeIndeterminate. + */ +@property (assign, nonatomic) MBProgressHUDMode mode; + +/** + * A color that gets forwarded to all labels and supported indicators. Also sets the tintColor + * for custom views on iOS 7+. Set to nil to manage color individually. + * Defaults to semi-translucent black on iOS 7 and later and white on earlier iOS versions. + */ +@property (strong, nonatomic, nullable) UIColor *contentColor UI_APPEARANCE_SELECTOR; + +/** + * The animation type that should be used when the HUD is shown and hidden. + */ +@property (assign, nonatomic) MBProgressHUDAnimation animationType UI_APPEARANCE_SELECTOR; + +/** + * The bezel offset relative to the center of the view. You can use MBProgressMaxOffset + * and -MBProgressMaxOffset to move the HUD all the way to the screen edge in each direction. + * E.g., CGPointMake(0.f, MBProgressMaxOffset) would position the HUD centered on the bottom edge. + */ +@property (assign, nonatomic) CGPoint offset UI_APPEARANCE_SELECTOR; + +/** + * The amount of space between the HUD edge and the HUD elements (labels, indicators or custom views). + * This also represents the minimum bezel distance to the edge of the HUD view. + * Defaults to 20.f + */ +@property (assign, nonatomic) CGFloat margin UI_APPEARANCE_SELECTOR; + +/** + * The minimum size of the HUD bezel. Defaults to CGSizeZero (no minimum size). + */ +@property (assign, nonatomic) CGSize minSize UI_APPEARANCE_SELECTOR; + +/** + * Force the HUD dimensions to be equal if possible. + */ +@property (assign, nonatomic, getter = isSquare) BOOL square UI_APPEARANCE_SELECTOR; + +/** + * When enabled, the bezel center gets slightly affected by the device accelerometer data. + * Defaults to NO. + * + * @note This can cause main thread checker assertions on certain devices. https://github.com/jdg/MBProgressHUD/issues/552 + */ +@property (assign, nonatomic, getter=areDefaultMotionEffectsEnabled) BOOL defaultMotionEffectsEnabled UI_APPEARANCE_SELECTOR; + +/// @name Progress + +/** + * The progress of the progress indicator, from 0.0 to 1.0. Defaults to 0.0. + */ +@property (assign, nonatomic) float progress; + +/// @name ProgressObject + +/** + * The NSProgress object feeding the progress information to the progress indicator. + */ +@property (strong, nonatomic, nullable) NSProgress *progressObject; + +/// @name Views + +/** + * The view containing the labels and indicator (or customView). + */ +@property (strong, nonatomic, readonly) MBBackgroundView *bezelView; + +/** + * View covering the entire HUD area, placed behind bezelView. + */ +@property (strong, nonatomic, readonly) MBBackgroundView *backgroundView; + +/** + * The UIView (e.g., a UIImageView) to be shown when the HUD is in MBProgressHUDModeCustomView. + * The view should implement intrinsicContentSize for proper sizing. For best results use approximately 37 by 37 pixels. + */ +@property (strong, nonatomic, nullable) UIView *customView; + +/** + * A label that holds an optional short message to be displayed below the activity indicator. The HUD is automatically resized to fit + * the entire text. + */ +@property (strong, nonatomic, readonly) UILabel *label; + +/** + * A label that holds an optional details message displayed below the labelText message. The details text can span multiple lines. + */ +@property (strong, nonatomic, readonly) UILabel *detailsLabel; + +/** + * A button that is placed below the labels. Visible only if a target / action is added and a title is assigned.. + */ +@property (strong, nonatomic, readonly) UIButton *button; + +@end + + +@protocol MBProgressHUDDelegate + +@optional + +/** + * Called after the HUD was fully hidden from the screen. + */ +- (void)hudWasHidden:(MBProgressHUD *)hud; + +@end + + +/** + * A progress view for showing definite progress by filling up a circle (pie chart). + */ +@interface MBRoundProgressView : UIView + +/** + * Progress (0.0 to 1.0) + */ +@property (nonatomic, assign) float progress; + +/** + * Indicator progress color. + * Defaults to white [UIColor whiteColor]. + */ +@property (nonatomic, strong) UIColor *progressTintColor; + +/** + * Indicator background (non-progress) color. + * Only applicable on iOS versions older than iOS 7. + * Defaults to translucent white (alpha 0.1). + */ +@property (nonatomic, strong) UIColor *backgroundTintColor; + +/* + * Display mode - NO = round or YES = annular. Defaults to round. + */ +@property (nonatomic, assign, getter = isAnnular) BOOL annular; + +@end + + +/** + * A flat bar progress view. + */ +@interface MBBarProgressView : UIView + +/** + * Progress (0.0 to 1.0) + */ +@property (nonatomic, assign) float progress; + +/** + * Bar border line color. + * Defaults to white [UIColor whiteColor]. + */ +@property (nonatomic, strong) UIColor *lineColor; + +/** + * Bar background color. + * Defaults to clear [UIColor clearColor]; + */ +@property (nonatomic, strong) UIColor *progressRemainingColor; + +/** + * Bar progress color. + * Defaults to white [UIColor whiteColor]. + */ +@property (nonatomic, strong) UIColor *progressColor; + +@end + + +@interface MBBackgroundView : UIView + +/** + * The background style. + * Defaults to MBProgressHUDBackgroundStyleBlur. + */ +@property (nonatomic) MBProgressHUDBackgroundStyle style; + +/** + * The blur effect style, when using MBProgressHUDBackgroundStyleBlur. + * Defaults to UIBlurEffectStyleLight. + */ +@property (nonatomic) UIBlurEffectStyle blurEffectStyle; + +/** + * The background color or the blur tint color. + * + * Defaults to nil on iOS 13 and later and + * `[UIColor colorWithWhite:0.8f alpha:0.6f]` + * on older systems. + */ +@property (nonatomic, strong, nullable) UIColor *color; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/MBProgressHUD/MBProgressHUD.m b/Pods/MBProgressHUD/MBProgressHUD.m new file mode 100644 index 0000000..a2829a3 --- /dev/null +++ b/Pods/MBProgressHUD/MBProgressHUD.m @@ -0,0 +1,1194 @@ +// +// MBProgressHUD.m +// Version 1.2.0 +// Created by Matej Bukovinski on 2.4.09. +// + +#import "MBProgressHUD.h" +#import + +#define MBMainThreadAssert() NSAssert([NSThread isMainThread], @"MBProgressHUD needs to be accessed on the main thread."); + +CGFloat const MBProgressMaxOffset = 1000000.f; + +static const CGFloat MBDefaultPadding = 4.f; +static const CGFloat MBDefaultLabelFontSize = 16.f; +static const CGFloat MBDefaultDetailsLabelFontSize = 12.f; + + +@interface MBProgressHUD () + +@property (nonatomic, assign) BOOL useAnimation; +@property (nonatomic, assign, getter=hasFinished) BOOL finished; +@property (nonatomic, strong) UIView *indicator; +@property (nonatomic, strong) NSDate *showStarted; +@property (nonatomic, strong) NSArray *paddingConstraints; +@property (nonatomic, strong) NSArray *bezelConstraints; +@property (nonatomic, strong) UIView *topSpacer; +@property (nonatomic, strong) UIView *bottomSpacer; +@property (nonatomic, strong) UIMotionEffectGroup *bezelMotionEffects; +@property (nonatomic, weak) NSTimer *graceTimer; +@property (nonatomic, weak) NSTimer *minShowTimer; +@property (nonatomic, weak) NSTimer *hideDelayTimer; +@property (nonatomic, weak) CADisplayLink *progressObjectDisplayLink; + +@end + + +@interface MBProgressHUDRoundedButton : UIButton +@end + + +@implementation MBProgressHUD + +#pragma mark - Class methods + ++ (instancetype)showHUDAddedTo:(UIView *)view animated:(BOOL)animated { + MBProgressHUD *hud = [[self alloc] initWithView:view]; + hud.removeFromSuperViewOnHide = YES; + [view addSubview:hud]; + [hud showAnimated:animated]; + return hud; +} + ++ (BOOL)hideHUDForView:(UIView *)view animated:(BOOL)animated { + MBProgressHUD *hud = [self HUDForView:view]; + if (hud != nil) { + hud.removeFromSuperViewOnHide = YES; + [hud hideAnimated:animated]; + return YES; + } + return NO; +} + ++ (MBProgressHUD *)HUDForView:(UIView *)view { + NSEnumerator *subviewsEnum = [view.subviews reverseObjectEnumerator]; + for (UIView *subview in subviewsEnum) { + if ([subview isKindOfClass:self]) { + MBProgressHUD *hud = (MBProgressHUD *)subview; + if (hud.hasFinished == NO) { + return hud; + } + } + } + return nil; +} + +#pragma mark - Lifecycle + +- (void)commonInit { + // Set default values for properties + _animationType = MBProgressHUDAnimationFade; + _mode = MBProgressHUDModeIndeterminate; + _margin = 20.0f; + _defaultMotionEffectsEnabled = NO; + + if (@available(iOS 13.0, tvOS 13, *)) { + _contentColor = [[UIColor labelColor] colorWithAlphaComponent:0.7f]; + } else { + _contentColor = [UIColor colorWithWhite:0.f alpha:0.7f]; + } + + // Transparent background + self.opaque = NO; + self.backgroundColor = [UIColor clearColor]; + // Make it invisible for now + self.alpha = 0.0f; + self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + self.layer.allowsGroupOpacity = NO; + + [self setupViews]; + [self updateIndicators]; + [self registerForNotifications]; +} + +- (instancetype)initWithFrame:(CGRect)frame { + if ((self = [super initWithFrame:frame])) { + [self commonInit]; + } + return self; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if ((self = [super initWithCoder:aDecoder])) { + [self commonInit]; + } + return self; +} + +- (id)initWithView:(UIView *)view { + NSAssert(view, @"View must not be nil."); + return [self initWithFrame:view.bounds]; +} + +- (void)dealloc { + [self unregisterFromNotifications]; +} + +#pragma mark - Show & hide + +- (void)showAnimated:(BOOL)animated { + MBMainThreadAssert(); + [self.minShowTimer invalidate]; + self.useAnimation = animated; + self.finished = NO; + // If the grace time is set, postpone the HUD display + if (self.graceTime > 0.0) { + NSTimer *timer = [NSTimer timerWithTimeInterval:self.graceTime target:self selector:@selector(handleGraceTimer:) userInfo:nil repeats:NO]; + [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; + self.graceTimer = timer; + } + // ... otherwise show the HUD immediately + else { + [self showUsingAnimation:self.useAnimation]; + } +} + +- (void)hideAnimated:(BOOL)animated { + MBMainThreadAssert(); + [self.graceTimer invalidate]; + self.useAnimation = animated; + self.finished = YES; + // If the minShow time is set, calculate how long the HUD was shown, + // and postpone the hiding operation if necessary + if (self.minShowTime > 0.0 && self.showStarted) { + NSTimeInterval interv = [[NSDate date] timeIntervalSinceDate:self.showStarted]; + if (interv < self.minShowTime) { + NSTimer *timer = [NSTimer timerWithTimeInterval:(self.minShowTime - interv) target:self selector:@selector(handleMinShowTimer:) userInfo:nil repeats:NO]; + [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; + self.minShowTimer = timer; + return; + } + } + // ... otherwise hide the HUD immediately + [self hideUsingAnimation:self.useAnimation]; +} + +- (void)hideAnimated:(BOOL)animated afterDelay:(NSTimeInterval)delay { + // Cancel any scheduled hideAnimated:afterDelay: calls + [self.hideDelayTimer invalidate]; + + NSTimer *timer = [NSTimer timerWithTimeInterval:delay target:self selector:@selector(handleHideTimer:) userInfo:@(animated) repeats:NO]; + [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; + self.hideDelayTimer = timer; +} + +#pragma mark - Timer callbacks + +- (void)handleGraceTimer:(NSTimer *)theTimer { + // Show the HUD only if the task is still running + if (!self.hasFinished) { + [self showUsingAnimation:self.useAnimation]; + } +} + +- (void)handleMinShowTimer:(NSTimer *)theTimer { + [self hideUsingAnimation:self.useAnimation]; +} + +- (void)handleHideTimer:(NSTimer *)timer { + [self hideAnimated:[timer.userInfo boolValue]]; +} + +#pragma mark - View Hierrarchy + +- (void)didMoveToSuperview { + [self updateForCurrentOrientationAnimated:NO]; +} + +#pragma mark - Internal show & hide operations + +- (void)showUsingAnimation:(BOOL)animated { + // Cancel any previous animations + [self.bezelView.layer removeAllAnimations]; + [self.backgroundView.layer removeAllAnimations]; + + // Cancel any scheduled hideAnimated:afterDelay: calls + [self.hideDelayTimer invalidate]; + + self.showStarted = [NSDate date]; + self.alpha = 1.f; + + // Needed in case we hide and re-show with the same NSProgress object attached. + [self setNSProgressDisplayLinkEnabled:YES]; + + // Set up motion effects only at this point to avoid needlessly + // creating the effect if it was disabled after initialization. + [self updateBezelMotionEffects]; + + if (animated) { + [self animateIn:YES withType:self.animationType completion:NULL]; + } else { + self.bezelView.alpha = 1.f; + self.backgroundView.alpha = 1.f; + } +} + +- (void)hideUsingAnimation:(BOOL)animated { + // Cancel any scheduled hideAnimated:afterDelay: calls. + // This needs to happen here instead of in done, + // to avoid races if another hideAnimated:afterDelay: + // call comes in while the HUD is animating out. + [self.hideDelayTimer invalidate]; + + if (animated && self.showStarted) { + self.showStarted = nil; + [self animateIn:NO withType:self.animationType completion:^(BOOL finished) { + [self done]; + }]; + } else { + self.showStarted = nil; + self.bezelView.alpha = 0.f; + self.backgroundView.alpha = 1.f; + [self done]; + } +} + +- (void)animateIn:(BOOL)animatingIn withType:(MBProgressHUDAnimation)type completion:(void(^)(BOOL finished))completion { + // Automatically determine the correct zoom animation type + if (type == MBProgressHUDAnimationZoom) { + type = animatingIn ? MBProgressHUDAnimationZoomIn : MBProgressHUDAnimationZoomOut; + } + + CGAffineTransform small = CGAffineTransformMakeScale(0.5f, 0.5f); + CGAffineTransform large = CGAffineTransformMakeScale(1.5f, 1.5f); + + // Set starting state + UIView *bezelView = self.bezelView; + if (animatingIn && bezelView.alpha == 0.f && type == MBProgressHUDAnimationZoomIn) { + bezelView.transform = small; + } else if (animatingIn && bezelView.alpha == 0.f && type == MBProgressHUDAnimationZoomOut) { + bezelView.transform = large; + } + + // Perform animations + dispatch_block_t animations = ^{ + if (animatingIn) { + bezelView.transform = CGAffineTransformIdentity; + } else if (!animatingIn && type == MBProgressHUDAnimationZoomIn) { + bezelView.transform = large; + } else if (!animatingIn && type == MBProgressHUDAnimationZoomOut) { + bezelView.transform = small; + } + CGFloat alpha = animatingIn ? 1.f : 0.f; + bezelView.alpha = alpha; + self.backgroundView.alpha = alpha; + }; + [UIView animateWithDuration:0.3 delay:0. usingSpringWithDamping:1.f initialSpringVelocity:0.f options:UIViewAnimationOptionBeginFromCurrentState animations:animations completion:completion]; +} + +- (void)done { + [self setNSProgressDisplayLinkEnabled:NO]; + + if (self.hasFinished) { + self.alpha = 0.0f; + if (self.removeFromSuperViewOnHide) { + [self removeFromSuperview]; + } + } + MBProgressHUDCompletionBlock completionBlock = self.completionBlock; + if (completionBlock) { + completionBlock(); + } + id delegate = self.delegate; + if ([delegate respondsToSelector:@selector(hudWasHidden:)]) { + [delegate performSelector:@selector(hudWasHidden:) withObject:self]; + } +} + +#pragma mark - UI + +- (void)setupViews { + UIColor *defaultColor = self.contentColor; + + MBBackgroundView *backgroundView = [[MBBackgroundView alloc] initWithFrame:self.bounds]; + backgroundView.style = MBProgressHUDBackgroundStyleSolidColor; + backgroundView.backgroundColor = [UIColor clearColor]; + backgroundView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + backgroundView.alpha = 0.f; + [self addSubview:backgroundView]; + _backgroundView = backgroundView; + + MBBackgroundView *bezelView = [MBBackgroundView new]; + bezelView.translatesAutoresizingMaskIntoConstraints = NO; + bezelView.layer.cornerRadius = 5.f; + bezelView.alpha = 0.f; + [self addSubview:bezelView]; + _bezelView = bezelView; + + UILabel *label = [UILabel new]; + label.adjustsFontSizeToFitWidth = NO; + label.textAlignment = NSTextAlignmentCenter; + label.textColor = defaultColor; + label.font = [UIFont boldSystemFontOfSize:MBDefaultLabelFontSize]; + label.opaque = NO; + label.backgroundColor = [UIColor clearColor]; + _label = label; + + UILabel *detailsLabel = [UILabel new]; + detailsLabel.adjustsFontSizeToFitWidth = NO; + detailsLabel.textAlignment = NSTextAlignmentCenter; + detailsLabel.textColor = defaultColor; + detailsLabel.numberOfLines = 0; + detailsLabel.font = [UIFont boldSystemFontOfSize:MBDefaultDetailsLabelFontSize]; + detailsLabel.opaque = NO; + detailsLabel.backgroundColor = [UIColor clearColor]; + _detailsLabel = detailsLabel; + + UIButton *button = [MBProgressHUDRoundedButton buttonWithType:UIButtonTypeCustom]; + button.titleLabel.textAlignment = NSTextAlignmentCenter; + button.titleLabel.font = [UIFont boldSystemFontOfSize:MBDefaultDetailsLabelFontSize]; + [button setTitleColor:defaultColor forState:UIControlStateNormal]; + _button = button; + + for (UIView *view in @[label, detailsLabel, button]) { + view.translatesAutoresizingMaskIntoConstraints = NO; + [view setContentCompressionResistancePriority:998.f forAxis:UILayoutConstraintAxisHorizontal]; + [view setContentCompressionResistancePriority:998.f forAxis:UILayoutConstraintAxisVertical]; + [bezelView addSubview:view]; + } + + UIView *topSpacer = [UIView new]; + topSpacer.translatesAutoresizingMaskIntoConstraints = NO; + topSpacer.hidden = YES; + [bezelView addSubview:topSpacer]; + _topSpacer = topSpacer; + + UIView *bottomSpacer = [UIView new]; + bottomSpacer.translatesAutoresizingMaskIntoConstraints = NO; + bottomSpacer.hidden = YES; + [bezelView addSubview:bottomSpacer]; + _bottomSpacer = bottomSpacer; +} + +- (void)updateIndicators { + UIView *indicator = self.indicator; + BOOL isActivityIndicator = [indicator isKindOfClass:[UIActivityIndicatorView class]]; + BOOL isRoundIndicator = [indicator isKindOfClass:[MBRoundProgressView class]]; + + MBProgressHUDMode mode = self.mode; + if (mode == MBProgressHUDModeIndeterminate) { + if (!isActivityIndicator) { + // Update to indeterminate indicator + UIActivityIndicatorView *activityIndicator; + [indicator removeFromSuperview]; +#if !TARGET_OS_MACCATALYST + if (@available(iOS 13.0, tvOS 13.0, *)) { +#endif + activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleLarge]; + activityIndicator.color = [UIColor whiteColor]; +#if !TARGET_OS_MACCATALYST + } else { + activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; + } +#endif + [activityIndicator startAnimating]; + indicator = activityIndicator; + [self.bezelView addSubview:indicator]; + } + } + else if (mode == MBProgressHUDModeDeterminateHorizontalBar) { + // Update to bar determinate indicator + [indicator removeFromSuperview]; + indicator = [[MBBarProgressView alloc] init]; + [self.bezelView addSubview:indicator]; + } + else if (mode == MBProgressHUDModeDeterminate || mode == MBProgressHUDModeAnnularDeterminate) { + if (!isRoundIndicator) { + // Update to determinante indicator + [indicator removeFromSuperview]; + indicator = [[MBRoundProgressView alloc] init]; + [self.bezelView addSubview:indicator]; + } + if (mode == MBProgressHUDModeAnnularDeterminate) { + [(MBRoundProgressView *)indicator setAnnular:YES]; + } + } + else if (mode == MBProgressHUDModeCustomView && self.customView != indicator) { + // Update custom view indicator + [indicator removeFromSuperview]; + indicator = self.customView; + [self.bezelView addSubview:indicator]; + } + else if (mode == MBProgressHUDModeText) { + [indicator removeFromSuperview]; + indicator = nil; + } + indicator.translatesAutoresizingMaskIntoConstraints = NO; + self.indicator = indicator; + + if ([indicator respondsToSelector:@selector(setProgress:)]) { + [(id)indicator setValue:@(self.progress) forKey:@"progress"]; + } + + [indicator setContentCompressionResistancePriority:998.f forAxis:UILayoutConstraintAxisHorizontal]; + [indicator setContentCompressionResistancePriority:998.f forAxis:UILayoutConstraintAxisVertical]; + + [self updateViewsForColor:self.contentColor]; + [self setNeedsUpdateConstraints]; +} + +- (void)updateViewsForColor:(UIColor *)color { + if (!color) return; + + self.label.textColor = color; + self.detailsLabel.textColor = color; + [self.button setTitleColor:color forState:UIControlStateNormal]; + + // UIAppearance settings are prioritized. If they are preset the set color is ignored. + + UIView *indicator = self.indicator; + if ([indicator isKindOfClass:[UIActivityIndicatorView class]]) { + UIActivityIndicatorView *appearance = nil; +#if __IPHONE_OS_VERSION_MIN_REQUIRED < 90000 + appearance = [UIActivityIndicatorView appearanceWhenContainedIn:[MBProgressHUD class], nil]; +#else + // For iOS 9+ + appearance = [UIActivityIndicatorView appearanceWhenContainedInInstancesOfClasses:@[[MBProgressHUD class]]]; +#endif + + if (appearance.color == nil) { + ((UIActivityIndicatorView *)indicator).color = color; + } + } else if ([indicator isKindOfClass:[MBRoundProgressView class]]) { + MBRoundProgressView *appearance = nil; +#if __IPHONE_OS_VERSION_MIN_REQUIRED < 90000 + appearance = [MBRoundProgressView appearanceWhenContainedIn:[MBProgressHUD class], nil]; +#else + appearance = [MBRoundProgressView appearanceWhenContainedInInstancesOfClasses:@[[MBProgressHUD class]]]; +#endif + if (appearance.progressTintColor == nil) { + ((MBRoundProgressView *)indicator).progressTintColor = color; + } + if (appearance.backgroundTintColor == nil) { + ((MBRoundProgressView *)indicator).backgroundTintColor = [color colorWithAlphaComponent:0.1]; + } + } else if ([indicator isKindOfClass:[MBBarProgressView class]]) { + MBBarProgressView *appearance = nil; +#if __IPHONE_OS_VERSION_MIN_REQUIRED < 90000 + appearance = [MBBarProgressView appearanceWhenContainedIn:[MBProgressHUD class], nil]; +#else + appearance = [MBBarProgressView appearanceWhenContainedInInstancesOfClasses:@[[MBProgressHUD class]]]; +#endif + if (appearance.progressColor == nil) { + ((MBBarProgressView *)indicator).progressColor = color; + } + if (appearance.lineColor == nil) { + ((MBBarProgressView *)indicator).lineColor = color; + } + } else { + [indicator setTintColor:color]; + } +} + +- (void)updateBezelMotionEffects { + MBBackgroundView *bezelView = self.bezelView; + UIMotionEffectGroup *bezelMotionEffects = self.bezelMotionEffects; + + if (self.defaultMotionEffectsEnabled && !bezelMotionEffects) { + CGFloat effectOffset = 10.f; + UIInterpolatingMotionEffect *effectX = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x" type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis]; + effectX.maximumRelativeValue = @(effectOffset); + effectX.minimumRelativeValue = @(-effectOffset); + + UIInterpolatingMotionEffect *effectY = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.y" type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis]; + effectY.maximumRelativeValue = @(effectOffset); + effectY.minimumRelativeValue = @(-effectOffset); + + UIMotionEffectGroup *group = [[UIMotionEffectGroup alloc] init]; + group.motionEffects = @[effectX, effectY]; + + self.bezelMotionEffects = group; + [bezelView addMotionEffect:group]; + } else if (bezelMotionEffects) { + self.bezelMotionEffects = nil; + [bezelView removeMotionEffect:bezelMotionEffects]; + } +} + +#pragma mark - Layout + +- (void)updateConstraints { + UIView *bezel = self.bezelView; + UIView *topSpacer = self.topSpacer; + UIView *bottomSpacer = self.bottomSpacer; + CGFloat margin = self.margin; + NSMutableArray *bezelConstraints = [NSMutableArray array]; + NSDictionary *metrics = @{@"margin": @(margin)}; + + NSMutableArray *subviews = [NSMutableArray arrayWithObjects:self.topSpacer, self.label, self.detailsLabel, self.button, self.bottomSpacer, nil]; + if (self.indicator) [subviews insertObject:self.indicator atIndex:1]; + + // Remove existing constraints + [self removeConstraints:self.constraints]; + [topSpacer removeConstraints:topSpacer.constraints]; + [bottomSpacer removeConstraints:bottomSpacer.constraints]; + if (self.bezelConstraints) { + [bezel removeConstraints:self.bezelConstraints]; + self.bezelConstraints = nil; + } + + // Center bezel in container (self), applying the offset if set + CGPoint offset = self.offset; + NSMutableArray *centeringConstraints = [NSMutableArray array]; + [centeringConstraints addObject:[NSLayoutConstraint constraintWithItem:bezel attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterX multiplier:1.f constant:offset.x]]; + [centeringConstraints addObject:[NSLayoutConstraint constraintWithItem:bezel attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterY multiplier:1.f constant:offset.y]]; + [self applyPriority:998.f toConstraints:centeringConstraints]; + [self addConstraints:centeringConstraints]; + + // Ensure minimum side margin is kept + NSMutableArray *sideConstraints = [NSMutableArray array]; + [sideConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"|-(>=margin)-[bezel]-(>=margin)-|" options:0 metrics:metrics views:NSDictionaryOfVariableBindings(bezel)]]; + [sideConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(>=margin)-[bezel]-(>=margin)-|" options:0 metrics:metrics views:NSDictionaryOfVariableBindings(bezel)]]; + [self applyPriority:999.f toConstraints:sideConstraints]; + [self addConstraints:sideConstraints]; + + // Minimum bezel size, if set + CGSize minimumSize = self.minSize; + if (!CGSizeEqualToSize(minimumSize, CGSizeZero)) { + NSMutableArray *minSizeConstraints = [NSMutableArray array]; + [minSizeConstraints addObject:[NSLayoutConstraint constraintWithItem:bezel attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.f constant:minimumSize.width]]; + [minSizeConstraints addObject:[NSLayoutConstraint constraintWithItem:bezel attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.f constant:minimumSize.height]]; + [self applyPriority:997.f toConstraints:minSizeConstraints]; + [bezelConstraints addObjectsFromArray:minSizeConstraints]; + } + + // Square aspect ratio, if set + if (self.square) { + NSLayoutConstraint *square = [NSLayoutConstraint constraintWithItem:bezel attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:bezel attribute:NSLayoutAttributeWidth multiplier:1.f constant:0]; + square.priority = 997.f; + [bezelConstraints addObject:square]; + } + + // Top and bottom spacing + [topSpacer addConstraint:[NSLayoutConstraint constraintWithItem:topSpacer attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.f constant:margin]]; + [bottomSpacer addConstraint:[NSLayoutConstraint constraintWithItem:bottomSpacer attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.f constant:margin]]; + // Top and bottom spaces should be equal + [bezelConstraints addObject:[NSLayoutConstraint constraintWithItem:topSpacer attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:bottomSpacer attribute:NSLayoutAttributeHeight multiplier:1.f constant:0.f]]; + + // Layout subviews in bezel + NSMutableArray *paddingConstraints = [NSMutableArray new]; + [subviews enumerateObjectsUsingBlock:^(UIView *view, NSUInteger idx, BOOL *stop) { + // Center in bezel + [bezelConstraints addObject:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:bezel attribute:NSLayoutAttributeCenterX multiplier:1.f constant:0.f]]; + // Ensure the minimum edge margin is kept + [bezelConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"|-(>=margin)-[view]-(>=margin)-|" options:0 metrics:metrics views:NSDictionaryOfVariableBindings(view)]]; + // Element spacing + if (idx == 0) { + // First, ensure spacing to bezel edge + [bezelConstraints addObject:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:bezel attribute:NSLayoutAttributeTop multiplier:1.f constant:0.f]]; + } else if (idx == subviews.count - 1) { + // Last, ensure spacing to bezel edge + [bezelConstraints addObject:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:bezel attribute:NSLayoutAttributeBottom multiplier:1.f constant:0.f]]; + } + if (idx > 0) { + // Has previous + NSLayoutConstraint *padding = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:subviews[idx - 1] attribute:NSLayoutAttributeBottom multiplier:1.f constant:0.f]; + [bezelConstraints addObject:padding]; + [paddingConstraints addObject:padding]; + } + }]; + + [bezel addConstraints:bezelConstraints]; + self.bezelConstraints = bezelConstraints; + + self.paddingConstraints = [paddingConstraints copy]; + [self updatePaddingConstraints]; + + [super updateConstraints]; +} + +- (void)layoutSubviews { + // There is no need to update constraints if they are going to + // be recreated in [super layoutSubviews] due to needsUpdateConstraints being set. + // This also avoids an issue on iOS 8, where updatePaddingConstraints + // would trigger a zombie object access. + if (!self.needsUpdateConstraints) { + [self updatePaddingConstraints]; + } + [super layoutSubviews]; +} + +- (void)updatePaddingConstraints { + // Set padding dynamically, depending on whether the view is visible or not + __block BOOL hasVisibleAncestors = NO; + [self.paddingConstraints enumerateObjectsUsingBlock:^(NSLayoutConstraint *padding, NSUInteger idx, BOOL *stop) { + UIView *firstView = (UIView *)padding.firstItem; + UIView *secondView = (UIView *)padding.secondItem; + BOOL firstVisible = !firstView.hidden && !CGSizeEqualToSize(firstView.intrinsicContentSize, CGSizeZero); + BOOL secondVisible = !secondView.hidden && !CGSizeEqualToSize(secondView.intrinsicContentSize, CGSizeZero); + // Set if both views are visible or if there's a visible view on top that doesn't have padding + // added relative to the current view yet + padding.constant = (firstVisible && (secondVisible || hasVisibleAncestors)) ? MBDefaultPadding : 0.f; + hasVisibleAncestors |= secondVisible; + }]; +} + +- (void)applyPriority:(UILayoutPriority)priority toConstraints:(NSArray *)constraints { + for (NSLayoutConstraint *constraint in constraints) { + constraint.priority = priority; + } +} + +#pragma mark - Properties + +- (void)setMode:(MBProgressHUDMode)mode { + if (mode != _mode) { + _mode = mode; + [self updateIndicators]; + } +} + +- (void)setCustomView:(UIView *)customView { + if (customView != _customView) { + _customView = customView; + if (self.mode == MBProgressHUDModeCustomView) { + [self updateIndicators]; + } + } +} + +- (void)setOffset:(CGPoint)offset { + if (!CGPointEqualToPoint(offset, _offset)) { + _offset = offset; + [self setNeedsUpdateConstraints]; + } +} + +- (void)setMargin:(CGFloat)margin { + if (margin != _margin) { + _margin = margin; + [self setNeedsUpdateConstraints]; + } +} + +- (void)setMinSize:(CGSize)minSize { + if (!CGSizeEqualToSize(minSize, _minSize)) { + _minSize = minSize; + [self setNeedsUpdateConstraints]; + } +} + +- (void)setSquare:(BOOL)square { + if (square != _square) { + _square = square; + [self setNeedsUpdateConstraints]; + } +} + +- (void)setProgressObjectDisplayLink:(CADisplayLink *)progressObjectDisplayLink { + if (progressObjectDisplayLink != _progressObjectDisplayLink) { + [_progressObjectDisplayLink invalidate]; + + _progressObjectDisplayLink = progressObjectDisplayLink; + + [_progressObjectDisplayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; + } +} + +- (void)setProgressObject:(NSProgress *)progressObject { + if (progressObject != _progressObject) { + _progressObject = progressObject; + [self setNSProgressDisplayLinkEnabled:YES]; + } +} + +- (void)setProgress:(float)progress { + if (progress != _progress) { + _progress = progress; + UIView *indicator = self.indicator; + if ([indicator respondsToSelector:@selector(setProgress:)]) { + [(id)indicator setValue:@(self.progress) forKey:@"progress"]; + } + } +} + +- (void)setContentColor:(UIColor *)contentColor { + if (contentColor != _contentColor && ![contentColor isEqual:_contentColor]) { + _contentColor = contentColor; + [self updateViewsForColor:contentColor]; + } +} + +- (void)setDefaultMotionEffectsEnabled:(BOOL)defaultMotionEffectsEnabled { + if (defaultMotionEffectsEnabled != _defaultMotionEffectsEnabled) { + _defaultMotionEffectsEnabled = defaultMotionEffectsEnabled; + [self updateBezelMotionEffects]; + } +} + +#pragma mark - NSProgress + +- (void)setNSProgressDisplayLinkEnabled:(BOOL)enabled { + // We're using CADisplayLink, because NSProgress can change very quickly and observing it may starve the main thread, + // so we're refreshing the progress only every frame draw + if (enabled && self.progressObject) { + // Only create if not already active. + if (!self.progressObjectDisplayLink) { + self.progressObjectDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateProgressFromProgressObject)]; + } + } else { + self.progressObjectDisplayLink = nil; + } +} + +- (void)updateProgressFromProgressObject { + self.progress = self.progressObject.fractionCompleted; +} + +#pragma mark - Notifications + +- (void)registerForNotifications { +#if !TARGET_OS_TV && !TARGET_OS_MACCATALYST + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + + [nc addObserver:self selector:@selector(statusBarOrientationDidChange:) + name:UIApplicationDidChangeStatusBarOrientationNotification object:nil]; +#endif +} + +- (void)unregisterFromNotifications { +#if !TARGET_OS_TV && !TARGET_OS_MACCATALYST + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc removeObserver:self name:UIApplicationDidChangeStatusBarOrientationNotification object:nil]; +#endif +} + +#if !TARGET_OS_TV && !TARGET_OS_MACCATALYST +- (void)statusBarOrientationDidChange:(NSNotification *)notification { + UIView *superview = self.superview; + if (!superview) { + return; + } else { + [self updateForCurrentOrientationAnimated:YES]; + } +} +#endif + +- (void)updateForCurrentOrientationAnimated:(BOOL)animated { + // Stay in sync with the superview in any case + if (self.superview) { + self.frame = self.superview.bounds; + } + + // Not needed on iOS 8+, compile out when the deployment target allows, + // to avoid sharedApplication problems on extension targets +#if __IPHONE_OS_VERSION_MIN_REQUIRED < 80000 + // Only needed pre iOS 8 when added to a window + BOOL iOS8OrLater = kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_8_0; + if (iOS8OrLater || ![self.superview isKindOfClass:[UIWindow class]]) return; + + // Make extension friendly. Will not get called on extensions (iOS 8+) due to the above check. + // This just ensures we don't get a warning about extension-unsafe API. + Class UIApplicationClass = NSClassFromString(@"UIApplication"); + if (!UIApplicationClass || ![UIApplicationClass respondsToSelector:@selector(sharedApplication)]) return; + + UIApplication *application = [UIApplication performSelector:@selector(sharedApplication)]; + UIInterfaceOrientation orientation = application.statusBarOrientation; + CGFloat radians = 0; + + if (UIInterfaceOrientationIsLandscape(orientation)) { + radians = orientation == UIInterfaceOrientationLandscapeLeft ? -(CGFloat)M_PI_2 : (CGFloat)M_PI_2; + // Window coordinates differ! + self.bounds = CGRectMake(0, 0, self.bounds.size.height, self.bounds.size.width); + } else { + radians = orientation == UIInterfaceOrientationPortraitUpsideDown ? (CGFloat)M_PI : 0.f; + } + + if (animated) { + [UIView animateWithDuration:0.3 animations:^{ + self.transform = CGAffineTransformMakeRotation(radians); + }]; + } else { + self.transform = CGAffineTransformMakeRotation(radians); + } +#endif +} + +@end + + +@implementation MBRoundProgressView + +#pragma mark - Lifecycle + +- (id)init { + return [self initWithFrame:CGRectMake(0.f, 0.f, 37.f, 37.f)]; +} + +- (id)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + self.backgroundColor = [UIColor clearColor]; + self.opaque = NO; + _progress = 0.f; + _annular = NO; + _progressTintColor = [[UIColor alloc] initWithWhite:1.f alpha:1.f]; + _backgroundTintColor = [[UIColor alloc] initWithWhite:1.f alpha:.1f]; + } + return self; +} + +#pragma mark - Layout + +- (CGSize)intrinsicContentSize { + return CGSizeMake(37.f, 37.f); +} + +#pragma mark - Properties + +- (void)setProgress:(float)progress { + if (progress != _progress) { + _progress = progress; + [self setNeedsDisplay]; + } +} + +- (void)setProgressTintColor:(UIColor *)progressTintColor { + NSAssert(progressTintColor, @"The color should not be nil."); + if (progressTintColor != _progressTintColor && ![progressTintColor isEqual:_progressTintColor]) { + _progressTintColor = progressTintColor; + [self setNeedsDisplay]; + } +} + +- (void)setBackgroundTintColor:(UIColor *)backgroundTintColor { + NSAssert(backgroundTintColor, @"The color should not be nil."); + if (backgroundTintColor != _backgroundTintColor && ![backgroundTintColor isEqual:_backgroundTintColor]) { + _backgroundTintColor = backgroundTintColor; + [self setNeedsDisplay]; + } +} + +#pragma mark - Drawing + +- (void)drawRect:(CGRect)rect { + CGContextRef context = UIGraphicsGetCurrentContext(); + + if (_annular) { + // Draw background + CGFloat lineWidth = 2.f; + UIBezierPath *processBackgroundPath = [UIBezierPath bezierPath]; + processBackgroundPath.lineWidth = lineWidth; + processBackgroundPath.lineCapStyle = kCGLineCapButt; + CGPoint center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds)); + CGFloat radius = (self.bounds.size.width - lineWidth)/2; + CGFloat startAngle = - ((float)M_PI / 2); // 90 degrees + CGFloat endAngle = (2 * (float)M_PI) + startAngle; + [processBackgroundPath addArcWithCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES]; + [_backgroundTintColor set]; + [processBackgroundPath stroke]; + // Draw progress + UIBezierPath *processPath = [UIBezierPath bezierPath]; + processPath.lineCapStyle = kCGLineCapSquare; + processPath.lineWidth = lineWidth; + endAngle = (self.progress * 2 * (float)M_PI) + startAngle; + [processPath addArcWithCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES]; + [_progressTintColor set]; + [processPath stroke]; + } else { + // Draw background + CGFloat lineWidth = 2.f; + CGRect allRect = self.bounds; + CGRect circleRect = CGRectInset(allRect, lineWidth/2.f, lineWidth/2.f); + CGPoint center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds)); + [_progressTintColor setStroke]; + [_backgroundTintColor setFill]; + CGContextSetLineWidth(context, lineWidth); + CGContextStrokeEllipseInRect(context, circleRect); + // 90 degrees + CGFloat startAngle = - ((float)M_PI / 2.f); + // Draw progress + UIBezierPath *processPath = [UIBezierPath bezierPath]; + processPath.lineCapStyle = kCGLineCapButt; + processPath.lineWidth = lineWidth * 2.f; + CGFloat radius = (CGRectGetWidth(self.bounds) / 2.f) - (processPath.lineWidth / 2.f); + CGFloat endAngle = (self.progress * 2.f * (float)M_PI) + startAngle; + [processPath addArcWithCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES]; + // Ensure that we don't get color overlapping when _progressTintColor alpha < 1.f. + CGContextSetBlendMode(context, kCGBlendModeCopy); + [_progressTintColor set]; + [processPath stroke]; + } +} + +@end + + +@implementation MBBarProgressView + +#pragma mark - Lifecycle + +- (id)init { + return [self initWithFrame:CGRectMake(.0f, .0f, 120.0f, 20.0f)]; +} + +- (id)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + _progress = 0.f; + _lineColor = [UIColor whiteColor]; + _progressColor = [UIColor whiteColor]; + _progressRemainingColor = [UIColor clearColor]; + self.backgroundColor = [UIColor clearColor]; + self.opaque = NO; + } + return self; +} + +#pragma mark - Layout + +- (CGSize)intrinsicContentSize { + return CGSizeMake(120.f, 10.f); +} + +#pragma mark - Properties + +- (void)setProgress:(float)progress { + if (progress != _progress) { + _progress = progress; + [self setNeedsDisplay]; + } +} + +- (void)setProgressColor:(UIColor *)progressColor { + NSAssert(progressColor, @"The color should not be nil."); + if (progressColor != _progressColor && ![progressColor isEqual:_progressColor]) { + _progressColor = progressColor; + [self setNeedsDisplay]; + } +} + +- (void)setProgressRemainingColor:(UIColor *)progressRemainingColor { + NSAssert(progressRemainingColor, @"The color should not be nil."); + if (progressRemainingColor != _progressRemainingColor && ![progressRemainingColor isEqual:_progressRemainingColor]) { + _progressRemainingColor = progressRemainingColor; + [self setNeedsDisplay]; + } +} + +#pragma mark - Drawing + +- (void)drawRect:(CGRect)rect { + CGContextRef context = UIGraphicsGetCurrentContext(); + + CGContextSetLineWidth(context, 2); + CGContextSetStrokeColorWithColor(context,[_lineColor CGColor]); + CGContextSetFillColorWithColor(context, [_progressRemainingColor CGColor]); + + // Draw background and Border + CGFloat radius = (rect.size.height / 2) - 2; + CGContextMoveToPoint(context, 2, rect.size.height/2); + CGContextAddArcToPoint(context, 2, 2, radius + 2, 2, radius); + CGContextAddArcToPoint(context, rect.size.width - 2, 2, rect.size.width - 2, rect.size.height / 2, radius); + CGContextAddArcToPoint(context, rect.size.width - 2, rect.size.height - 2, rect.size.width - radius - 2, rect.size.height - 2, radius); + CGContextAddArcToPoint(context, 2, rect.size.height - 2, 2, rect.size.height/2, radius); + CGContextDrawPath(context, kCGPathFillStroke); + + CGContextSetFillColorWithColor(context, [_progressColor CGColor]); + radius = radius - 2; + CGFloat amount = self.progress * rect.size.width; + + // Progress in the middle area + if (amount >= radius + 4 && amount <= (rect.size.width - radius - 4)) { + CGContextMoveToPoint(context, 4, rect.size.height/2); + CGContextAddArcToPoint(context, 4, 4, radius + 4, 4, radius); + CGContextAddLineToPoint(context, amount, 4); + CGContextAddLineToPoint(context, amount, radius + 4); + + CGContextMoveToPoint(context, 4, rect.size.height/2); + CGContextAddArcToPoint(context, 4, rect.size.height - 4, radius + 4, rect.size.height - 4, radius); + CGContextAddLineToPoint(context, amount, rect.size.height - 4); + CGContextAddLineToPoint(context, amount, radius + 4); + + CGContextFillPath(context); + } + + // Progress in the right arc + else if (amount > radius + 4) { + CGFloat x = amount - (rect.size.width - radius - 4); + + CGContextMoveToPoint(context, 4, rect.size.height/2); + CGContextAddArcToPoint(context, 4, 4, radius + 4, 4, radius); + CGContextAddLineToPoint(context, rect.size.width - radius - 4, 4); + CGFloat angle = -acos(x/radius); + if (isnan(angle)) angle = 0; + CGContextAddArc(context, rect.size.width - radius - 4, rect.size.height/2, radius, M_PI, angle, 0); + CGContextAddLineToPoint(context, amount, rect.size.height/2); + + CGContextMoveToPoint(context, 4, rect.size.height/2); + CGContextAddArcToPoint(context, 4, rect.size.height - 4, radius + 4, rect.size.height - 4, radius); + CGContextAddLineToPoint(context, rect.size.width - radius - 4, rect.size.height - 4); + angle = acos(x/radius); + if (isnan(angle)) angle = 0; + CGContextAddArc(context, rect.size.width - radius - 4, rect.size.height/2, radius, -M_PI, angle, 1); + CGContextAddLineToPoint(context, amount, rect.size.height/2); + + CGContextFillPath(context); + } + + // Progress is in the left arc + else if (amount < radius + 4 && amount > 0) { + CGContextMoveToPoint(context, 4, rect.size.height/2); + CGContextAddArcToPoint(context, 4, 4, radius + 4, 4, radius); + CGContextAddLineToPoint(context, radius + 4, rect.size.height/2); + + CGContextMoveToPoint(context, 4, rect.size.height/2); + CGContextAddArcToPoint(context, 4, rect.size.height - 4, radius + 4, rect.size.height - 4, radius); + CGContextAddLineToPoint(context, radius + 4, rect.size.height/2); + + CGContextFillPath(context); + } +} + +@end + + +@interface MBBackgroundView () + +@property UIVisualEffectView *effectView; + +@end + + +@implementation MBBackgroundView + +#pragma mark - Lifecycle + +- (instancetype)initWithFrame:(CGRect)frame { + if ((self = [super initWithFrame:frame])) { + _style = MBProgressHUDBackgroundStyleBlur; + if (@available(iOS 13.0, *)) { + #if TARGET_OS_TV + _blurEffectStyle = UIBlurEffectStyleRegular; + #else + _blurEffectStyle = UIBlurEffectStyleSystemThickMaterial; + #endif + // Leaving the color unassigned yields best results. + } else { + _blurEffectStyle = UIBlurEffectStyleLight; + _color = [UIColor colorWithWhite:0.8f alpha:0.6f]; + } + + self.clipsToBounds = YES; + + [self updateForBackgroundStyle]; + } + return self; +} + +#pragma mark - Layout + +- (CGSize)intrinsicContentSize { + // Smallest size possible. Content pushes against this. + return CGSizeZero; +} + +#pragma mark - Appearance + +- (void)setStyle:(MBProgressHUDBackgroundStyle)style { + if (_style != style) { + _style = style; + [self updateForBackgroundStyle]; + } +} + +- (void)setColor:(UIColor *)color { + NSAssert(color, @"The color should not be nil."); + if (color != _color && ![color isEqual:_color]) { + _color = color; + [self updateViewsForColor:color]; + } +} + +- (void)setBlurEffectStyle:(UIBlurEffectStyle)blurEffectStyle { + if (_blurEffectStyle == blurEffectStyle) { + return; + } + + _blurEffectStyle = blurEffectStyle; + + [self updateForBackgroundStyle]; +} + +/////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - Views + +- (void)updateForBackgroundStyle { + [self.effectView removeFromSuperview]; + self.effectView = nil; + + MBProgressHUDBackgroundStyle style = self.style; + if (style == MBProgressHUDBackgroundStyleBlur) { + UIBlurEffect *effect = [UIBlurEffect effectWithStyle:self.blurEffectStyle]; + UIVisualEffectView *effectView = [[UIVisualEffectView alloc] initWithEffect:effect]; + [self insertSubview:effectView atIndex:0]; + effectView.frame = self.bounds; + effectView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; + self.backgroundColor = self.color; + self.layer.allowsGroupOpacity = NO; + self.effectView = effectView; + } else { + self.backgroundColor = self.color; + } +} + +- (void)updateViewsForColor:(UIColor *)color { + if (self.style == MBProgressHUDBackgroundStyleBlur) { + self.backgroundColor = self.color; + } else { + self.backgroundColor = self.color; + } +} + +@end + + +@implementation MBProgressHUDRoundedButton + +#pragma mark - Lifecycle + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + CALayer *layer = self.layer; + layer.borderWidth = 1.f; + } + return self; +} + +#pragma mark - Layout + +- (void)layoutSubviews { + [super layoutSubviews]; + // Fully rounded corners + CGFloat height = CGRectGetHeight(self.bounds); + self.layer.cornerRadius = ceil(height / 2.f); +} + +- (CGSize)intrinsicContentSize { + // Only show if we have associated control events and a title + if ((self.allControlEvents == 0) || ([self titleForState:UIControlStateNormal].length == 0)) + return CGSizeZero; + CGSize size = [super intrinsicContentSize]; + // Add some side padding + size.width += 20.f; + return size; +} + +#pragma mark - Color + +- (void)setTitleColor:(UIColor *)color forState:(UIControlState)state { + [super setTitleColor:color forState:state]; + // Update related colors + [self setHighlighted:self.highlighted]; + self.layer.borderColor = color.CGColor; +} + +- (void)setHighlighted:(BOOL)highlighted { + [super setHighlighted:highlighted]; + UIColor *baseColor = [self titleColorForState:UIControlStateSelected]; + self.backgroundColor = highlighted ? [baseColor colorWithAlphaComponent:0.1f] : [UIColor clearColor]; +} + +@end diff --git a/Pods/MBProgressHUD/README.mdown b/Pods/MBProgressHUD/README.mdown new file mode 100644 index 0000000..c90f5c6 --- /dev/null +++ b/Pods/MBProgressHUD/README.mdown @@ -0,0 +1,138 @@ +# MBProgressHUD + +[![Build Status](https://travis-ci.org/matej/MBProgressHUD.svg?branch=master)](https://travis-ci.org/matej/MBProgressHUD) [![codecov.io](https://codecov.io/github/matej/MBProgressHUD/coverage.svg?branch=master)](https://codecov.io/github/matej/MBProgressHUD?branch=master) + [![SwiftPM compatible](https://img.shields.io/badge/SwiftPM-compatible-brightgreen.svg)](https://github.com/apple/swift-package-manager) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage#adding-frameworks-to-an-application) [![Accio supported](https://img.shields.io/badge/Accio-supported-0A7CF5.svg?style=flat)](https://github.com/JamitLabs/Accio) [![CocoaPods compatible](https://img.shields.io/cocoapods/v/MBProgressHUD.svg?style=flat)](https://cocoapods.org/pods/MBProgressHUD) [![License: MIT](https://img.shields.io/cocoapods/l/MBProgressHUD.svg?style=flat)](http://opensource.org/licenses/MIT) + +`MBProgressHUD` is an iOS drop-in class that displays a translucent HUD with an indicator and/or labels while work is being done in a background thread. The HUD is meant as a replacement for the undocumented, private `UIKit` `UIProgressHUD` with some additional features. + +[![](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/1-small.png)](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/1.png) +[![](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/2-small.png)](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/2.png) +[![](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/3-small.png)](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/3.png) +[![](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/4-small.png)](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/4.png) +[![](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/5-small.png)](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/5.png) +[![](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/6-small.png)](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/6.png) +[![](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/7-small.png)](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/7.png) + +**NOTE:** The class has recently undergone a major rewrite. The old version is available in the [legacy](https://github.com/jdg/MBProgressHUD/tree/legacy) branch, should you need it. + +## Requirements + +`MBProgressHUD` works on iOS 9.0+. It depends on the following Apple frameworks, which should already be included with most Xcode templates: + +* Foundation.framework +* UIKit.framework +* CoreGraphics.framework + +You will need the latest developer tools in order to build `MBProgressHUD`. Old Xcode versions might work, but compatibility will not be explicitly maintained. + +## Adding MBProgressHUD to your project + +### CocoaPods + +[CocoaPods](http://cocoapods.org) is the recommended way to add MBProgressHUD to your project. + +1. Add a pod entry for MBProgressHUD to your Podfile `pod 'MBProgressHUD', '~> 1.2.0'` +2. Install the pod(s) by running `pod install`. +3. Include MBProgressHUD wherever you need it with `#import "MBProgressHUD.h"`. + +### Carthage + +1. Add MBProgressHUD to your Cartfile. e.g., `github "jdg/MBProgressHUD" ~> 1.2.0` +2. Run `carthage update` +3. Follow the rest of the [standard Carthage installation instructions](https://github.com/Carthage/Carthage#adding-frameworks-to-an-application) to add MBProgressHUD to your project. + +### SwiftPM / Accio + +1. Add the following to your `Package.swift`: + ```swift + .package(url: "https://github.com/jdg/MBProgressHUD.git", .upToNextMajor(from: "1.2.0")), + ``` +2. Next, add `MBProgressHUD` to your App targets dependencies like so: + ```swift + .target(name: "App", dependencies: ["MBProgressHUD"]), + ``` +3. Then open your project in Xcode 11+ (SwiftPM) or run `accio update` (Accio). + +### Source files + +Alternatively you can directly add the `MBProgressHUD.h` and `MBProgressHUD.m` source files to your project. + +1. Download the [latest code version](https://github.com/matej/MBProgressHUD/archive/master.zip) or add the repository as a git submodule to your git-tracked project. +2. Open your project in Xcode, then drag and drop `MBProgressHUD.h` and `MBProgressHUD.m` onto your project (use the "Product Navigator view"). Make sure to select Copy items when asked if you extracted the code archive outside of your project. +3. Include MBProgressHUD wherever you need it with `#import "MBProgressHUD.h"`. + +### Static library + +You can also add MBProgressHUD as a static library to your project or workspace. + +1. Download the [latest code version](https://github.com/matej/MBProgressHUD/downloads) or add the repository as a git submodule to your git-tracked project. +2. Open your project in Xcode, then drag and drop `MBProgressHUD.xcodeproj` onto your project or workspace (use the "Product Navigator view"). +3. Select your target and go to the Build phases tab. In the Link Binary With Libraries section select the add button. On the sheet find and add `libMBProgressHUD.a`. You might also need to add `MBProgressHUD` to the Target Dependencies list. +4. Include MBProgressHUD wherever you need it with `#import `. + +## Usage + +The main guideline you need to follow when dealing with MBProgressHUD while running long-running tasks is keeping the main thread work-free, so the UI can be updated promptly. The recommended way of using MBProgressHUD is therefore to set it up on the main thread and then spinning the task, that you want to perform, off onto a new thread. + +```objective-c +[MBProgressHUD showHUDAddedTo:self.view animated:YES]; +dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ + // Do something... + dispatch_async(dispatch_get_main_queue(), ^{ + [MBProgressHUD hideHUDForView:self.view animated:YES]; + }); +}); +``` + +You can add the HUD on any view or window. It is however a good idea to avoid adding the HUD to certain `UIKit` views with complex view hierarchies - like `UITableView` or `UICollectionView`. Those can mutate their subviews in unexpected ways and thereby break HUD display. + +If you need to configure the HUD you can do this by using the MBProgressHUD reference that showHUDAddedTo:animated: returns. + +```objective-c +MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES]; +hud.mode = MBProgressHUDModeAnnularDeterminate; +hud.label.text = @"Loading"; +[self doSomethingInBackgroundWithProgressCallback:^(float progress) { + hud.progress = progress; +} completionCallback:^{ + [hud hideAnimated:YES]; +}]; +``` + +You can also use a `NSProgress` object and MBProgressHUD will update itself when there is progress reported through that object. + +```objective-c +MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES]; +hud.mode = MBProgressHUDModeAnnularDeterminate; +hud.label.text = @"Loading"; +NSProgress *progress = [self doSomethingInBackgroundCompletion:^{ + [hud hideAnimated:YES]; +}]; +hud.progressObject = progress; +``` + +Keep in mind that UI updates, inclining calls to MBProgressHUD should always be done on the main thread. + +If you need to run your long-running task in the main thread, you should perform it with a slight delay, so UIKit will have enough time to update the UI (i.e., draw the HUD) before you block the main thread with your task. + +```objective-c +[MBProgressHUD showHUDAddedTo:self.view animated:YES]; +dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 0.01 * NSEC_PER_SEC); +dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ + // Do something... + [MBProgressHUD hideHUDForView:self.view animated:YES]; +}); +``` + +You should be aware that any HUD updates issued inside the above block won't be displayed until the block completes. + +For more examples, including how to use MBProgressHUD with asynchronous operations such as NSURLConnection, take a look at the bundled demo project. Extensive API documentation is provided in the header file (MBProgressHUD.h). + + +## License + +This code is distributed under the terms and conditions of the [MIT license](LICENSE). + +## Change-log + +A brief summary of each MBProgressHUD release can be found in the [CHANGELOG](CHANGELOG.mdown). diff --git a/Pods/Manifest.lock b/Pods/Manifest.lock index ff55f71..5242fd1 100644 --- a/Pods/Manifest.lock +++ b/Pods/Manifest.lock @@ -15,7 +15,12 @@ PODS: - AFNetworking/UIKit (4.0.1): - AFNetworking/NSURLSession - Bugly (2.6.1) + - DZNEmptyDataSet (1.8.1) + - LookinServer (1.2.8): + - LookinServer/Core (= 1.2.8) + - LookinServer/Core (1.2.8) - Masonry (1.1.0) + - MBProgressHUD (1.2.0) - MJExtension (3.4.2) - MJRefresh (3.7.9) - SDWebImage (5.21.1): @@ -25,16 +30,23 @@ PODS: DEPENDENCIES: - AFNetworking (= 4.0.1) - Bugly (= 2.6.1) + - DZNEmptyDataSet (= 1.8.1) + - LookinServer - Masonry (= 1.1.0) + - MBProgressHUD (= 1.2.0) - MJExtension (= 3.4.2) - MJRefresh (= 3.7.9) + - SDWebImage - SDWebImage (= 5.21.1) SPEC REPOS: https://github.com/CocoaPods/Specs.git: - AFNetworking - Bugly + - DZNEmptyDataSet + - LookinServer - Masonry + - MBProgressHUD - MJExtension - MJRefresh - SDWebImage @@ -42,11 +54,14 @@ SPEC REPOS: SPEC CHECKSUMS: AFNetworking: 3bd23d814e976cd148d7d44c3ab78017b744cd58 Bugly: 217ac2ce5f0f2626d43dbaa4f70764c953a26a31 + DZNEmptyDataSet: 9525833b9e68ac21c30253e1d3d7076cc828eaa7 + LookinServer: 1b2b61c6402ae29fa22182d48f5cd067b4e99e80 Masonry: 678fab65091a9290e40e2832a55e7ab731aad201 + MBProgressHUD: 3ee5efcc380f6a79a7cc9b363dd669c5e1ae7406 MJExtension: e97d164cb411aa9795cf576093a1fa208b4a8dd8 MJRefresh: ff9e531227924c84ce459338414550a05d2aea78 SDWebImage: f29024626962457f3470184232766516dee8dfea -PODFILE CHECKSUM: b3c72fe500149c35040cdd73c1d91fe05777bc5f +PODFILE CHECKSUM: 6e0fcb7cf319a770ac7883c7cf3b1df1a6829e77 COCOAPODS: 1.16.2 diff --git a/Pods/Pods.xcodeproj/project.pbxproj b/Pods/Pods.xcodeproj/project.pbxproj index 5dec3e7..7903662 100644 --- a/Pods/Pods.xcodeproj/project.pbxproj +++ b/Pods/Pods.xcodeproj/project.pbxproj @@ -19,741 +19,1113 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ - 00DAE48C9A4FBCD1FCAA922CA57B45F9 /* SDWebImageDownloaderRequestModifier.m in Sources */ = {isa = PBXBuildFile; fileRef = 06B71FC03BF92D5C7E3E050752C0E06C /* SDWebImageDownloaderRequestModifier.m */; }; - 042D40751BD2F51FBE9FECD4707CBBE9 /* SDDeviceHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = AC2514CF7A7B043E035CFB079E6FB5A0 /* SDDeviceHelper.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 0453019EC6578A67B82CF569EC765546 /* SDFileAttributeHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = D13BE3E84BFB9462CF54B22B35F89ADC /* SDFileAttributeHelper.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 05E2B7C1DB7528A0BBEA1521BE0DBAF1 /* MASViewAttribute.h in Headers */ = {isa = PBXBuildFile; fileRef = 2CCE60F6B1B48663415E0A4BC9662B33 /* MASViewAttribute.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 06C4E233E7977DB81A24482E69B2D7D7 /* UIImage+Transform.m in Sources */ = {isa = PBXBuildFile; fileRef = 14C4334FE2177757C132CBBCD17C11B5 /* UIImage+Transform.m */; }; - 08719ABCE689ED74FE7486B1E49DAA6C /* MJRefreshBackStateFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F8526067D06A009E96461455DBA1B40 /* MJRefreshBackStateFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 089F3C4BAA46A37EC5763DD312771021 /* SDImageIOAnimatedCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 13F0EE17165FE326BF8D348C181A1E71 /* SDImageIOAnimatedCoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 08D50C5AC969A3701B6F9137CF3A10F1 /* UIImage+ForceDecode.m in Sources */ = {isa = PBXBuildFile; fileRef = 840FE4FBC8DFDB4B1238B06FEA5AF259 /* UIImage+ForceDecode.m */; }; - 08DF3A0323B44ABF3FAAE0F291F8566E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18BF12DFF6188AFC43E6F26853B048F9 /* Foundation.framework */; }; - 09A2ACBC8CE1761652EAA20886AEFE10 /* SDImageCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = B3A54C7306CBDB1BC3189CCF492C92DE /* SDImageCoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 0B0E6CECDF516BC83756C1D5515A725B /* SDAsyncBlockOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = FF49D60AE2D0E7C2857D88C5353083C3 /* SDAsyncBlockOperation.m */; }; - 0BADC710EA22BBCD76E59748C2A56ECF /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = A9F5CF889820DAD55268C3832155A2E1 /* PrivacyInfo.xcprivacy */; }; - 0EF10747EF2A02413E84BD5EF7C87A4B /* MJRefreshNormalHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = E7D9B8C39A19DDF2CE7619D44758B033 /* MJRefreshNormalHeader.m */; }; - 0F1D0F5DCC8C94A4C684DF846D14F436 /* SDWebImagePrefetcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 916FC91BADACF2A6F0FF12F1385FC1D4 /* SDWebImagePrefetcher.m */; }; - 0FF9F459ED16719292443A4C99B52B20 /* SDImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 8332CB32D0FA2CE8D910AA5A9BE18D8B /* SDImageCache.m */; }; - 10017B43AC38C3A89D7AC1376C6E7066 /* SDImageLoadersManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 80E9D6278C5650A6AD05F331651F6DEB /* SDImageLoadersManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 11C929E6BFB46F981685446F26DCE605 /* MJRefreshAutoFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = 568638C925360332377ACFB503131A76 /* MJRefreshAutoFooter.m */; }; - 126496714AD564062A8C10787CC01B8B /* MJFoundation.m in Sources */ = {isa = PBXBuildFile; fileRef = 4830CF5BA96EF2AA3AC7496D62A49A0D /* MJFoundation.m */; }; - 14943D0EE97A4966510A86F5C3FC66A5 /* MJExtension-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = C5D0E76AC56695893DB1713CA7212B8C /* MJExtension-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 14CA284AC4FF1EED75E785641EE98034 /* SDImageCacheConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 19E0C6994863739B688E61DCE0E025C3 /* SDImageCacheConfig.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 165F1C9CBD621828C788A3018D0426C5 /* SDImageAPNGCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C38C5957F4EAC459AB28A71622C865C /* SDImageAPNGCoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 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, ); }; }; 16D7DCB7CC985C33EEC41B371C029C84 /* SDWebImage-SDWebImage in Resources */ = {isa = PBXBuildFile; fileRef = CF1281E58AA1045D4B7F33FC56691C42 /* SDWebImage-SDWebImage */; }; - 1708C1D28B421C4AD310426D1695CE77 /* SDAnimatedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = DC6CF0A46A4D9FFFBA2057678DF1978B /* SDAnimatedImage.m */; }; - 1754DD5511A7BF462B116F70B0D4006A /* SDWebImageOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 76F97ACAD92849B1F665FD0FF282B3C8 /* SDWebImageOperation.m */; }; - 1830558A4D2D63C8E76BC3136D8213F9 /* UIImage+ExtendedCacheData.h in Headers */ = {isa = PBXBuildFile; fileRef = 377FB4D51134D774594E6EAF0BB4DFAA /* UIImage+ExtendedCacheData.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18660FA595DBE133BB784E813A7122A8 /* SDImageHEICCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 20B21087EF80825B8FC789A191A95BAA /* SDImageHEICCoder.m */; }; - 186B573F1BEB8A23419A02814A7741DB /* MJRefreshFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = EAFBBF7E1270693113CDF0C1D9CBB512 /* MJRefreshFooter.m */; }; - 18AD90784D549657DF51BC8377DA3085 /* SDWebImageDownloaderResponseModifier.h in Headers */ = {isa = PBXBuildFile; fileRef = D99D7FCB3FD62B8D8BF11087E1D6E47F /* SDWebImageDownloaderResponseModifier.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1B6CE67196EE181E6B56788EFC7E00D3 /* SDImageGIFCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = B60142D76441D9D2B7BA4991E7523577 /* SDImageGIFCoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1BC44E2FDD197D5210A23C9CCF1A906B /* SDWebImageCompat.m in Sources */ = {isa = PBXBuildFile; fileRef = 7980625AB48FABAF33EDB825FF587011 /* SDWebImageCompat.m */; }; - 1C73BC7EEF39CC3D3A21EACAD858413D /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 970B39752136D5831550118975DC4A91 /* PrivacyInfo.xcprivacy */; }; - 1C8B70C74291A3076746C3B18781568E /* SDImageCachesManagerOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 9DBD448EB576D346FBA1D20A1BD13F1D /* SDImageCachesManagerOperation.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 1EA011B45EC780B434507AFB3D9647ED /* NSObject+MJCoding.h in Headers */ = {isa = PBXBuildFile; fileRef = E200433A892F1843DD9B8C05E3C226BE /* NSObject+MJCoding.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1ECC5F320AEFB120081358B4FFB7442F /* NSString+MJExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = E310A44D757B0556FA6F2882D1565A8C /* NSString+MJExtension.m */; }; - 2055774CD703B52DABFB1CC588394A94 /* MJExtension-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = FB792580573132155A61C027392EF360 /* MJExtension-dummy.m */; }; - 20D618EF3EA5E3BE96DA24D36E3CA9EF /* SDAsyncBlockOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 42134A400043398C196C2BDF73B21075 /* SDAsyncBlockOperation.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 22516EA77E7120000632C30BD9A03927 /* UIScrollView+MJExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = C55407E10212267DCB2FC49D3260EF48 /* UIScrollView+MJExtension.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 24E8E4ED0B5D988E3346E6638619F4E4 /* SDImageFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B7D77CB378449CF4A7041A3EA89C102 /* SDImageFrame.m */; }; - 24E963C1D6245F98BAC8A0ACCB7DE987 /* NSBundle+MJRefresh.m in Sources */ = {isa = PBXBuildFile; fileRef = 37DCC80FE271D2095A398F8D8F22C7E7 /* NSBundle+MJRefresh.m */; }; - 2567FE276DB76481DEFC7DDFE7D775CC /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18BF12DFF6188AFC43E6F26853B048F9 /* Foundation.framework */; }; - 288CD3416B265CAC1300D7938167AE66 /* MJPropertyKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 250848691A5C0FC662F372FB71E83AE5 /* MJPropertyKey.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 288D796F3F7B9F42690E24A3B1018B2C /* SDImageIOAnimatedCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = E2EAE5E554B07101C740E6CB128A93A0 /* SDImageIOAnimatedCoder.m */; }; - 28BA9702905AA2B4C1E9E4878032D4E4 /* MJRefreshConst.h in Headers */ = {isa = PBXBuildFile; fileRef = BE6C3AB94897685F9464AA252C4EFB17 /* MJRefreshConst.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 29F7F0E98FD26A96364DBACD7D5F237A /* SDWebImageDownloader.h in Headers */ = {isa = PBXBuildFile; fileRef = 00031196DD7FBA552243DCF5CEB19ABD /* SDWebImageDownloader.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 2DC44A09A6C9D6DC7D1BDA2DFCF99EE3 /* MJRefreshConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 2EFA72948DE45F4B6CAD9DA5C625D259 /* MJRefreshConfig.m */; }; - 2DDD48230ED9E8068C7E439D79B99A8E /* SDInternalMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = A294AA5EAB4FD3CAF8C4A072117591C1 /* SDInternalMacros.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 2F6D9BEA582A2DBB70A6C3B2FC2DB91E /* SDWebImageDownloaderResponseModifier.m in Sources */ = {isa = PBXBuildFile; fileRef = 4F51691B6717B6D9E4E3FE0977CF3163 /* SDWebImageDownloaderResponseModifier.m */; }; - 3187FF0C251D1B78BE87F64F6F6E944A /* SDWebImageTransition.m in Sources */ = {isa = PBXBuildFile; fileRef = A11030FED687E26E2A7953D880C8DDD7 /* SDWebImageTransition.m */; }; - 31DC2EC78AD1F8241AE6051EF9E73B0A /* SDWebImageDefine.m in Sources */ = {isa = PBXBuildFile; fileRef = 6DE36A434A8BD3593CCBD95090373332 /* SDWebImageDefine.m */; }; - 320DE42AF3CFE11FF785FEB1A7E6547B /* SDImageFramePool.m in Sources */ = {isa = PBXBuildFile; fileRef = BF3675A98BB80F2630D08AB3BE31E1B7 /* SDImageFramePool.m */; }; - 321F87DA34863DC5C977323BAEDB2B55 /* NSObject+MJCoding.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D403D54754F62E7ECBA2668B217E5FD /* NSObject+MJCoding.m */; }; - 325CA20B9271F3E008234E1518B79061 /* MJRefresh-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = AECAC2F59ABD4A78D2B73C898E485890 /* MJRefresh-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 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, ); }; }; + 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, ); }; }; 327BA3DDA513422E632D3DA4A8FC60EC /* MJRefresh-MJRefresh.Privacy in Resources */ = {isa = PBXBuildFile; fileRef = 7E3097CFEFDA621E9FB0E62009FF87FC /* MJRefresh-MJRefresh.Privacy */; }; - 32ACEDCEBE0507A82D6323114A1C74F1 /* UIImageView+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 23078E14E88B14332A0B4BE57A2A9488 /* UIImageView+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 32F2B91621A2F8F9AD7C8E2B224D73F6 /* SDWebImageDownloaderDecryptor.m in Sources */ = {isa = PBXBuildFile; fileRef = 1C27DC7D5FFFA31A8EA1C7B95F3079E1 /* SDWebImageDownloaderDecryptor.m */; }; - 3331A013D48A5063B483A51B7E9068ED /* AFURLSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 7506ED7F0118C1C5FE230328CCC6543E /* AFURLSessionManager.m */; }; - 33D3587AF629B2FA21554DA002D6ACB8 /* SDImageCachesManager.m in Sources */ = {isa = PBXBuildFile; fileRef = F0CEEBB5DD628DB121172299787A25A9 /* SDImageCachesManager.m */; }; - 34B28D4F0168194B6EFAC0520EB7A7F4 /* NSImage+Compatibility.h in Headers */ = {isa = PBXBuildFile; fileRef = F76369243ECD96D54BBB9C4A97EB6946 /* NSImage+Compatibility.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 36F4B09E7C71DCC5CEC6057814033C37 /* UIView+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = A87E9EA0B6E9AB8C1E29A3AE50F278CB /* UIView+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 3777CD89D444CBBB48AE323B303F3FC7 /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DDAE741F085915AF2475C918F1A17466 /* ImageIO.framework */; }; - 37B890ABDC7DD441E6AA662325D412E6 /* MASConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = 71C9A7FB9BC0D7C0FA902D0643B08962 /* MASConstraint.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 38938E604A7D708E6378A44063EF3512 /* UIImageView+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = C6C465F665338FA163A2F6623C933047 /* UIImageView+WebCache.m */; }; - 3A1AD84C0DC3C256418CC46739024E96 /* SDmetamacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 61B4061AC178FEE58C9618133524CF08 /* SDmetamacros.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 3A2FCB914F6EADED828FF05F7E9132AE /* UIView+MJExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = 35F55EE8682F170A101CA85DD55D1B58 /* UIView+MJExtension.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 3B8EDFF69A68ABD3735E0C6931CA5C95 /* AFURLSessionManager.h in Headers */ = {isa = PBXBuildFile; fileRef = A95F96D9DAA700949C3A302C92FD9231 /* AFURLSessionManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 3C7815EEC599DD7D42FDEF19B2FF1563 /* SDWebImageOptionsProcessor.h in Headers */ = {isa = PBXBuildFile; fileRef = B9DF6B027952E0BE3781007ECC6436E7 /* SDWebImageOptionsProcessor.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 3C7EAECB8C573E714C818BA04EB33773 /* UIImage+MultiFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = 897B6BFD5EA50E7440FD4FA3769B3C78 /* UIImage+MultiFormat.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 3C8F2F868D0C361CAF43E53CDB8EB631 /* SDWebImageCacheSerializer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A71363040CF6A8E6D918CEF79A555D5 /* SDWebImageCacheSerializer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 3CE201A6CFF26BD49792F9A8E4C822A5 /* Pods-keyBoard-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 969A9A842778EFB5D62826500DFF4E11 /* Pods-keyBoard-dummy.m */; }; - 3D0BBFEC1921CE71BC240DC18D8BE540 /* SDImageTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 6E7A746456C4F5E2C887572055F6A833 /* SDImageTransformer.m */; }; - 3FE4CEC187728FF5B98CECE3D92744E7 /* Pods-CustomKeyboard-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 9DDD0462C32F55EF5E9CB1056459809F /* Pods-CustomKeyboard-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 3FF7252DD60182221BB1E5A167C41A07 /* UIProgressView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = 018B520CB407C3492F13C3767C15E377 /* UIProgressView+AFNetworking.m */; }; - 416DA8B2997381F954DBA6E6A53DA4A2 /* NSData+ImageContentType.m in Sources */ = {isa = PBXBuildFile; fileRef = 90687AA744E720C17FD8600B60F43FF5 /* NSData+ImageContentType.m */; }; - 425C9EA28FBEB7F7FC09A3F4A88C5955 /* SDWebImageError.m in Sources */ = {isa = PBXBuildFile; fileRef = B509365346F676352BBC6630F5F1FADB /* SDWebImageError.m */; }; - 442F468E261A1106C291BF52BDBF9DB7 /* MJRefreshHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = 724FB5172055CF20AE6E6F4D007D8038 /* MJRefreshHeader.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 44CD842019B1CEA681F820F37A30B7C4 /* SDImageFramePool.h in Headers */ = {isa = PBXBuildFile; fileRef = 12C162655386843E5BE2582AC09CA762 /* SDImageFramePool.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 452C940762F65B125C216F73B369F583 /* MJRefreshStateTrailer.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B9AAE9B2C02781F4AC71AEDB56A439 /* MJRefreshStateTrailer.m */; }; - 4571A0EA37DC84F39E3830D38A1531AB /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5BA0325112AB8CA7AB613D1A8ED2DB65 /* UIKit.framework */; }; - 45E1583D7EF53489B82C4CA2AD1AD0CF /* MJRefreshBackFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = 3126B87E909122AFEE37CA26F800E7D9 /* MJRefreshBackFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4688743B7B845309486559EB7BD5D147 /* SDWebImageCompat.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B6867FF0B2276E04032D8E5C44B4EB9 /* SDWebImageCompat.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 475B4F3E71C293065AAFDB1888696CF6 /* MJRefreshBackGifFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = 29AFC65F883E204F73DDE040C829BC77 /* MJRefreshBackGifFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 48916DE9521F627589300512ECC2D4A5 /* NSButton+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 008AD8F77F87E2DC5C0DB4CD71AC5858 /* NSButton+WebCache.m */; }; - 4B2C2AE16AE3DDA7417AFCF7952588F1 /* SDImageAssetManager.h in Headers */ = {isa = PBXBuildFile; fileRef = F7A20DE3DDDA450D1997F9A3184CD3C6 /* SDImageAssetManager.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4D2C79AB2D24CFEC864F08D913CE7692 /* SDImageCodersManager.m in Sources */ = {isa = PBXBuildFile; fileRef = C3EC2E3BBB3895884BB4AA3B74A54476 /* SDImageCodersManager.m */; }; - 4DCA75BFE1558CE59DFC56607E49B3D2 /* MJRefreshConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = BEC2871B1357A63D88FCC0144C7847CD /* MJRefreshConfig.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4ED05DB3E43FF6AE1FA22130B2B50F05 /* UIImage+MemoryCacheCost.h in Headers */ = {isa = PBXBuildFile; fileRef = 4797723C6D7C918B816F46FCFB028F6F /* UIImage+MemoryCacheCost.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 506FC58999564A737C745F2590E9B4D5 /* AFHTTPSessionManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C60E3EC4F7CE664E3A6586ED2AC0ED5 /* AFHTTPSessionManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5111A0A0934551CD2B9DDB1A1CA79FA7 /* SDAnimatedImageRep.m in Sources */ = {isa = PBXBuildFile; fileRef = 9954286F43C39384A1EADABA9AAE0B0D /* SDAnimatedImageRep.m */; }; - 512B9661FC34235E0EEB3A6D3E319B88 /* MJPropertyType.m in Sources */ = {isa = PBXBuildFile; fileRef = 7842E350E0D12563DE7C0EB363356BF8 /* MJPropertyType.m */; }; - 5163FC6D715F6881B1FA1AB13DCEF870 /* UICollectionViewLayout+MJRefresh.h in Headers */ = {isa = PBXBuildFile; fileRef = 24B89B49F862DFF8218AA2D11CEDFD3E /* UICollectionViewLayout+MJRefresh.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5174DD2019966DFDC21B8864453ED3DE /* NSObject+MJClass.m in Sources */ = {isa = PBXBuildFile; fileRef = 5A50D4A4631B759E5D73FDFF78C8BF75 /* NSObject+MJClass.m */; }; - 523235228A1C021C67F2E3776A922DC5 /* MJRefreshTrailer.h in Headers */ = {isa = PBXBuildFile; fileRef = B6011963612818816E2CF40CED8B0112 /* MJRefreshTrailer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 526485EF6D2B62B24DB59122FB94BD42 /* SDDeviceHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 4090C24D16A324EB9D2A6747886BD217 /* SDDeviceHelper.m */; }; - 5308E660E723C11E7691D311FD59C459 /* SDDisplayLink.m in Sources */ = {isa = PBXBuildFile; fileRef = 48E4A519DF8188F67D6109DB1AF82FF9 /* SDDisplayLink.m */; }; - 53433003112C4FE271EC985803862B61 /* SDWebImageCacheKeyFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 9802609AB0266E444A1BD29FA119D9BC /* SDWebImageCacheKeyFilter.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 54E268C32915CF908E7AA776909B45EB /* MJRefreshConst.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BECBF70665658E16C4E9DDD74C7161A /* MJRefreshConst.m */; }; - 55F7C7F055A18044497F8C88CAE34118 /* SDImageCachesManagerOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 305FF55ADA3393924EFC2D4B6D38166D /* SDImageCachesManagerOperation.m */; }; - 561420A20DC0A84258A902E9EB69A15A /* MJRefreshAutoFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D4327E5DC3980134C42B829E8798AA4 /* MJRefreshAutoFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 564714D075CF51356D3D8437846AA6EB /* AFURLRequestSerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = 74446596F2A689B17D9187482A194EEC /* AFURLRequestSerialization.m */; }; - 56D8A7EAE4D72FF6C23421CAB6F21504 /* MJPropertyType.h in Headers */ = {isa = PBXBuildFile; fileRef = 950F7A4DEA1A2D31E4A650C9526788F7 /* MJPropertyType.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 56E800EB3B2BE8AE0BA45A30974D7920 /* Masonry-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E8106411081DD6C7F5FE7804947412C /* Masonry-dummy.m */; }; - 58F7CE37BB4CB3BE806B68A502E6E1A7 /* SDWeakProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F0E8534D3C055E4D5D27EBF7422DA74 /* SDWeakProxy.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 596180E0EC9F46D12BA840DC4AA62659 /* UIImage+MemoryCacheCost.m in Sources */ = {isa = PBXBuildFile; fileRef = EA1E48B813787CAC28E89E7F260BFCD4 /* UIImage+MemoryCacheCost.m */; }; - 597E390C0BBB75B8045B651C487C2034 /* SDImageAWebPCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = DFD5A14F9DC74814903A901B625C5A94 /* SDImageAWebPCoder.m */; }; - 5A6D3BE92C77ED70C397567996DFAEB9 /* AFHTTPSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C0AB8960CBA6D24923E096B9378691C /* AFHTTPSessionManager.m */; }; - 5AF22814CD055B553AD9D78BE54B94E1 /* UIProgressView+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE5F401F42AA242D6CAE9E463DE5CD4 /* UIProgressView+AFNetworking.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5B08596E856E4CC2F34A8A2372F9F764 /* NSArray+MASAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = F934ACD20FEDAB980427B3D001DF8312 /* NSArray+MASAdditions.m */; }; - 5BB6B99986FD7111B3AEBE931C7F507B /* MJRefreshAutoStateFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = 3526591F674CF19FB39EF872089A7F49 /* MJRefreshAutoStateFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5BD5D9B8F61C124A62C75D9AC36A07BD /* MJRefreshTrailer.m in Sources */ = {isa = PBXBuildFile; fileRef = B1CE88DD0007C23B107D2BD3A6AB545B /* MJRefreshTrailer.m */; }; - 5C8279C226EB028B044C5A0F4AC5A91A /* SDAssociatedObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 34E2AA501576A0C5221012B9066EC56A /* SDAssociatedObject.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 5DCBA14510E091D6A1CE499B08B794B5 /* UIImage+Metadata.h in Headers */ = {isa = PBXBuildFile; fileRef = 03DE7669ACCB33ED7598791177D4881A /* UIImage+Metadata.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5DFCBADAC7D0FAC82C84A6C8E7BF1DA6 /* MJRefreshStateHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = A20073D67775A184A6AEF2667BC7628C /* MJRefreshStateHeader.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5E10328A83E05D0015D7459FAAEF121D /* SDGraphicsImageRenderer.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FD6594A1D1613C90FF5EF2CBD5CE123 /* SDGraphicsImageRenderer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5F45735DF355530CC955066D3C007E19 /* MASViewConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = 266F6A7CA0ABF9B26D746459A14BAEBA /* MASViewConstraint.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5FDC4239F7B651092BF582D0F460BAD4 /* UIView+MJExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = 06B650CAE141ABD90E360415151BC9B9 /* UIView+MJExtension.m */; }; - 61461B0D9D7B81C3F8D24066D9A19DCE /* MJRefreshGifHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = F4E10DADB58D42AEAD6CD268CEB583E8 /* MJRefreshGifHeader.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 61507E402F1F7C58BF119995A0479A22 /* NSArray+MASShorthandAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 1DA8FCC29DBFD3824ADEAD9F14A76E86 /* NSArray+MASShorthandAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 616A8338C42FB01748DF1BDDA944858D /* UIView+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D3CFDF279C9B9946089A89EFB72A50D /* UIView+WebCache.m */; }; - 61857C821395B868C65A8FFE4DA1B4E3 /* MJExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = 569FA95248CF0B824C3928196386FFC2 /* MJExtension.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 62FE895DF9D65A2955A275D909ECBE18 /* SDAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = F0C38163E5AA6D4BEAA1C7E79C82A930 /* SDAnimatedImageView.m */; }; - 67178A8153B1A2F1D0D544B8093E23C5 /* SDAnimatedImageView+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C6DD7AD3672258C4407B4269B490F27 /* SDAnimatedImageView+WebCache.m */; }; - 676775CB29378BB6CA3CA5992E9C6A99 /* SDImageIOAnimatedCoderInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CB3E312C9D65596A37072C76944B850 /* SDImageIOAnimatedCoderInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 69345CBCB31076EBF8A2C5885AF973AB /* MJRefreshComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = E553AE6B35449F8CB4BAA4FFE1DCAFAC /* MJRefreshComponent.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 694B8697854A776E32032999B2EF1FEA /* UIImage+Metadata.m in Sources */ = {isa = PBXBuildFile; fileRef = 46F91B0801CEBD1D73003708566CC913 /* UIImage+Metadata.m */; }; - 69A06A02F52EB26259FAD1DF6B121BE1 /* SDCallbackQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = AF26D1DF8BE4D63027161EEBE6FDE7AE /* SDCallbackQueue.m */; }; - 69AB6A513D5F36D7360FEF4FDA1D60D0 /* UIView+WebCacheState.h in Headers */ = {isa = PBXBuildFile; fileRef = DC6DB03243923516662807D789FF26B1 /* UIView+WebCacheState.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 69E353C99C6EEA3C93CCF2E526460B9D /* UIScrollView+MJRefresh.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C64CBB1952BF537420E489E4AF7DED5 /* UIScrollView+MJRefresh.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 6A19379E3B0370EDA447743C9B1A1379 /* UIImageView+HighlightedWebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 982D370CD4E116E0C1917E832541C530 /* UIImageView+HighlightedWebCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 6B0978C9398336656EE309E62060AEAB /* SDImageAssetManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 19F5C3BFE7C9E2977EB241266B257ABE /* SDImageAssetManager.m */; }; - 6B5C3592B5E911E833D067D0BC785B1A /* SDImageFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = AB8EC26A51378B3F4C5559E371607480 /* SDImageFrame.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 6C85CA8D99E50C137D056B6057DAC58A /* UIRefreshControl+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = B070DCCCA22D6ECC24DC0BD5CCEF5372 /* UIRefreshControl+AFNetworking.m */; }; - 6CA0B4A9E7B2957063163BC673F355CD /* AFAutoPurgingImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 3FBCEF9827DD721BAF021C98F7311D30 /* AFAutoPurgingImageCache.m */; }; - 6DE6C7F0FA965828E4FCE687BF75FBBE /* MJRefreshAutoNormalFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E6DD5C54D7EC67B674C64E88446BAA7 /* MJRefreshAutoNormalFooter.m */; }; - 6E66305665DBCFBCF5B2480BF705D500 /* SDWebImageTransition.h in Headers */ = {isa = PBXBuildFile; fileRef = 575E3DAA2F5DDC8FBD895B8BEA5FB8C6 /* SDWebImageTransition.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 6EFEEE3AE22E97DCEC4F5A3B88F56FC7 /* SDImageLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 7869EB02C0774141B550180F17DBF9F0 /* SDImageLoader.m */; }; - 6F3637EE643EABB1DE9212EA68649A64 /* UIColor+SDHexString.m in Sources */ = {isa = PBXBuildFile; fileRef = 10E420AEEA134E4CDDBAA68DEA103561 /* UIColor+SDHexString.m */; }; - 7074EA7FCC90B4967A437F5C43496828 /* SDDisplayLink.h in Headers */ = {isa = PBXBuildFile; fileRef = 078FC3682AC6F2B8020DD6D0F6A1A818 /* SDDisplayLink.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 711D32EF4A9901567A488291603BF906 /* SDWebImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 67DDCFED9CF39A1F995D9E7B12E35A7E /* SDWebImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 71538A1D21015F459964BA625D5EE90A /* NSObject+MJClass.h in Headers */ = {isa = PBXBuildFile; fileRef = 25ABF76DAF311B44A4F41DD3F9F04644 /* NSObject+MJClass.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 717F76926C7BCB5B10C3037AD9239084 /* SDImageIOCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 21EE020A32A9ADF76D7C1AF1A9B28D63 /* SDImageIOCoder.m */; }; - 71BEB1D9532900291A5A24B1C038516F /* UIColor+SDHexString.h in Headers */ = {isa = PBXBuildFile; fileRef = 851329DB564FCDDAD9A52952F487E28D /* UIColor+SDHexString.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 71F2B8CBB99087F348C472230200586F /* SDGraphicsImageRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = 661BCD3C752D21E81C83DA14D3C4502A /* SDGraphicsImageRenderer.m */; }; - 724991CA89C46BAFBC08264D94D86484 /* AFURLRequestSerialization.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DD19473CA2658646B964B6124A31FB9 /* AFURLRequestSerialization.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 74C474676C69A80BEC29B0F55FDF4D19 /* UIView+WebCacheState.m in Sources */ = {isa = PBXBuildFile; fileRef = 197BBC12418F4C1E7719181019D1E9EA /* UIView+WebCacheState.m */; }; - 74E069F8C9E22C0E37F261A5AB03A613 /* SDWebImageDownloaderConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E8EE46DFF5945CB5FDB220509F5E1A0 /* SDWebImageDownloaderConfig.m */; }; - 752822FE3F5092322D18FEC4533B79A9 /* SDWebImageDownloader.m in Sources */ = {isa = PBXBuildFile; fileRef = F104350C0F7D19687DAC6BD75101DA7F /* SDWebImageDownloader.m */; }; - 75771A97B77FA30A0175A81B480F80EF /* UIImage+ForceDecode.h in Headers */ = {isa = PBXBuildFile; fileRef = EA46C1DE7820870BF842553EA6A951F9 /* UIImage+ForceDecode.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 772CF8E9CD02ECA4275B6173E2110E80 /* View+MASShorthandAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = E5886305209187E582C024335BD55AE9 /* View+MASShorthandAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 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, ); }; }; + 34F918A5603258EEA91431BC4E1150F6 /* Pods-keyBoard-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = A2D8E1EB42D41EA6B94901E5B68C9011 /* Pods-keyBoard-umbrella.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 */; }; + 5A1E04C829BF2C50593ADDBC1A69429F /* Pods-keyBoard-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 969A9A842778EFB5D62826500DFF4E11 /* Pods-keyBoard-dummy.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, ); }; }; 7873F2F89CD0A435FAB776BC27BFB56A /* MJExtension-MJExtension in Resources */ = {isa = PBXBuildFile; fileRef = 43EAAD2AB7E6B407E80E95F643F93D22 /* MJExtension-MJExtension */; }; - 7902D28FC9EF5AFEB452F508C7F266B1 /* MJRefreshAutoNormalFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = 0073EB182F9CC003B9721B132AC0082F /* MJRefreshAutoNormalFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 7989A6E79BFA78440C39F568D972305C /* MJRefresh.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D2A2C7E78B1029B85E812A9CC5D4F58 /* MJRefresh.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 7A4EB9ED5D4E03170FFE61FCB299687B /* SDAnimatedImagePlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = B20A669086F5506692603D3336437ABD /* SDAnimatedImagePlayer.m */; }; - 7C45DBA62EE045C4922404182F6393B8 /* SDWebImageError.h in Headers */ = {isa = PBXBuildFile; fileRef = 646B483EDAD1F8B7F96981EB5E185F2E /* SDWebImageError.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 7C5505A2D3F2A697A5F324787061F4B7 /* MASConstraint+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 5AC074355067D4E88EB993DD28E44948 /* MASConstraint+Private.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 7F10C0D094C74F2FA4CD38C7FD77B0A8 /* WKWebView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = 71A4B6E144674403F50435C67561B1BB /* WKWebView+AFNetworking.m */; }; - 7F886FC2763F0BF1625A24EE4F94C04D /* UIRefreshControl+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 0044E51493E8CC5F8C46E1EC18F97722 /* UIRefreshControl+AFNetworking.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 7FA8C78DB021A7731D30D80C102DE042 /* NSObject+MJKeyValue.m in Sources */ = {isa = PBXBuildFile; fileRef = C23DF793769699E27A02E0B30615EF6F /* NSObject+MJKeyValue.m */; }; - 7FF8A56511E71D6FEC966BF9FEE135B5 /* AFNetworkActivityIndicatorManager.h in Headers */ = {isa = PBXBuildFile; fileRef = D875CFB5AA1591E80BD3A95A94255894 /* AFNetworkActivityIndicatorManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 813BE4C96A6D39C13EC50C6CD164F0AF /* MASConstraintMaker.h in Headers */ = {isa = PBXBuildFile; fileRef = F9CEF650A6E8658ECF7704A7EE2E7452 /* MASConstraintMaker.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 81A5635CEA2AD9623E30CAE9AFC3BF65 /* NSBundle+MJRefresh.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E459098B6FF83AA9172F97696B64090 /* NSBundle+MJRefresh.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 83530BF68848CD2C4A79A1FD69B304A5 /* SDImageGIFCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 42FE2C6A18379D9944FBBA606FB88133 /* SDImageGIFCoder.m */; }; - 83A4F2816C1B3F072E1A26A34C3BC4AC /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18BF12DFF6188AFC43E6F26853B048F9 /* Foundation.framework */; }; - 8414CFEEB64ACA817EB88D2FEADDA3B3 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18BF12DFF6188AFC43E6F26853B048F9 /* Foundation.framework */; }; - 854807558DCB972EDDFC1D00032BA6E4 /* SDWebImageDownloaderConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 8A926EA8E3863425810DDC585C464587 /* SDWebImageDownloaderConfig.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 85AB23275E9D19394969235E5DC2300E /* MJRefreshHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = F74EE2D92793519D84E4B72CD6AB0C63 /* MJRefreshHeader.m */; }; - 85C0B4EE334B9972299E62DE61A4BB56 /* SDImageLoadersManager.m in Sources */ = {isa = PBXBuildFile; fileRef = A1ECACF57484B51D17735566ED038104 /* SDImageLoadersManager.m */; }; - 860CB3A5D2E13B946CD2EFB7F749C4CF /* UIActivityIndicatorView+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 29DD9709CE876731037B630B8F1370DA /* UIActivityIndicatorView+AFNetworking.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 864972FB0DF4B464B1B505AA5F788E91 /* SDInternalMacros.m in Sources */ = {isa = PBXBuildFile; fileRef = 06A2AED69705719F9BEBAEDC9D1D18C6 /* SDInternalMacros.m */; }; - 88473AE7C22F952DACB39FA0758D1624 /* SDMemoryCache.h in Headers */ = {isa = PBXBuildFile; fileRef = E97276CEE18BF4611E1C1D42736F6EAB /* SDMemoryCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 8872BEB0954C0254A792469F4DBC9891 /* MJRefreshAutoStateFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = CCDB436E5F20F839485E728CEF386187 /* MJRefreshAutoStateFooter.m */; }; - 88A23DF6F5638AC66C28C4102824E8B5 /* NSImage+Compatibility.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C040DD9465E298ACD105143A3265009 /* NSImage+Compatibility.m */; }; - 8AF38EDB1E9BF0D334AEB23C488870B8 /* NSData+ImageContentType.h in Headers */ = {isa = PBXBuildFile; fileRef = DDC08D9E69C76309DA07F96C62824633 /* NSData+ImageContentType.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 8C6C7E25C5A24C936F81823978190E96 /* ViewController+MASAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 6EB624EDC7B2F6F92D5F6AEF8AAA4356 /* ViewController+MASAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 8D8AD606ECD8E1F247965CD43956D412 /* UIImage+Transform.h in Headers */ = {isa = PBXBuildFile; fileRef = AF6FBF6EC0693B752A91650764E380C8 /* UIImage+Transform.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 8FF7B6477BFA6E6ABA168E1417291D5F /* MASCompositeConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = 0F7E589343BFFDCABC0FCDF6E321CDA2 /* MASCompositeConstraint.m */; }; - 906DCE66CD5BD236081D468616199BB7 /* SDWebImageOptionsProcessor.m in Sources */ = {isa = PBXBuildFile; fileRef = ADF1D8C19CC2D66E65B4B1746316FFC5 /* SDWebImageOptionsProcessor.m */; }; - 91AAF555B286FBF53E4F98D092B406BD /* SDWebImageTransitionInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 755B7205B482C6B79DEAE02978E7FD20 /* SDWebImageTransitionInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 91E8B94F8E02ABF5197DF5AE7D0B3934 /* SDWebImageDownloaderDecryptor.h in Headers */ = {isa = PBXBuildFile; fileRef = 29834704EC1453F0ACBDF5CAA435E7B0 /* SDWebImageDownloaderDecryptor.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 928371B066E1211CE87089668D5BCB4C /* SDDiskCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 6DFD30C63C15966EA8BF3CAD55EB97F8 /* SDDiskCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 9345137ED10358B60E37D05FB6165759 /* SDFileAttributeHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = DBFD2ECA52ECDAAA78246FE8B02312A9 /* SDFileAttributeHelper.m */; }; - 9358FC6C6DA728AEE250D8E7DD236946 /* MJProperty.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D8FF130378AA0390E3754AB93673319 /* MJProperty.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 955B87902E039163281C4F47C95DB851 /* MJRefreshBackNormalFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = 14C952AD321D89B78D085CA0FBC817D9 /* MJRefreshBackNormalFooter.m */; }; - 96E97174F4614FFA0649085022CB4AFE /* SDWebImage-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 34F1A2FD98EEB8019052FBD5528585C9 /* SDWebImage-dummy.m */; }; - 97235408E59E16C18B6BDA1D29E1CB26 /* SDWebImageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 09C03827CE30DECF1B8884688B6651D8 /* SDWebImageManager.m */; }; - 97385A64CA020489951EF769392C6DCF /* UIView+WebCacheOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D5935FEEF657D48BF93BE04A41CF816 /* UIView+WebCacheOperation.m */; }; - 9A7FB1E975A5955C896E6B195C521804 /* MJRefreshBackNormalFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = 087882A7DEA5E7EECA5B73EB89E95C00 /* MJRefreshBackNormalFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 9B3420DEB8A0CCB9E1241A669AEFCA8E /* SDAnimatedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 2CCDC185ACCEFD6ACB87234F081FC1A1 /* SDAnimatedImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 9B9343E8599EE5196BA75E842DCB48B7 /* NSBezierPath+SDRoundedCorners.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A46DCA8F7BDEE6453116CAF6CBBAC40 /* NSBezierPath+SDRoundedCorners.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 9CE425B89294BE2C13E70A86E75B15CF /* SDDiskCache.m in Sources */ = {isa = PBXBuildFile; fileRef = A113F5BE027C0A2BC1CC3F420069F969 /* SDDiskCache.m */; }; - 9D422527A25BAE6A207DEFE11958ABBC /* AFCompatibilityMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B8247E0ADA45F5408F3DE8313900894 /* AFCompatibilityMacros.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 9DF446F8CA5BC4D4098766EC9063012C /* SDWebImageOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 33152C1C1E9FE19D1E9C8D8BF0C963DA /* SDWebImageOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A078A275FFFA48D620074790DA3CA6CE /* MJRefreshStateHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = D513B9FE4981B810C5EBD34AAD6D0CD7 /* MJRefreshStateHeader.m */; }; - A0E0DC76F51300E7EB1EBA5492DE854D /* UIImageView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = AF94F3E24B633799AB0B2B75B193A4F3 /* UIImageView+AFNetworking.m */; }; - A1560247914C760D9EE5F7A2392CC06C /* UIImage+GIF.h in Headers */ = {isa = PBXBuildFile; fileRef = 429C09B93893D24656048D336CE95D59 /* UIImage+GIF.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A1DC9EFDF50DF0EAF24D9D7C219AD2C1 /* NSObject+MJProperty.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C8185E7D34531047F63FFFBB2C6C9D3 /* NSObject+MJProperty.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A1E44277704AD68E867FD7C955A6632D /* MJRefreshBackGifFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = 32EACA7B3E95EF3C511EEAED34B5C23A /* MJRefreshBackGifFooter.m */; }; - A3148D9EB39C7BFAF4F85E3378F3EF80 /* Pods-CustomKeyboard-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 3CB13D51E717D347023EEB57263E3072 /* Pods-CustomKeyboard-dummy.m */; }; - A3EA39A13714B3103B82F4066A642F53 /* MJExtensionConst.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D68500D4C2F7DB8B114E62F888BDD85 /* MJExtensionConst.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A839428F403C52D8AA3466B65E20C27A /* NSButton+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 11F1BA773620708277D240BE4CD304E4 /* NSButton+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A86CC1AFDFDD692DC4EE66F57C0F39E6 /* UIScrollView+MJRefresh.m in Sources */ = {isa = PBXBuildFile; fileRef = 8AF059A8B1C2B3EE76BCDE329D0C926E /* UIScrollView+MJRefresh.m */; }; - A92AB5E65CA85947368E46E6627F1BFB /* UIButton+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 4638EBD469283AF4DC5CBD3CE927D254 /* UIButton+WebCache.m */; }; - A9A49E4A3BE8882F60DF32BAF39DE191 /* SDWebImageManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 02379CD5F0D938EE2DBABC8871CB17E5 /* SDWebImageManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - AA1EA8F0F0470F1596B1FFA58ABF3375 /* SDWebImageDownloaderOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 825CA08D9974B4E876CAFA68A0F53F93 /* SDWebImageDownloaderOperation.m */; }; - ABCB80C4813C849FC93D57676820C907 /* SDImageCacheDefine.h in Headers */ = {isa = PBXBuildFile; fileRef = 97F65BC08A412ED6706647722A834532 /* SDImageCacheDefine.h */; settings = {ATTRIBUTES = (Public, ); }; }; - AC14E56ECA7A4980A8E1CA68E800B12C /* SDWebImagePrefetcher.h in Headers */ = {isa = PBXBuildFile; fileRef = 0DC8E0CC70A7B84D1A1E1FAAF5AF5A4D /* SDWebImagePrefetcher.h */; settings = {ATTRIBUTES = (Public, ); }; }; - AC710813CB6A1DAEEE45914402F864D2 /* MJProperty.m in Sources */ = {isa = PBXBuildFile; fileRef = 87A1195922F05E5D23FF9A3C4509A854 /* MJProperty.m */; }; - AE7B02645B8F769CA5F215EE8F7CC5B0 /* View+MASAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 88799C33D6D0AAE2D395A1496F3A9E5D /* View+MASAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; - AF1A6353DEDBE196A10C8897F94DDA8E /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 94F556719E0728E491D5BDF953E9A668 /* PrivacyInfo.xcprivacy */; }; - B030B558BE97E0225652EFB8C8FA431F /* AFAutoPurgingImageCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 246841FAF82F0BA847818A9594B81CCB /* AFAutoPurgingImageCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B09F08548ACA8379445F6525011EE219 /* MJRefreshBackStateFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = 71B30FE27ADA94703A3F06804277A5C0 /* MJRefreshBackStateFooter.m */; }; - B2704AFFC5CC053154839DB44924D255 /* SDImageCoderHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = F62E78180455B791A034CFBD4F4CE6A3 /* SDImageCoderHelper.m */; }; - B331CE2D3DEB461E738B886086A365F9 /* SDImageGraphics.h in Headers */ = {isa = PBXBuildFile; fileRef = 34CEE2DA708B82493E132F274E2E9493 /* SDImageGraphics.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B48A975992E58328254C494F133DE467 /* NSObject+MJProperty.m in Sources */ = {isa = PBXBuildFile; fileRef = 4AFCF05D160C4A925AEC624ED1CD826F /* NSObject+MJProperty.m */; }; - B4F231C5CBAB3D4A184699D0066E0E83 /* SDImageAWebPCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 7315702A1F332F57A8765F720EE5B18F /* SDImageAWebPCoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B59E60FBC9665FC1061B88B8E6FD9FAF /* Masonry-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 92D14A3D3FA826806436A8CFCBD915DA /* Masonry-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B5AF87C11A465F666473F6191D173905 /* UIView+WebCacheOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = AED6E178EFE04C18394DE24CF7E24E01 /* UIView+WebCacheOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B66356D4E7E43B3D15324569AA7EBB05 /* SDWebImageDownloaderOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = A1D6DA8B66269F171ED8918C664075F4 /* SDWebImageDownloaderOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B680C2604BD8BC9644AE7C67BC46B9BB /* MASLayoutConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = 52AD4C798F619843C6425BB666EE43A0 /* MASLayoutConstraint.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B741DBE2A466E6211F879EF997D9322D /* SDImageCodersManager.h in Headers */ = {isa = PBXBuildFile; fileRef = DBEED872AB83B013F34A14A1823F4820 /* SDImageCodersManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B95C63A039D9D08896421291DEBD3AEB /* SDWebImageCacheKeyFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = F7E0DB23007E49794165F74548446C13 /* SDWebImageCacheKeyFilter.m */; }; - BA904ABA8ED36CC4E5EB2B2004CA1F18 /* MASCompositeConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = 104166B53DA0CBE95AF12518EB609B7A /* MASCompositeConstraint.h */; settings = {ATTRIBUTES = (Public, ); }; }; - BACAA91A92F35CD7E7795232A83F21D1 /* AFNetworkActivityIndicatorManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 859BA7601F83844D2D2ABC395E386663 /* AFNetworkActivityIndicatorManager.m */; }; - BADA31750A2136D073EDA4461DBE1EEA /* UIButton+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E2F76F628A20AA296860E039C6A51DE /* UIButton+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - BC2F9B1D6986FEB23B4FB1288B512538 /* MJRefreshNormalTrailer.h in Headers */ = {isa = PBXBuildFile; fileRef = 73D1ED74B2085AA85B8213943DE4AD83 /* MJRefreshNormalTrailer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - BC5458210A973BC7A29D1F45D458A14B /* AFNetworking-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 14D8DE9600B7E469FA4A83E84C149E08 /* AFNetworking-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - BCDC1E1D46DD124B5726A064D2EE66A3 /* UIImage+MultiFormat.m in Sources */ = {isa = PBXBuildFile; fileRef = F68941BD4F4913D60B00D4A8F049112A /* UIImage+MultiFormat.m */; }; - BCEFDE57BB0E0B36731C8D39FFA1BE2C /* SDWebImageDownloaderRequestModifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 969BDA148FEBCD19E1B7701E7F70E539 /* SDWebImageDownloaderRequestModifier.h */; settings = {ATTRIBUTES = (Public, ); }; }; - BCFA1CA56CA625A754714006E0032750 /* Pods-keyBoard-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = A2D8E1EB42D41EA6B94901E5B68C9011 /* Pods-keyBoard-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - BD30193C1E3D7B1F17B1B1F3F08BE655 /* UICollectionViewLayout+MJRefresh.m in Sources */ = {isa = PBXBuildFile; fileRef = BCC0677B77FA6DFFDE007551F1660B1E /* UICollectionViewLayout+MJRefresh.m */; }; - BDBE494BAC544843982C3CA96A6C41DD /* SDAnimatedImagePlayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 81D5F6E26D64BB94294CEC208FAEEBE2 /* SDAnimatedImagePlayer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - BF0C3D2782FE1425C2F1F8827132A94B /* MJFoundation.h in Headers */ = {isa = PBXBuildFile; fileRef = 0AFFFE7105483F8A94BFD883AD56221D /* MJFoundation.h */; settings = {ATTRIBUTES = (Public, ); }; }; - BF22D137EF6324675FA50080C5D93C00 /* NSArray+MASAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 93EB15003C1E2452E5C21AD7FF38A39D /* NSArray+MASAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C0D7926E41A294ACA98D7B033B283919 /* WKWebView+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E3334C24AC0A37A21A6D9B9ECA94AB2 /* WKWebView+AFNetworking.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C1DD8C6A64F948E4C53560C76B995DA4 /* SDAnimatedImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = 8AACAEAAD31005B66599055215ADA658 /* SDAnimatedImageView.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C2068AEACC2D9C7F1FFE41AA25B12A68 /* MASUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 3F58F61640AAFD16139A83CC4EA55B1D /* MASUtilities.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C2840BF1950FF7EE2DCD6D55F768A49C /* UIImage+GIF.m in Sources */ = {isa = PBXBuildFile; fileRef = 24F6DCD61BBDE3823CE167416B3799D1 /* UIImage+GIF.m */; }; - C2FE60A10C792613E45031AE6E851ECB /* MASViewConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = D28BB6B7AF2BC47AA045CB28AE578B56 /* MASViewConstraint.m */; }; - C60DB44F719853DE3B7157960DAF9270 /* MJRefreshComponent.m in Sources */ = {isa = PBXBuildFile; fileRef = FB988F307C9B24539A026F84144A0402 /* MJRefreshComponent.m */; }; - C6A100159974349FEAAC99B82BE0F872 /* SDImageLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 50DC89AF710F42BFF3D4C048EFAC8BB7 /* SDImageLoader.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C857B8D2D0BAA5A8A764F9E1C4B85807 /* ViewController+MASAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 33EBB93597383ED9EEA18C0A9BCE3B84 /* ViewController+MASAdditions.m */; }; - C8EC35DFB0945DBE2F2FF9ECFE6D9711 /* NSLayoutConstraint+MASDebugAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = DE966A3AAABAC126A570DC36F74E07AE /* NSLayoutConstraint+MASDebugAdditions.m */; }; - C93E972E75F84674690300123984EC43 /* SDAssociatedObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C838D64A8654D1DDA15A6DDC98360A9 /* SDAssociatedObject.m */; }; - C9E19D164C26414115CC969ED9A303C1 /* MASLayoutConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = 047628989EB45DFAC6DD4B6DDC61C1D7 /* MASLayoutConstraint.m */; }; - CA1E0DCDF679EA2DE2ED0915426E1D04 /* SDWeakProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 93A3B9C517383784D38DA222632F5FFB /* SDWeakProxy.m */; }; - CFF8D1A5E4C2097EF05E1021FE112886 /* SDWebImageIndicator.m in Sources */ = {isa = PBXBuildFile; fileRef = 0FC44A2AEE9BAA02332A14994FF0E2E0 /* SDWebImageIndicator.m */; }; - D06BB547D59D183FD1DDD84DEBAC9EE8 /* SDWebImageCacheSerializer.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C4CAA32BF7068345545D717BAAF7069 /* SDWebImageCacheSerializer.m */; }; - D2AF9A7FD73B95960FDA4FD06C4BED08 /* NSObject+MJKeyValue.h in Headers */ = {isa = PBXBuildFile; fileRef = D915858ABB2794C80C0D2328483F75C4 /* NSObject+MJKeyValue.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D2CD8848F856EC9942A76610AAE66F0A /* SDImageIOCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = FF09658FCA5560C3552AF5B4B7E7C6ED /* SDImageIOCoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D5C046C46961BE465293625D6B870620 /* AFNetworking-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = CC69297E62F679246B8FE5B49D774CF4 /* AFNetworking-dummy.m */; }; - D62A672EEB252581BD972DDA862BE1DD /* SDWebImage-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 70330531B46EEB4398625F2AFC6683E5 /* SDWebImage-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D662C83ECE8BEDA5FFB52F3575CA3E1A /* SDImageCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D1581B25C7E0154AE410EBB56CE516 /* SDImageCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D663837F4347AF58660EE6F7FD426ECE /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18BF12DFF6188AFC43E6F26853B048F9 /* Foundation.framework */; }; - D788BA4B9E8186271BA75CA52B30502C /* View+MASAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = E135DFBB6A830F84DCF4A1D31534EE65 /* View+MASAdditions.m */; }; - D7B3E8948DB04BD8FB6748419DA03EA9 /* SDAnimatedImageView+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 371EEAE238A16CCB71633D3E6EF40F2B /* SDAnimatedImageView+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D90607B4E56247B19B14462E487BA86E /* MJRefreshNormalTrailer.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E7292A83C005323B245A7EF2737878F /* MJRefreshNormalTrailer.m */; }; - D90DED0F5638B1C44F4B6C62D600D240 /* MJRefreshFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = 53392BC7B7115E12AC2077F4447BF455 /* MJRefreshFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D90DF1376DF5E2EA644313BCD2E03058 /* MJRefresh.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 5FDFD2C717749B65FE64DACB99DF72A3 /* MJRefresh.bundle */; }; - DBA9500CBBA5FF6FCBBA115AE4D12152 /* NSLayoutConstraint+MASDebugAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 5679D7FEFDE3E519C17C0EAAA7867122 /* NSLayoutConstraint+MASDebugAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; - DBD9152526A180771BF7D7CD209B957E /* AFSecurityPolicy.h in Headers */ = {isa = PBXBuildFile; fileRef = 85AD1C60C75A73E360E4320DD271A77D /* AFSecurityPolicy.h */; settings = {ATTRIBUTES = (Public, ); }; }; - DC87E6C5364DC59641BC8A0676B5EA55 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18BF12DFF6188AFC43E6F26853B048F9 /* Foundation.framework */; }; - DDA16FB9C21AD941442357DAE6939530 /* UIKit+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 2008561C63F2B5CE8C1C38CF97F13753 /* UIKit+AFNetworking.h */; settings = {ATTRIBUTES = (Public, ); }; }; - DE5A78F116018E2AC54714238276574D /* UIActivityIndicatorView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C41FE7B076060F0600FEC9D5AFF762A /* UIActivityIndicatorView+AFNetworking.m */; }; - DE98ECCCA7106A4EA575EF34830D41FF /* MJRefresh-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = C71B36DE1531E30C6C8E2592C55C0ED5 /* MJRefresh-dummy.m */; }; - DEA09692CF813A23899CD4949A9B6801 /* SDAnimatedImageRep.h in Headers */ = {isa = PBXBuildFile; fileRef = FB47049112F4F8EEA8F6068CB0393B3F /* SDAnimatedImageRep.h */; settings = {ATTRIBUTES = (Public, ); }; }; - DED9ADFC8CC65243FC54E008A853742C /* MJPropertyKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 12CCB648397BE0600012171A844509DE /* MJPropertyKey.m */; }; - DF2B15402CE105F5A8CE48BBDCFFD5DD /* MASConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = 7C1791A7C256B13C227BF8DAE4C2EFE9 /* MASConstraint.m */; }; - E0BCF21E9FA59F638C13ECCECC4D9690 /* SDMemoryCache.m in Sources */ = {isa = PBXBuildFile; fileRef = A6CCAA7B0AD1373217438DACF7AB456C /* SDMemoryCache.m */; }; - E1BF615DD0422B06C97542F03C879D41 /* AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = BE440D8DEC29075E20FE83DB3AB2620D /* AFNetworking.h */; settings = {ATTRIBUTES = (Public, ); }; }; - E1DE69F6BB6235A6EDB6C99A184BEDB4 /* UIScrollView+MJExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B4BB6924504E595528A838685E1B608 /* UIScrollView+MJExtension.m */; }; - E3FC6BEE41652C0500F57E0CB83B347F /* UIButton+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 7AE552655E7E703CCEDD4BE44EFA5662 /* UIButton+AFNetworking.h */; settings = {ATTRIBUTES = (Public, ); }; }; - E4F1B478580D6D7328BC29607BDE46F6 /* UIImage+ExtendedCacheData.m in Sources */ = {isa = PBXBuildFile; fileRef = 8FC489301C2534B7DD53B90720E80BF3 /* UIImage+ExtendedCacheData.m */; }; - E50613C67DD02AF6EA825DA0B31EFFAD /* SDImageGraphics.m in Sources */ = {isa = PBXBuildFile; fileRef = 830D06A83C1E8E77E539514107F83812 /* SDImageGraphics.m */; }; - E55B3151D86660E28CEABC3CDE6B1508 /* UIButton+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = F0300A3A30BF1560E306C61ACCE11C1A /* UIButton+AFNetworking.m */; }; - E5B057BC87284367918B2DB9CA084B4E /* MJRefreshAutoGifFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = 2514349975FAC97A668A1C6665BD754F /* MJRefreshAutoGifFooter.m */; }; - E76969F9B01139118427505B18F9CD21 /* SDImageHEICCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 8430A616C01FADC1B0DB9E5D08A03C35 /* SDImageHEICCoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; - E8AB529B9E0B4C23921344F6C4ABFEA4 /* SDImageCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 01F1EC51FF11D8BE91D0807E9CB714CC /* SDImageCoder.m */; }; - E930A5612DC6D120BE040AD17C6D1BCD /* MASViewAttribute.m in Sources */ = {isa = PBXBuildFile; fileRef = E5AEFA07EBF944C0387D10A7BD7BC85F /* MASViewAttribute.m */; }; - EA82B6D97C9C5D0558047AF552D63203 /* SDWebImageDefine.h in Headers */ = {isa = PBXBuildFile; fileRef = 19C379703ED728112C6AD8D69CB97193 /* SDWebImageDefine.h */; settings = {ATTRIBUTES = (Public, ); }; }; - EABCB60A26B06BF576E50BBD2F89A385 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18BF12DFF6188AFC43E6F26853B048F9 /* Foundation.framework */; }; - EB3DF628891F7D6AB114718AF760CB2A /* UIImageView+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = AB321552F4E1B0F80966FCA9AF11848F /* UIImageView+AFNetworking.h */; settings = {ATTRIBUTES = (Public, ); }; }; - EC8E84A8FFADDCA562A8608D141D9027 /* MJRefreshAutoGifFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = 1D9CC7A1A5CD78BA5BDFC0C1D94B2D4D /* MJRefreshAutoGifFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; - EC9B34262AED632D7EFB49804337648E /* Masonry.h in Headers */ = {isa = PBXBuildFile; fileRef = 23D13EEFDD6A912D7922FE8AE4E23D60 /* Masonry.h */; settings = {ATTRIBUTES = (Public, ); }; }; - ECE64B732F9FA7C402DDEEC58DCB9D98 /* SDImageAPNGCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = BF154B0F2EB8913A8674795FD63311D2 /* SDImageAPNGCoder.m */; }; - ED8991A8AE7C04362C2BED3875DC1656 /* AFURLResponseSerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = CEC061A3621F113DA97A66F89E6A844B /* AFURLResponseSerialization.m */; }; - ED8F64FF98CFAE0B12CF60A1B0E6BAF8 /* SDCallbackQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 678A010D7D73785C1E08D97B5F67AAAA /* SDCallbackQueue.h */; settings = {ATTRIBUTES = (Public, ); }; }; - EE6E8FE636D2C02E3D2FC1E8555B4612 /* MJRefreshNormalHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = 5713367A1E361064DE338AB389631FF5 /* MJRefreshNormalHeader.h */; settings = {ATTRIBUTES = (Public, ); }; }; - EED016DE8173CD38CC01D88CD2628984 /* NSString+MJExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = 0A6C15EE27B77ABD56B0A0807D581260 /* NSString+MJExtension.h */; settings = {ATTRIBUTES = (Public, ); }; }; - EF6A6C725598F572A70C5FCEE328C184 /* SDImageTransformer.h in Headers */ = {isa = PBXBuildFile; fileRef = 2C0A8B13D619D89C3E57F4B83ACBF157 /* SDImageTransformer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - F1D845E22D5B8FC6AFC3C2E41DA1B6DF /* AFNetworkReachabilityManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 523BDC065F0AF63F170A84FAF905FD26 /* AFNetworkReachabilityManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - F2AD91050B1FE3C8BC78567F1FDE3ED5 /* AFURLResponseSerialization.h in Headers */ = {isa = PBXBuildFile; fileRef = 517973DC2D89829B73698FF20240431A /* AFURLResponseSerialization.h */; settings = {ATTRIBUTES = (Public, ); }; }; - F3263D294D688533EB974E37C61F1E24 /* MJExtensionConst.m in Sources */ = {isa = PBXBuildFile; fileRef = 31F5F018A672BC56D29258EEBC019C32 /* MJExtensionConst.m */; }; - F3AECEF6D3BB919B3E7392942E1BC58B /* MJRefreshBackFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = 19839A21E0B314D9E8C99EBD5D071916 /* MJRefreshBackFooter.m */; }; - F49CB22863CCFEC7817D259F27F91C57 /* SDWebImageIndicator.h in Headers */ = {isa = PBXBuildFile; fileRef = D0B1FCAC31B9EF58F1FD85B83EA55B1C /* SDWebImageIndicator.h */; settings = {ATTRIBUTES = (Public, ); }; }; - F53BE4449AE5896F76325E4DCB6D0B13 /* SDImageCachesManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 0ACA8E457A64FBC07F850B4E390020D4 /* SDImageCachesManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - F60F90EAF35CFF40DF1C33557965787D /* MJRefreshStateTrailer.h in Headers */ = {isa = PBXBuildFile; fileRef = 036A5C31DE156FE1001CC60EF1E3E122 /* MJRefreshStateTrailer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - F68889CD481716EE5D6B75EBD8FD53A6 /* SDImageCoderHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 176CBDEEAB52421C3AA5CB3917B54885 /* SDImageCoderHelper.h */; settings = {ATTRIBUTES = (Public, ); }; }; - F6D1C960368EB1E067ABD0BFF707FC56 /* MASConstraintMaker.m in Sources */ = {isa = PBXBuildFile; fileRef = 8ABF0BFFB097FE97D207EBE5498289D3 /* MASConstraintMaker.m */; }; - F7623E7C314AA5010D8D0BD6ED4AAAD4 /* AFImageDownloader.m in Sources */ = {isa = PBXBuildFile; fileRef = 61D0A0EB33F4B0A380D6DE9E8E5D56D7 /* AFImageDownloader.m */; }; - F9789D86D3279D71B398B550F27C3EFF /* AFSecurityPolicy.m in Sources */ = {isa = PBXBuildFile; fileRef = 52AA08F30FFF4D9FF32F48E3AC195A6A /* AFSecurityPolicy.m */; }; - FA3021DED76B9B182CC9195A60EB1209 /* NSBezierPath+SDRoundedCorners.m in Sources */ = {isa = PBXBuildFile; fileRef = B147B49E855B11A35493E26865607BDF /* NSBezierPath+SDRoundedCorners.m */; }; - FCDEC6A53CF5517E1AF5B331FD65F6D9 /* SDImageCacheConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = C5D645FDA53D7713D436C992B2BC3E96 /* SDImageCacheConfig.m */; }; - FCEE5BD645E95FF55468C4AB6D17CFDA /* UIImageView+HighlightedWebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 56347C360CEDAA8246A01A213DEBBF8B /* UIImageView+HighlightedWebCache.m */; }; - FDACBA49610EA6F39CABB7FE44B137D1 /* AFImageDownloader.h in Headers */ = {isa = PBXBuildFile; fileRef = E8780E8A7822982224C2ACEBBC3B52B8 /* AFImageDownloader.h */; settings = {ATTRIBUTES = (Public, ); }; }; - FE07C069C2E3543002CEB5D751ABA9AC /* AFNetworkReachabilityManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B7BBB3446628A3BC637B9F57A5C49901 /* AFNetworkReachabilityManager.m */; }; - FEA8BA4F82CCBD1D28DCC7EF39FB4096 /* SDImageCacheDefine.m in Sources */ = {isa = PBXBuildFile; fileRef = 9AF4B903EB65570DDDE8731659809CA1 /* SDImageCacheDefine.m */; }; - FEE883575278D5BE8F185437AB5DB3BB /* MJRefreshGifHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 275A2D66E7913A4B508816E187F4D3C3 /* MJRefreshGifHeader.m */; }; + 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 */; }; + 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, ); }; }; + 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 */; }; + 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 */; }; + 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 */; }; + C828F9FE16619B2D51C4F3E40185DE85 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3964617E5C241BE3E12D8F1D88607841 /* Foundation.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 */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 23C4ACB33CF11EF7F294BFEFDFEE525F /* PBXContainerItemProxy */ = { + 332EDC024ABBEE82955E7E88C302D2E4 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = B32AF3F43989CBA171BB1FB3957A4509; - remoteInfo = "MJExtension-MJExtension"; + remoteGlobalIDString = 638FEAAFC575BB76BC6AC055CDDA3506; + remoteInfo = LookinServer; }; - 74C35E0C9F3979D774EBA89927D5F9BE /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = B26054DF1DEA11585A231AF6D1D80D5E; - remoteInfo = "MJRefresh-MJRefresh.Privacy"; - }; - 7F4A11CEA9C42F01CCC8FD8CF31E0D31 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 55AF53E6C77A10ED4985E04D74A8878E; - remoteInfo = Masonry; - }; - 8C46BC742135C578AA462516574ECF6A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 94CFBA7D633ECA58DF85C327B035E6A3; - remoteInfo = "SDWebImage-SDWebImage"; - }; - D00922B5D33413CCF1E3D4753D9B5522 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 6868056D761E163D10FDAF8CF1C4D9B8; - remoteInfo = MJRefresh; - }; - D31947E4B8C395A2964CC7C4CA10B4B3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 4D3BA58D0583DF37575CACAB3DDADC85; - remoteInfo = MJExtension; - }; - ED8283C03EBD084126ED5759CD5B7EF5 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 4A68CFD979D413A619DF631BB121D98F; - remoteInfo = Bugly; - }; - F236FEF1E37470AFA015925961D566A3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 3847153A6E5EEFB86565BA840768F429; - remoteInfo = SDWebImage; - }; - F4298358FEAF506C773B2D34F3DF6B12 /* PBXContainerItemProxy */ = { + 45076E4E15CD2B80A147FBC40CD1D7BD /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; remoteGlobalIDString = 0130B3724283586C0E9D2A112D4F2AA1; remoteInfo = AFNetworking; }; + 551922F754B651AFCAAB56605458A1A4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 55AF53E6C77A10ED4985E04D74A8878E; + remoteInfo = Masonry; + }; + 5D9596750911C6C3E3B693FA7242334B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 3847153A6E5EEFB86565BA840768F429; + remoteInfo = SDWebImage; + }; + 67F0F8485CEFCEAF14CFFCC3F2461F7C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 82B0A41D3031FF27D78E17B0A9A46FB0; + remoteInfo = MBProgressHUD; + }; + 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; + }; + AA9226BB33C3F9E019FB415C2032A082 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = F1BCD9702276377FB5B3BDB6EAF709D7; + remoteInfo = DZNEmptyDataSet; + }; + 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; + }; + B680C6AEDC2C7072F4BCC65FA83A00F2 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4A68CFD979D413A619DF631BB121D98F; + remoteInfo = Bugly; + }; + BBBA8C59A31486B3AE2F16C6A4AAAB66 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = B26054DF1DEA11585A231AF6D1D80D5E; + remoteInfo = "MJRefresh-MJRefresh.Privacy"; + }; + DF6BBAC9AED95181B9D6A27C2AED4872 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 6868056D761E163D10FDAF8CF1C4D9B8; + remoteInfo = MJRefresh; + }; + E2B36932A623A0432422370F519C4507 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 55AF53E6C77A10ED4985E04D74A8878E; + remoteInfo = Masonry; + }; + ED58197BE1BA80A23DFAA0D475221386 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4D3BA58D0583DF37575CACAB3DDADC85; + remoteInfo = MJExtension; + }; + F34B1D580EA71604D4CC7C4C5807E366 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0130B3724283586C0E9D2A112D4F2AA1; + remoteInfo = AFNetworking; + }; + F4000FEC7CADA56B75E5CC31E64EC891 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = B32AF3F43989CBA171BB1FB3957A4509; + remoteInfo = "MJExtension-MJExtension"; + }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 00031196DD7FBA552243DCF5CEB19ABD /* SDWebImageDownloader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageDownloader.h; path = SDWebImage/Core/SDWebImageDownloader.h; sourceTree = ""; }; - 0044E51493E8CC5F8C46E1EC18F97722 /* UIRefreshControl+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIRefreshControl+AFNetworking.h"; path = "UIKit+AFNetworking/UIRefreshControl+AFNetworking.h"; sourceTree = ""; }; - 0073EB182F9CC003B9721B132AC0082F /* MJRefreshAutoNormalFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshAutoNormalFooter.h; path = MJRefresh/Custom/Footer/Auto/MJRefreshAutoNormalFooter.h; sourceTree = ""; }; - 008AD8F77F87E2DC5C0DB4CD71AC5858 /* NSButton+WebCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSButton+WebCache.m"; path = "SDWebImage/Core/NSButton+WebCache.m"; sourceTree = ""; }; - 018B520CB407C3492F13C3767C15E377 /* UIProgressView+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIProgressView+AFNetworking.m"; path = "UIKit+AFNetworking/UIProgressView+AFNetworking.m"; sourceTree = ""; }; - 01F1EC51FF11D8BE91D0807E9CB714CC /* SDImageCoder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageCoder.m; path = SDWebImage/Core/SDImageCoder.m; sourceTree = ""; }; - 02379CD5F0D938EE2DBABC8871CB17E5 /* SDWebImageManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageManager.h; path = SDWebImage/Core/SDWebImageManager.h; sourceTree = ""; }; - 036A5C31DE156FE1001CC60EF1E3E122 /* MJRefreshStateTrailer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshStateTrailer.h; path = MJRefresh/Custom/Trailer/MJRefreshStateTrailer.h; sourceTree = ""; }; - 03DE7669ACCB33ED7598791177D4881A /* UIImage+Metadata.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+Metadata.h"; path = "SDWebImage/Core/UIImage+Metadata.h"; sourceTree = ""; }; - 047628989EB45DFAC6DD4B6DDC61C1D7 /* MASLayoutConstraint.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASLayoutConstraint.m; path = Masonry/MASLayoutConstraint.m; sourceTree = ""; }; - 06A2AED69705719F9BEBAEDC9D1D18C6 /* SDInternalMacros.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDInternalMacros.m; path = SDWebImage/Private/SDInternalMacros.m; sourceTree = ""; }; - 06B650CAE141ABD90E360415151BC9B9 /* UIView+MJExtension.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIView+MJExtension.m"; path = "MJRefresh/UIView+MJExtension.m"; sourceTree = ""; }; - 06B71FC03BF92D5C7E3E050752C0E06C /* SDWebImageDownloaderRequestModifier.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageDownloaderRequestModifier.m; path = SDWebImage/Core/SDWebImageDownloaderRequestModifier.m; sourceTree = ""; }; - 078FC3682AC6F2B8020DD6D0F6A1A818 /* SDDisplayLink.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDDisplayLink.h; path = SDWebImage/Private/SDDisplayLink.h; sourceTree = ""; }; - 087882A7DEA5E7EECA5B73EB89E95C00 /* MJRefreshBackNormalFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshBackNormalFooter.h; path = MJRefresh/Custom/Footer/Back/MJRefreshBackNormalFooter.h; sourceTree = ""; }; - 09C03827CE30DECF1B8884688B6651D8 /* SDWebImageManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageManager.m; path = SDWebImage/Core/SDWebImageManager.m; sourceTree = ""; }; - 0A6C15EE27B77ABD56B0A0807D581260 /* NSString+MJExtension.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSString+MJExtension.h"; path = "MJExtension/NSString+MJExtension.h"; sourceTree = ""; }; - 0ACA8E457A64FBC07F850B4E390020D4 /* SDImageCachesManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageCachesManager.h; path = SDWebImage/Core/SDImageCachesManager.h; sourceTree = ""; }; - 0AFFFE7105483F8A94BFD883AD56221D /* MJFoundation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJFoundation.h; path = MJExtension/MJFoundation.h; sourceTree = ""; }; + 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 = ""; }; 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 = ""; }; 0C4AE62ED97252893F28F670D61AFB24 /* Pods-keyBoard-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-keyBoard-Info.plist"; sourceTree = ""; }; - 0C6DD7AD3672258C4407B4269B490F27 /* SDAnimatedImageView+WebCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "SDAnimatedImageView+WebCache.m"; path = "SDWebImage/Core/SDAnimatedImageView+WebCache.m"; sourceTree = ""; }; - 0C8185E7D34531047F63FFFBB2C6C9D3 /* NSObject+MJProperty.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSObject+MJProperty.h"; path = "MJExtension/NSObject+MJProperty.h"; sourceTree = ""; }; - 0C838D64A8654D1DDA15A6DDC98360A9 /* SDAssociatedObject.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDAssociatedObject.m; path = SDWebImage/Private/SDAssociatedObject.m; sourceTree = ""; }; - 0CB3E312C9D65596A37072C76944B850 /* SDImageIOAnimatedCoderInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageIOAnimatedCoderInternal.h; path = SDWebImage/Private/SDImageIOAnimatedCoderInternal.h; 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 = ""; }; 0D6215D1BCCE125B8DF73E38013CBBDC /* Pods-CustomKeyboard.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-CustomKeyboard.debug.xcconfig"; sourceTree = ""; }; - 0DC8E0CC70A7B84D1A1E1FAAF5AF5A4D /* SDWebImagePrefetcher.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImagePrefetcher.h; path = SDWebImage/Core/SDWebImagePrefetcher.h; 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 = ""; }; 0E732C0D026ACBC7DBD039DC3BDC2BCE /* Pods-keyBoard.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-keyBoard.modulemap"; sourceTree = ""; }; - 0F7E589343BFFDCABC0FCDF6E321CDA2 /* MASCompositeConstraint.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASCompositeConstraint.m; path = Masonry/MASCompositeConstraint.m; sourceTree = ""; }; - 0FC44A2AEE9BAA02332A14994FF0E2E0 /* SDWebImageIndicator.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageIndicator.m; path = SDWebImage/Core/SDWebImageIndicator.m; sourceTree = ""; }; - 104166B53DA0CBE95AF12518EB609B7A /* MASCompositeConstraint.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASCompositeConstraint.h; path = Masonry/MASCompositeConstraint.h; sourceTree = ""; }; - 10E420AEEA134E4CDDBAA68DEA103561 /* UIColor+SDHexString.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIColor+SDHexString.m"; path = "SDWebImage/Private/UIColor+SDHexString.m"; sourceTree = ""; }; - 1170792DCF45BF664C43019D3E77D80F /* Masonry.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = Masonry.modulemap; sourceTree = ""; }; - 11F1BA773620708277D240BE4CD304E4 /* NSButton+WebCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSButton+WebCache.h"; path = "SDWebImage/Core/NSButton+WebCache.h"; sourceTree = ""; }; - 12C162655386843E5BE2582AC09CA762 /* SDImageFramePool.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageFramePool.h; path = SDWebImage/Private/SDImageFramePool.h; sourceTree = ""; }; - 12CCB648397BE0600012171A844509DE /* MJPropertyKey.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJPropertyKey.m; path = MJExtension/MJPropertyKey.m; sourceTree = ""; }; - 13F0EE17165FE326BF8D348C181A1E71 /* SDImageIOAnimatedCoder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageIOAnimatedCoder.h; path = SDWebImage/Core/SDImageIOAnimatedCoder.h; sourceTree = ""; }; - 14C4334FE2177757C132CBBCD17C11B5 /* UIImage+Transform.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+Transform.m"; path = "SDWebImage/Core/UIImage+Transform.m"; sourceTree = ""; }; - 14C952AD321D89B78D085CA0FBC817D9 /* MJRefreshBackNormalFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshBackNormalFooter.m; path = MJRefresh/Custom/Footer/Back/MJRefreshBackNormalFooter.m; sourceTree = ""; }; - 14D8DE9600B7E469FA4A83E84C149E08 /* AFNetworking-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "AFNetworking-umbrella.h"; sourceTree = ""; }; - 176CBDEEAB52421C3AA5CB3917B54885 /* SDImageCoderHelper.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageCoderHelper.h; path = SDWebImage/Core/SDImageCoderHelper.h; sourceTree = ""; }; - 18BF12DFF6188AFC43E6F26853B048F9 /* 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; }; - 197BBC12418F4C1E7719181019D1E9EA /* UIView+WebCacheState.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIView+WebCacheState.m"; path = "SDWebImage/Core/UIView+WebCacheState.m"; sourceTree = ""; }; - 19839A21E0B314D9E8C99EBD5D071916 /* MJRefreshBackFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshBackFooter.m; path = MJRefresh/Base/MJRefreshBackFooter.m; sourceTree = ""; }; - 19C379703ED728112C6AD8D69CB97193 /* SDWebImageDefine.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageDefine.h; path = SDWebImage/Core/SDWebImageDefine.h; sourceTree = ""; }; - 19E0C6994863739B688E61DCE0E025C3 /* SDImageCacheConfig.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageCacheConfig.h; path = SDWebImage/Core/SDImageCacheConfig.h; sourceTree = ""; }; - 19F5C3BFE7C9E2977EB241266B257ABE /* SDImageAssetManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageAssetManager.m; path = SDWebImage/Private/SDImageAssetManager.m; sourceTree = ""; }; - 1AFEE2DD6CE0A6302F3235AF172A2B77 /* ResourceBundle-MJExtension-MJExtension-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-MJExtension-MJExtension-Info.plist"; sourceTree = ""; }; - 1C27DC7D5FFFA31A8EA1C7B95F3079E1 /* SDWebImageDownloaderDecryptor.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageDownloaderDecryptor.m; path = SDWebImage/Core/SDWebImageDownloaderDecryptor.m; sourceTree = ""; }; - 1C3E83B47A120437F73D41A878F182D1 /* Masonry-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Masonry-prefix.pch"; sourceTree = ""; }; - 1C60E3EC4F7CE664E3A6586ED2AC0ED5 /* AFHTTPSessionManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFHTTPSessionManager.h; path = AFNetworking/AFHTTPSessionManager.h; 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 = ""; }; 1D774D8146EBC82B4A77204A273761B8 /* Pods-CustomKeyboard.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-CustomKeyboard.release.xcconfig"; sourceTree = ""; }; - 1D9CC7A1A5CD78BA5BDFC0C1D94B2D4D /* MJRefreshAutoGifFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshAutoGifFooter.h; path = MJRefresh/Custom/Footer/Auto/MJRefreshAutoGifFooter.h; sourceTree = ""; }; - 1DA8FCC29DBFD3824ADEAD9F14A76E86 /* NSArray+MASShorthandAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSArray+MASShorthandAdditions.h"; path = "Masonry/NSArray+MASShorthandAdditions.h"; sourceTree = ""; }; - 1E8EE46DFF5945CB5FDB220509F5E1A0 /* SDWebImageDownloaderConfig.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageDownloaderConfig.m; path = SDWebImage/Core/SDWebImageDownloaderConfig.m; sourceTree = ""; }; - 1F0E8534D3C055E4D5D27EBF7422DA74 /* SDWeakProxy.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWeakProxy.h; path = SDWebImage/Private/SDWeakProxy.h; sourceTree = ""; }; - 1F8526067D06A009E96461455DBA1B40 /* MJRefreshBackStateFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshBackStateFooter.h; path = MJRefresh/Custom/Footer/Back/MJRefreshBackStateFooter.h; 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 = ""; }; 1FFED36A657123030ABB700256D73F15 /* Masonry */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Masonry; path = Masonry.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 2008561C63F2B5CE8C1C38CF97F13753 /* UIKit+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIKit+AFNetworking.h"; path = "UIKit+AFNetworking/UIKit+AFNetworking.h"; sourceTree = ""; }; - 20B1DAD84F32D1AF296F0D63C5DEE9AB /* SDWebImage.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SDWebImage.debug.xcconfig; sourceTree = ""; }; - 20B21087EF80825B8FC789A191A95BAA /* SDImageHEICCoder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageHEICCoder.m; path = SDWebImage/Core/SDImageHEICCoder.m; sourceTree = ""; }; - 21EE020A32A9ADF76D7C1AF1A9B28D63 /* SDImageIOCoder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageIOCoder.m; path = SDWebImage/Core/SDImageIOCoder.m; sourceTree = ""; }; - 23078E14E88B14332A0B4BE57A2A9488 /* UIImageView+WebCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImageView+WebCache.h"; path = "SDWebImage/Core/UIImageView+WebCache.h"; sourceTree = ""; }; - 2356B7A3F963324EEBA83CB0C527CC22 /* ResourceBundle-SDWebImage-SDWebImage-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-SDWebImage-SDWebImage-Info.plist"; sourceTree = ""; }; - 23D13EEFDD6A912D7922FE8AE4E23D60 /* Masonry.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Masonry.h; path = Masonry/Masonry.h; sourceTree = ""; }; - 23D6F4D8D5B6512D7A50FF1054426C09 /* AFNetworking.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = AFNetworking.release.xcconfig; sourceTree = ""; }; - 246841FAF82F0BA847818A9594B81CCB /* AFAutoPurgingImageCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFAutoPurgingImageCache.h; path = "UIKit+AFNetworking/AFAutoPurgingImageCache.h"; sourceTree = ""; }; - 24B89B49F862DFF8218AA2D11CEDFD3E /* UICollectionViewLayout+MJRefresh.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UICollectionViewLayout+MJRefresh.h"; path = "MJRefresh/UICollectionViewLayout+MJRefresh.h"; sourceTree = ""; }; - 24F6DCD61BBDE3823CE167416B3799D1 /* UIImage+GIF.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+GIF.m"; path = "SDWebImage/Core/UIImage+GIF.m"; sourceTree = ""; }; - 250848691A5C0FC662F372FB71E83AE5 /* MJPropertyKey.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJPropertyKey.h; path = MJExtension/MJPropertyKey.h; sourceTree = ""; }; - 25119C155F0BB240A5DDFB8155627C04 /* SDWebImage.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SDWebImage.release.xcconfig; sourceTree = ""; }; - 2514349975FAC97A668A1C6665BD754F /* MJRefreshAutoGifFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshAutoGifFooter.m; path = MJRefresh/Custom/Footer/Auto/MJRefreshAutoGifFooter.m; sourceTree = ""; }; - 25ABF76DAF311B44A4F41DD3F9F04644 /* NSObject+MJClass.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSObject+MJClass.h"; path = "MJExtension/NSObject+MJClass.h"; sourceTree = ""; }; - 266F6A7CA0ABF9B26D746459A14BAEBA /* MASViewConstraint.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASViewConstraint.h; path = Masonry/MASViewConstraint.h; sourceTree = ""; }; - 275A2D66E7913A4B508816E187F4D3C3 /* MJRefreshGifHeader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshGifHeader.m; path = MJRefresh/Custom/Header/MJRefreshGifHeader.m; sourceTree = ""; }; + 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 = ""; }; + 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 = ""; }; 281686F4C9CC2C718B45E1DEB7E63948 /* Pods-CustomKeyboard-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-CustomKeyboard-acknowledgements.markdown"; sourceTree = ""; }; - 29834704EC1453F0ACBDF5CAA435E7B0 /* SDWebImageDownloaderDecryptor.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageDownloaderDecryptor.h; path = SDWebImage/Core/SDWebImageDownloaderDecryptor.h; sourceTree = ""; }; - 29AFC65F883E204F73DDE040C829BC77 /* MJRefreshBackGifFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshBackGifFooter.h; path = MJRefresh/Custom/Footer/Back/MJRefreshBackGifFooter.h; sourceTree = ""; }; - 29DD9709CE876731037B630B8F1370DA /* UIActivityIndicatorView+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIActivityIndicatorView+AFNetworking.h"; path = "UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.h"; 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 = ""; }; 2B276B0A79173A1D6E83C9B4FB9A4A57 /* MJExtension */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = MJExtension; path = MJExtension.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 2B8247E0ADA45F5408F3DE8313900894 /* AFCompatibilityMacros.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFCompatibilityMacros.h; path = AFNetworking/AFCompatibilityMacros.h; sourceTree = ""; }; - 2C0A8B13D619D89C3E57F4B83ACBF157 /* SDImageTransformer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageTransformer.h; path = SDWebImage/Core/SDImageTransformer.h; sourceTree = ""; }; - 2CCDC185ACCEFD6ACB87234F081FC1A1 /* SDAnimatedImage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDAnimatedImage.h; path = SDWebImage/Core/SDAnimatedImage.h; sourceTree = ""; }; - 2CCE60F6B1B48663415E0A4BC9662B33 /* MASViewAttribute.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASViewAttribute.h; path = Masonry/MASViewAttribute.h; sourceTree = ""; }; - 2D2A2C7E78B1029B85E812A9CC5D4F58 /* MJRefresh.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefresh.h; path = MJRefresh/MJRefresh.h; sourceTree = ""; }; - 2D68500D4C2F7DB8B114E62F888BDD85 /* MJExtensionConst.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJExtensionConst.h; path = MJExtension/MJExtensionConst.h; sourceTree = ""; }; - 2E459098B6FF83AA9172F97696B64090 /* NSBundle+MJRefresh.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSBundle+MJRefresh.h"; path = "MJRefresh/NSBundle+MJRefresh.h"; sourceTree = ""; }; - 2EFA72948DE45F4B6CAD9DA5C625D259 /* MJRefreshConfig.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshConfig.m; path = MJRefresh/MJRefreshConfig.m; sourceTree = ""; }; - 305FF55ADA3393924EFC2D4B6D38166D /* SDImageCachesManagerOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageCachesManagerOperation.m; path = SDWebImage/Private/SDImageCachesManagerOperation.m; sourceTree = ""; }; - 3126B87E909122AFEE37CA26F800E7D9 /* MJRefreshBackFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshBackFooter.h; path = MJRefresh/Base/MJRefreshBackFooter.h; sourceTree = ""; }; - 31F5F018A672BC56D29258EEBC019C32 /* MJExtensionConst.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJExtensionConst.m; path = MJExtension/MJExtensionConst.m; sourceTree = ""; }; - 32EACA7B3E95EF3C511EEAED34B5C23A /* MJRefreshBackGifFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshBackGifFooter.m; path = MJRefresh/Custom/Footer/Back/MJRefreshBackGifFooter.m; sourceTree = ""; }; - 33152C1C1E9FE19D1E9C8D8BF0C963DA /* SDWebImageOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageOperation.h; path = SDWebImage/Core/SDWebImageOperation.h; sourceTree = ""; }; - 3316E3BF456739AB7A0F0FD1920F5F6B /* MJExtension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = MJExtension.debug.xcconfig; sourceTree = ""; }; - 33EBB93597383ED9EEA18C0A9BCE3B84 /* ViewController+MASAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "ViewController+MASAdditions.m"; path = "Masonry/ViewController+MASAdditions.m"; sourceTree = ""; }; - 34B9AAE9B2C02781F4AC71AEDB56A439 /* MJRefreshStateTrailer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshStateTrailer.m; path = MJRefresh/Custom/Trailer/MJRefreshStateTrailer.m; sourceTree = ""; }; - 34CEE2DA708B82493E132F274E2E9493 /* SDImageGraphics.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageGraphics.h; path = SDWebImage/Core/SDImageGraphics.h; sourceTree = ""; }; - 34E2AA501576A0C5221012B9066EC56A /* SDAssociatedObject.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDAssociatedObject.h; path = SDWebImage/Private/SDAssociatedObject.h; sourceTree = ""; }; - 34F1A2FD98EEB8019052FBD5528585C9 /* SDWebImage-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "SDWebImage-dummy.m"; sourceTree = ""; }; - 3526591F674CF19FB39EF872089A7F49 /* MJRefreshAutoStateFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshAutoStateFooter.h; path = MJRefresh/Custom/Footer/Auto/MJRefreshAutoStateFooter.h; sourceTree = ""; }; + 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 = ""; }; 35BFA337F4E1FDE67C773A82CCDFD6DA /* Pods-keyBoard.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-keyBoard.debug.xcconfig"; sourceTree = ""; }; - 35F55EE8682F170A101CA85DD55D1B58 /* UIView+MJExtension.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIView+MJExtension.h"; path = "MJRefresh/UIView+MJExtension.h"; sourceTree = ""; }; - 371EEAE238A16CCB71633D3E6EF40F2B /* SDAnimatedImageView+WebCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "SDAnimatedImageView+WebCache.h"; path = "SDWebImage/Core/SDAnimatedImageView+WebCache.h"; sourceTree = ""; }; - 377FB4D51134D774594E6EAF0BB4DFAA /* UIImage+ExtendedCacheData.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+ExtendedCacheData.h"; path = "SDWebImage/Core/UIImage+ExtendedCacheData.h"; sourceTree = ""; }; - 37DCC80FE271D2095A398F8D8F22C7E7 /* NSBundle+MJRefresh.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSBundle+MJRefresh.m"; path = "MJRefresh/NSBundle+MJRefresh.m"; sourceTree = ""; }; - 38A043FDCD06C3C9914C9A22FB6B1D28 /* SDWebImage.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = SDWebImage.modulemap; sourceTree = ""; }; - 396F4E7921EA26CDE8AAEADDD8CFBB49 /* Masonry.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Masonry.release.xcconfig; sourceTree = ""; }; - 3B4BB6924504E595528A838685E1B608 /* UIScrollView+MJExtension.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIScrollView+MJExtension.m"; path = "MJRefresh/UIScrollView+MJExtension.m"; 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 = ""; }; 3CB13D51E717D347023EEB57263E3072 /* Pods-CustomKeyboard-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-CustomKeyboard-dummy.m"; sourceTree = ""; }; - 3D5935FEEF657D48BF93BE04A41CF816 /* UIView+WebCacheOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIView+WebCacheOperation.m"; path = "SDWebImage/Core/UIView+WebCacheOperation.m"; sourceTree = ""; }; - 3F58F61640AAFD16139A83CC4EA55B1D /* MASUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASUtilities.h; path = Masonry/MASUtilities.h; sourceTree = ""; }; - 3FBCEF9827DD721BAF021C98F7311D30 /* AFAutoPurgingImageCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFAutoPurgingImageCache.m; path = "UIKit+AFNetworking/AFAutoPurgingImageCache.m"; sourceTree = ""; }; - 4090C24D16A324EB9D2A6747886BD217 /* SDDeviceHelper.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDDeviceHelper.m; path = SDWebImage/Private/SDDeviceHelper.m; sourceTree = ""; }; - 42134A400043398C196C2BDF73B21075 /* SDAsyncBlockOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDAsyncBlockOperation.h; path = SDWebImage/Private/SDAsyncBlockOperation.h; sourceTree = ""; }; - 429C09B93893D24656048D336CE95D59 /* UIImage+GIF.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+GIF.h"; path = "SDWebImage/Core/UIImage+GIF.h"; sourceTree = ""; }; - 42FE2C6A18379D9944FBBA606FB88133 /* SDImageGIFCoder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageGIFCoder.m; path = SDWebImage/Core/SDImageGIFCoder.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 = ""; }; 43EAAD2AB7E6B407E80E95F643F93D22 /* MJExtension-MJExtension */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = "MJExtension-MJExtension"; path = MJExtension.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; - 4638EBD469283AF4DC5CBD3CE927D254 /* UIButton+WebCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIButton+WebCache.m"; path = "SDWebImage/Core/UIButton+WebCache.m"; sourceTree = ""; }; - 46F91B0801CEBD1D73003708566CC913 /* UIImage+Metadata.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+Metadata.m"; path = "SDWebImage/Core/UIImage+Metadata.m"; sourceTree = ""; }; - 4797723C6D7C918B816F46FCFB028F6F /* UIImage+MemoryCacheCost.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+MemoryCacheCost.h"; path = "SDWebImage/Core/UIImage+MemoryCacheCost.h"; sourceTree = ""; }; - 4830CF5BA96EF2AA3AC7496D62A49A0D /* MJFoundation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJFoundation.m; path = MJExtension/MJFoundation.m; sourceTree = ""; }; - 48E4A519DF8188F67D6109DB1AF82FF9 /* SDDisplayLink.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDDisplayLink.m; path = SDWebImage/Private/SDDisplayLink.m; sourceTree = ""; }; - 4A71363040CF6A8E6D918CEF79A555D5 /* SDWebImageCacheSerializer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageCacheSerializer.h; path = SDWebImage/Core/SDWebImageCacheSerializer.h; sourceTree = ""; }; - 4AFCF05D160C4A925AEC624ED1CD826F /* NSObject+MJProperty.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSObject+MJProperty.m"; path = "MJExtension/NSObject+MJProperty.m"; sourceTree = ""; }; - 4B22EE0B7D2C1D1066750C4AB84FDA27 /* MJExtension.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = MJExtension.release.xcconfig; sourceTree = ""; }; - 4C41FE7B076060F0600FEC9D5AFF762A /* UIActivityIndicatorView+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIActivityIndicatorView+AFNetworking.m"; path = "UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.m"; sourceTree = ""; }; - 4C64CBB1952BF537420E489E4AF7DED5 /* UIScrollView+MJRefresh.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIScrollView+MJRefresh.h"; path = "MJRefresh/UIScrollView+MJRefresh.h"; sourceTree = ""; }; - 4CD2E3B8C4EBAB8CE1F46D4D7B1B5CAA /* Bugly.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Bugly.debug.xcconfig; sourceTree = ""; }; - 4EF47C40D45E06BA89946B4C9F04A546 /* Masonry.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Masonry.debug.xcconfig; sourceTree = ""; }; - 4F51691B6717B6D9E4E3FE0977CF3163 /* SDWebImageDownloaderResponseModifier.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageDownloaderResponseModifier.m; path = SDWebImage/Core/SDWebImageDownloaderResponseModifier.m; sourceTree = ""; }; - 50DC89AF710F42BFF3D4C048EFAC8BB7 /* SDImageLoader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageLoader.h; path = SDWebImage/Core/SDImageLoader.h; sourceTree = ""; }; - 517973DC2D89829B73698FF20240431A /* AFURLResponseSerialization.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFURLResponseSerialization.h; path = AFNetworking/AFURLResponseSerialization.h; sourceTree = ""; }; - 523BDC065F0AF63F170A84FAF905FD26 /* AFNetworkReachabilityManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFNetworkReachabilityManager.h; path = AFNetworking/AFNetworkReachabilityManager.h; sourceTree = ""; }; - 52AA08F30FFF4D9FF32F48E3AC195A6A /* AFSecurityPolicy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFSecurityPolicy.m; path = AFNetworking/AFSecurityPolicy.m; sourceTree = ""; }; - 52AD4C798F619843C6425BB666EE43A0 /* MASLayoutConstraint.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASLayoutConstraint.h; path = Masonry/MASLayoutConstraint.h; sourceTree = ""; }; + 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 = ""; }; 5327DD01C6533D102D66E1636B3827F3 /* Pods-keyBoard-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-keyBoard-acknowledgements.plist"; sourceTree = ""; }; - 53392BC7B7115E12AC2077F4447BF455 /* MJRefreshFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshFooter.h; path = MJRefresh/Base/MJRefreshFooter.h; sourceTree = ""; }; - 56347C360CEDAA8246A01A213DEBBF8B /* UIImageView+HighlightedWebCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImageView+HighlightedWebCache.m"; path = "SDWebImage/Core/UIImageView+HighlightedWebCache.m"; sourceTree = ""; }; - 5679D7FEFDE3E519C17C0EAAA7867122 /* NSLayoutConstraint+MASDebugAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSLayoutConstraint+MASDebugAdditions.h"; path = "Masonry/NSLayoutConstraint+MASDebugAdditions.h"; sourceTree = ""; }; - 568638C925360332377ACFB503131A76 /* MJRefreshAutoFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshAutoFooter.m; path = MJRefresh/Base/MJRefreshAutoFooter.m; sourceTree = ""; }; - 569FA95248CF0B824C3928196386FFC2 /* MJExtension.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJExtension.h; path = MJExtension/MJExtension.h; sourceTree = ""; }; - 5713367A1E361064DE338AB389631FF5 /* MJRefreshNormalHeader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshNormalHeader.h; path = MJRefresh/Custom/Header/MJRefreshNormalHeader.h; sourceTree = ""; }; - 575E3DAA2F5DDC8FBD895B8BEA5FB8C6 /* SDWebImageTransition.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageTransition.h; path = SDWebImage/Core/SDWebImageTransition.h; sourceTree = ""; }; - 5A50D4A4631B759E5D73FDFF78C8BF75 /* NSObject+MJClass.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSObject+MJClass.m"; path = "MJExtension/NSObject+MJClass.m"; sourceTree = ""; }; - 5AC074355067D4E88EB993DD28E44948 /* MASConstraint+Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "MASConstraint+Private.h"; path = "Masonry/MASConstraint+Private.h"; sourceTree = ""; }; - 5BA0325112AB8CA7AB613D1A8ED2DB65 /* 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; }; - 5DD19473CA2658646B964B6124A31FB9 /* AFURLRequestSerialization.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFURLRequestSerialization.h; path = AFNetworking/AFURLRequestSerialization.h; sourceTree = ""; }; - 5E8106411081DD6C7F5FE7804947412C /* Masonry-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Masonry-dummy.m"; sourceTree = ""; }; - 5FD6594A1D1613C90FF5EF2CBD5CE123 /* SDGraphicsImageRenderer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDGraphicsImageRenderer.h; path = SDWebImage/Core/SDGraphicsImageRenderer.h; sourceTree = ""; }; - 5FDFD2C717749B65FE64DACB99DF72A3 /* MJRefresh.bundle */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "wrapper.plug-in"; name = MJRefresh.bundle; path = MJRefresh/MJRefresh.bundle; sourceTree = ""; }; - 6134DA50CBB0F618C7502B9B4E23963F /* Bugly.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Bugly.release.xcconfig; sourceTree = ""; }; - 61B4061AC178FEE58C9618133524CF08 /* SDmetamacros.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDmetamacros.h; path = SDWebImage/Private/SDmetamacros.h; sourceTree = ""; }; - 61D0A0EB33F4B0A380D6DE9E8E5D56D7 /* AFImageDownloader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFImageDownloader.m; path = "UIKit+AFNetworking/AFImageDownloader.m"; 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 = ""; }; + 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 = ""; }; 641251D3092FFCF2B6259BF8676A212E /* Pods-CustomKeyboard-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-CustomKeyboard-Info.plist"; sourceTree = ""; }; - 646B483EDAD1F8B7F96981EB5E185F2E /* SDWebImageError.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageError.h; path = SDWebImage/Core/SDWebImageError.h; sourceTree = ""; }; - 661BCD3C752D21E81C83DA14D3C4502A /* SDGraphicsImageRenderer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDGraphicsImageRenderer.m; path = SDWebImage/Core/SDGraphicsImageRenderer.m; sourceTree = ""; }; - 678A010D7D73785C1E08D97B5F67AAAA /* SDCallbackQueue.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDCallbackQueue.h; path = SDWebImage/Core/SDCallbackQueue.h; sourceTree = ""; }; - 67DDCFED9CF39A1F995D9E7B12E35A7E /* SDWebImage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImage.h; path = WebImage/SDWebImage.h; sourceTree = ""; }; - 6C4CAA32BF7068345545D717BAAF7069 /* SDWebImageCacheSerializer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageCacheSerializer.m; path = SDWebImage/Core/SDWebImageCacheSerializer.m; sourceTree = ""; }; - 6DE36A434A8BD3593CCBD95090373332 /* SDWebImageDefine.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageDefine.m; path = SDWebImage/Core/SDWebImageDefine.m; sourceTree = ""; }; - 6DFD30C63C15966EA8BF3CAD55EB97F8 /* SDDiskCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDDiskCache.h; path = SDWebImage/Core/SDDiskCache.h; sourceTree = ""; }; - 6E7A746456C4F5E2C887572055F6A833 /* SDImageTransformer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageTransformer.m; path = SDWebImage/Core/SDImageTransformer.m; sourceTree = ""; }; - 6EB624EDC7B2F6F92D5F6AEF8AAA4356 /* ViewController+MASAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "ViewController+MASAdditions.h"; path = "Masonry/ViewController+MASAdditions.h"; sourceTree = ""; }; - 70330531B46EEB4398625F2AFC6683E5 /* SDWebImage-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SDWebImage-umbrella.h"; sourceTree = ""; }; - 71A4B6E144674403F50435C67561B1BB /* WKWebView+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "WKWebView+AFNetworking.m"; path = "UIKit+AFNetworking/WKWebView+AFNetworking.m"; sourceTree = ""; }; - 71B30FE27ADA94703A3F06804277A5C0 /* MJRefreshBackStateFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshBackStateFooter.m; path = MJRefresh/Custom/Footer/Back/MJRefreshBackStateFooter.m; sourceTree = ""; }; - 71C9A7FB9BC0D7C0FA902D0643B08962 /* MASConstraint.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASConstraint.h; path = Masonry/MASConstraint.h; sourceTree = ""; }; - 724FB5172055CF20AE6E6F4D007D8038 /* MJRefreshHeader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshHeader.h; path = MJRefresh/Base/MJRefreshHeader.h; sourceTree = ""; }; - 72789BA685A26A276A98609F54509572 /* MJRefresh-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "MJRefresh-prefix.pch"; sourceTree = ""; }; - 7315702A1F332F57A8765F720EE5B18F /* SDImageAWebPCoder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageAWebPCoder.h; path = SDWebImage/Core/SDImageAWebPCoder.h; sourceTree = ""; }; - 73D1ED74B2085AA85B8213943DE4AD83 /* MJRefreshNormalTrailer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshNormalTrailer.h; path = MJRefresh/Custom/Trailer/MJRefreshNormalTrailer.h; sourceTree = ""; }; - 74446596F2A689B17D9187482A194EEC /* AFURLRequestSerialization.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFURLRequestSerialization.m; path = AFNetworking/AFURLRequestSerialization.m; sourceTree = ""; }; - 74CC813EBCFDBA413D1E8F2AE302E41A /* MJRefresh.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = MJRefresh.debug.xcconfig; sourceTree = ""; }; - 7506ED7F0118C1C5FE230328CCC6543E /* AFURLSessionManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFURLSessionManager.m; path = AFNetworking/AFURLSessionManager.m; sourceTree = ""; }; - 755B7205B482C6B79DEAE02978E7FD20 /* SDWebImageTransitionInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageTransitionInternal.h; path = SDWebImage/Private/SDWebImageTransitionInternal.h; sourceTree = ""; }; - 76F97ACAD92849B1F665FD0FF282B3C8 /* SDWebImageOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageOperation.m; path = SDWebImage/Core/SDWebImageOperation.m; sourceTree = ""; }; - 7842E350E0D12563DE7C0EB363356BF8 /* MJPropertyType.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJPropertyType.m; path = MJExtension/MJPropertyType.m; sourceTree = ""; }; - 7869EB02C0774141B550180F17DBF9F0 /* SDImageLoader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageLoader.m; path = SDWebImage/Core/SDImageLoader.m; sourceTree = ""; }; - 78744B8D1235EE30BFB429D8C13D63F4 /* AFNetworking.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = AFNetworking.debug.xcconfig; sourceTree = ""; }; - 7980625AB48FABAF33EDB825FF587011 /* SDWebImageCompat.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageCompat.m; path = SDWebImage/Core/SDWebImageCompat.m; sourceTree = ""; }; - 7A46DCA8F7BDEE6453116CAF6CBBAC40 /* NSBezierPath+SDRoundedCorners.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSBezierPath+SDRoundedCorners.h"; path = "SDWebImage/Private/NSBezierPath+SDRoundedCorners.h"; sourceTree = ""; }; - 7AE552655E7E703CCEDD4BE44EFA5662 /* UIButton+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIButton+AFNetworking.h"; path = "UIKit+AFNetworking/UIButton+AFNetworking.h"; sourceTree = ""; }; - 7B6867FF0B2276E04032D8E5C44B4EB9 /* SDWebImageCompat.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageCompat.h; path = SDWebImage/Core/SDWebImageCompat.h; sourceTree = ""; }; - 7C1791A7C256B13C227BF8DAE4C2EFE9 /* MASConstraint.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASConstraint.m; path = Masonry/MASConstraint.m; sourceTree = ""; }; - 7C38C5957F4EAC459AB28A71622C865C /* SDImageAPNGCoder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageAPNGCoder.h; path = SDWebImage/Core/SDImageAPNGCoder.h; sourceTree = ""; }; - 7D3CFDF279C9B9946089A89EFB72A50D /* UIView+WebCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIView+WebCache.m"; path = "SDWebImage/Core/UIView+WebCache.m"; sourceTree = ""; }; - 7D4327E5DC3980134C42B829E8798AA4 /* MJRefreshAutoFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshAutoFooter.h; path = MJRefresh/Base/MJRefreshAutoFooter.h; sourceTree = ""; }; - 7D8FF130378AA0390E3754AB93673319 /* MJProperty.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJProperty.h; path = MJExtension/MJProperty.h; 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 = ""; }; 7E3097CFEFDA621E9FB0E62009FF87FC /* MJRefresh-MJRefresh.Privacy */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = "MJRefresh-MJRefresh.Privacy"; path = MJRefresh.Privacy.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; - 7E6DD5C54D7EC67B674C64E88446BAA7 /* MJRefreshAutoNormalFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshAutoNormalFooter.m; path = MJRefresh/Custom/Footer/Auto/MJRefreshAutoNormalFooter.m; sourceTree = ""; }; - 7E72BDE0490314836A44AFEE2FD465C2 /* AFNetworking.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = AFNetworking.modulemap; sourceTree = ""; }; - 801C19E603261CA9778C89D068D49697 /* SDWebImage-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SDWebImage-prefix.pch"; sourceTree = ""; }; - 80E9D6278C5650A6AD05F331651F6DEB /* SDImageLoadersManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageLoadersManager.h; path = SDWebImage/Core/SDImageLoadersManager.h; sourceTree = ""; }; - 81D5F6E26D64BB94294CEC208FAEEBE2 /* SDAnimatedImagePlayer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDAnimatedImagePlayer.h; path = SDWebImage/Core/SDAnimatedImagePlayer.h; sourceTree = ""; }; - 825CA08D9974B4E876CAFA68A0F53F93 /* SDWebImageDownloaderOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageDownloaderOperation.m; path = SDWebImage/Core/SDWebImageDownloaderOperation.m; sourceTree = ""; }; - 830D06A83C1E8E77E539514107F83812 /* SDImageGraphics.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageGraphics.m; path = SDWebImage/Core/SDImageGraphics.m; sourceTree = ""; }; - 8332CB32D0FA2CE8D910AA5A9BE18D8B /* SDImageCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageCache.m; path = SDWebImage/Core/SDImageCache.m; sourceTree = ""; }; - 840FE4FBC8DFDB4B1238B06FEA5AF259 /* UIImage+ForceDecode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+ForceDecode.m"; path = "SDWebImage/Core/UIImage+ForceDecode.m"; sourceTree = ""; }; - 8430A616C01FADC1B0DB9E5D08A03C35 /* SDImageHEICCoder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageHEICCoder.h; path = SDWebImage/Core/SDImageHEICCoder.h; sourceTree = ""; }; - 851329DB564FCDDAD9A52952F487E28D /* UIColor+SDHexString.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIColor+SDHexString.h"; path = "SDWebImage/Private/UIColor+SDHexString.h"; sourceTree = ""; }; - 852C84F2242375BE5446ADE5B9509933 /* ResourceBundle-MJRefresh.Privacy-MJRefresh-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-MJRefresh.Privacy-MJRefresh-Info.plist"; sourceTree = ""; }; - 859BA7601F83844D2D2ABC395E386663 /* AFNetworkActivityIndicatorManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFNetworkActivityIndicatorManager.m; path = "UIKit+AFNetworking/AFNetworkActivityIndicatorManager.m"; sourceTree = ""; }; - 85AD1C60C75A73E360E4320DD271A77D /* AFSecurityPolicy.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFSecurityPolicy.h; path = AFNetworking/AFSecurityPolicy.h; sourceTree = ""; }; - 87A1195922F05E5D23FF9A3C4509A854 /* MJProperty.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJProperty.m; path = MJExtension/MJProperty.m; sourceTree = ""; }; - 88799C33D6D0AAE2D395A1496F3A9E5D /* View+MASAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "View+MASAdditions.h"; path = "Masonry/View+MASAdditions.h"; sourceTree = ""; }; - 897B6BFD5EA50E7440FD4FA3769B3C78 /* UIImage+MultiFormat.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+MultiFormat.h"; path = "SDWebImage/Core/UIImage+MultiFormat.h"; sourceTree = ""; }; - 8A926EA8E3863425810DDC585C464587 /* SDWebImageDownloaderConfig.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageDownloaderConfig.h; path = SDWebImage/Core/SDWebImageDownloaderConfig.h; sourceTree = ""; }; - 8AACAEAAD31005B66599055215ADA658 /* SDAnimatedImageView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDAnimatedImageView.h; path = SDWebImage/Core/SDAnimatedImageView.h; sourceTree = ""; }; - 8ABF0BFFB097FE97D207EBE5498289D3 /* MASConstraintMaker.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASConstraintMaker.m; path = Masonry/MASConstraintMaker.m; sourceTree = ""; }; - 8AF059A8B1C2B3EE76BCDE329D0C926E /* UIScrollView+MJRefresh.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIScrollView+MJRefresh.m"; path = "MJRefresh/UIScrollView+MJRefresh.m"; sourceTree = ""; }; - 8BECBF70665658E16C4E9DDD74C7161A /* MJRefreshConst.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshConst.m; path = MJRefresh/MJRefreshConst.m; sourceTree = ""; }; - 8C0AB8960CBA6D24923E096B9378691C /* AFHTTPSessionManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFHTTPSessionManager.m; path = AFNetworking/AFHTTPSessionManager.m; sourceTree = ""; }; - 8E7292A83C005323B245A7EF2737878F /* MJRefreshNormalTrailer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshNormalTrailer.m; path = MJRefresh/Custom/Trailer/MJRefreshNormalTrailer.m; sourceTree = ""; }; - 8FC489301C2534B7DD53B90720E80BF3 /* UIImage+ExtendedCacheData.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+ExtendedCacheData.m"; path = "SDWebImage/Core/UIImage+ExtendedCacheData.m"; sourceTree = ""; }; - 90687AA744E720C17FD8600B60F43FF5 /* NSData+ImageContentType.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSData+ImageContentType.m"; path = "SDWebImage/Core/NSData+ImageContentType.m"; sourceTree = ""; }; - 916FC91BADACF2A6F0FF12F1385FC1D4 /* SDWebImagePrefetcher.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImagePrefetcher.m; path = SDWebImage/Core/SDWebImagePrefetcher.m; sourceTree = ""; }; - 92D14A3D3FA826806436A8CFCBD915DA /* Masonry-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Masonry-umbrella.h"; sourceTree = ""; }; - 93A3B9C517383784D38DA222632F5FFB /* SDWeakProxy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWeakProxy.m; path = SDWebImage/Private/SDWeakProxy.m; sourceTree = ""; }; - 93D1581B25C7E0154AE410EBB56CE516 /* SDImageCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageCache.h; path = SDWebImage/Core/SDImageCache.h; sourceTree = ""; }; - 93EB15003C1E2452E5C21AD7FF38A39D /* NSArray+MASAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSArray+MASAdditions.h"; path = "Masonry/NSArray+MASAdditions.h"; sourceTree = ""; }; - 94F556719E0728E491D5BDF953E9A668 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; name = PrivacyInfo.xcprivacy; path = MJRefresh/PrivacyInfo.xcprivacy; sourceTree = ""; }; - 950F7A4DEA1A2D31E4A650C9526788F7 /* MJPropertyType.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJPropertyType.h; path = MJExtension/MJPropertyType.h; sourceTree = ""; }; + 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 = ""; }; + 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 = ""; }; 969A9A842778EFB5D62826500DFF4E11 /* Pods-keyBoard-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-keyBoard-dummy.m"; sourceTree = ""; }; - 969BDA148FEBCD19E1B7701E7F70E539 /* SDWebImageDownloaderRequestModifier.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageDownloaderRequestModifier.h; path = SDWebImage/Core/SDWebImageDownloaderRequestModifier.h; sourceTree = ""; }; - 970B39752136D5831550118975DC4A91 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; name = PrivacyInfo.xcprivacy; path = MJExtension/PrivacyInfo.xcprivacy; sourceTree = ""; }; - 9784638759F544FA3CC67A7E0CA9454B /* Bugly.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Bugly.framework; sourceTree = ""; }; - 97F65BC08A412ED6706647722A834532 /* SDImageCacheDefine.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageCacheDefine.h; path = SDWebImage/Core/SDImageCacheDefine.h; sourceTree = ""; }; - 9802609AB0266E444A1BD29FA119D9BC /* SDWebImageCacheKeyFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageCacheKeyFilter.h; path = SDWebImage/Core/SDWebImageCacheKeyFilter.h; sourceTree = ""; }; - 982D370CD4E116E0C1917E832541C530 /* UIImageView+HighlightedWebCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImageView+HighlightedWebCache.h"; path = "SDWebImage/Core/UIImageView+HighlightedWebCache.h"; sourceTree = ""; }; - 98E94877A92313B71CB6789264CC6752 /* AFNetworking-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "AFNetworking-Info.plist"; sourceTree = ""; }; - 9954286F43C39384A1EADABA9AAE0B0D /* SDAnimatedImageRep.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDAnimatedImageRep.m; path = SDWebImage/Core/SDAnimatedImageRep.m; sourceTree = ""; }; - 9ADF16A9C4A54B7486F74B1F31DE3947 /* Masonry-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Masonry-Info.plist"; sourceTree = ""; }; - 9AF4B903EB65570DDDE8731659809CA1 /* SDImageCacheDefine.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageCacheDefine.m; path = SDWebImage/Core/SDImageCacheDefine.m; sourceTree = ""; }; - 9B7D77CB378449CF4A7041A3EA89C102 /* SDImageFrame.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageFrame.m; path = SDWebImage/Core/SDImageFrame.m; sourceTree = ""; }; - 9C040DD9465E298ACD105143A3265009 /* NSImage+Compatibility.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSImage+Compatibility.m"; path = "SDWebImage/Core/NSImage+Compatibility.m"; sourceTree = ""; }; - 9D403D54754F62E7ECBA2668B217E5FD /* NSObject+MJCoding.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSObject+MJCoding.m"; path = "MJExtension/NSObject+MJCoding.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 = ""; }; 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; }; - 9DBD448EB576D346FBA1D20A1BD13F1D /* SDImageCachesManagerOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageCachesManagerOperation.h; path = SDWebImage/Private/SDImageCachesManagerOperation.h; sourceTree = ""; }; + 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 = ""; }; - 9E2F76F628A20AA296860E039C6A51DE /* UIButton+WebCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIButton+WebCache.h"; path = "SDWebImage/Core/UIButton+WebCache.h"; sourceTree = ""; }; - 9E3334C24AC0A37A21A6D9B9ECA94AB2 /* WKWebView+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "WKWebView+AFNetworking.h"; path = "UIKit+AFNetworking/WKWebView+AFNetworking.h"; sourceTree = ""; }; - A11030FED687E26E2A7953D880C8DDD7 /* SDWebImageTransition.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageTransition.m; path = SDWebImage/Core/SDWebImageTransition.m; sourceTree = ""; }; - A113F5BE027C0A2BC1CC3F420069F969 /* SDDiskCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDDiskCache.m; path = SDWebImage/Core/SDDiskCache.m; sourceTree = ""; }; - A1D6DA8B66269F171ED8918C664075F4 /* SDWebImageDownloaderOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageDownloaderOperation.h; path = SDWebImage/Core/SDWebImageDownloaderOperation.h; sourceTree = ""; }; - A1ECACF57484B51D17735566ED038104 /* SDImageLoadersManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageLoadersManager.m; path = SDWebImage/Core/SDImageLoadersManager.m; sourceTree = ""; }; - A20073D67775A184A6AEF2667BC7628C /* MJRefreshStateHeader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshStateHeader.h; path = MJRefresh/Custom/Header/MJRefreshStateHeader.h; sourceTree = ""; }; - A294AA5EAB4FD3CAF8C4A072117591C1 /* SDInternalMacros.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDInternalMacros.h; path = SDWebImage/Private/SDInternalMacros.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 = ""; }; 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 = ""; }; A4FA15D44DF6BAC7550EDEED10862AA3 /* AFNetworking */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = AFNetworking; path = AFNetworking.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - A6CCAA7B0AD1373217438DACF7AB456C /* SDMemoryCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDMemoryCache.m; path = SDWebImage/Core/SDMemoryCache.m; sourceTree = ""; }; + 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 = ""; }; A6E8FF241173D596A21D4D4B7D86A810 /* Pods-keyBoard.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-keyBoard.release.xcconfig"; sourceTree = ""; }; - A87E9EA0B6E9AB8C1E29A3AE50F278CB /* UIView+WebCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIView+WebCache.h"; path = "SDWebImage/Core/UIView+WebCache.h"; sourceTree = ""; }; - A95F96D9DAA700949C3A302C92FD9231 /* AFURLSessionManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFURLSessionManager.h; path = AFNetworking/AFURLSessionManager.h; sourceTree = ""; }; - A9F5CF889820DAD55268C3832155A2E1 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; name = PrivacyInfo.xcprivacy; path = WebImage/PrivacyInfo.xcprivacy; sourceTree = ""; }; - AB321552F4E1B0F80966FCA9AF11848F /* UIImageView+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImageView+AFNetworking.h"; path = "UIKit+AFNetworking/UIImageView+AFNetworking.h"; sourceTree = ""; }; - AB8EC26A51378B3F4C5559E371607480 /* SDImageFrame.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageFrame.h; path = SDWebImage/Core/SDImageFrame.h; sourceTree = ""; }; - AC2514CF7A7B043E035CFB079E6FB5A0 /* SDDeviceHelper.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDDeviceHelper.h; path = SDWebImage/Private/SDDeviceHelper.h; sourceTree = ""; }; - ADF1D8C19CC2D66E65B4B1746316FFC5 /* SDWebImageOptionsProcessor.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageOptionsProcessor.m; path = SDWebImage/Core/SDWebImageOptionsProcessor.m; sourceTree = ""; }; - AECAC2F59ABD4A78D2B73C898E485890 /* MJRefresh-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "MJRefresh-umbrella.h"; sourceTree = ""; }; - AED6E178EFE04C18394DE24CF7E24E01 /* UIView+WebCacheOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIView+WebCacheOperation.h"; path = "SDWebImage/Core/UIView+WebCacheOperation.h"; sourceTree = ""; }; - AF26D1DF8BE4D63027161EEBE6FDE7AE /* SDCallbackQueue.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDCallbackQueue.m; path = SDWebImage/Core/SDCallbackQueue.m; sourceTree = ""; }; - AF6FBF6EC0693B752A91650764E380C8 /* UIImage+Transform.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+Transform.h"; path = "SDWebImage/Core/UIImage+Transform.h"; sourceTree = ""; }; - AF94F3E24B633799AB0B2B75B193A4F3 /* UIImageView+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImageView+AFNetworking.m"; path = "UIKit+AFNetworking/UIImageView+AFNetworking.m"; sourceTree = ""; }; - B070DCCCA22D6ECC24DC0BD5CCEF5372 /* UIRefreshControl+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIRefreshControl+AFNetworking.m"; path = "UIKit+AFNetworking/UIRefreshControl+AFNetworking.m"; 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 = ""; }; B0B214D775196BA7CA8E17E53048A493 /* SDWebImage */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = SDWebImage; path = SDWebImage.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - B147B49E855B11A35493E26865607BDF /* NSBezierPath+SDRoundedCorners.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSBezierPath+SDRoundedCorners.m"; path = "SDWebImage/Private/NSBezierPath+SDRoundedCorners.m"; sourceTree = ""; }; - B1CE88DD0007C23B107D2BD3A6AB545B /* MJRefreshTrailer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshTrailer.m; path = MJRefresh/Base/MJRefreshTrailer.m; sourceTree = ""; }; - B20A669086F5506692603D3336437ABD /* SDAnimatedImagePlayer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDAnimatedImagePlayer.m; path = SDWebImage/Core/SDAnimatedImagePlayer.m; sourceTree = ""; }; - B3A54C7306CBDB1BC3189CCF492C92DE /* SDImageCoder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageCoder.h; path = SDWebImage/Core/SDImageCoder.h; sourceTree = ""; }; - B509365346F676352BBC6630F5F1FADB /* SDWebImageError.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageError.m; path = SDWebImage/Core/SDWebImageError.m; sourceTree = ""; }; - B6011963612818816E2CF40CED8B0112 /* MJRefreshTrailer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshTrailer.h; path = MJRefresh/Base/MJRefreshTrailer.h; sourceTree = ""; }; - B60142D76441D9D2B7BA4991E7523577 /* SDImageGIFCoder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageGIFCoder.h; path = SDWebImage/Core/SDImageGIFCoder.h; sourceTree = ""; }; - B61705A318B7E4CE5BB4A9A618397777 /* MJExtension-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "MJExtension-prefix.pch"; sourceTree = ""; }; - B7BBB3446628A3BC637B9F57A5C49901 /* AFNetworkReachabilityManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFNetworkReachabilityManager.m; path = AFNetworking/AFNetworkReachabilityManager.m; sourceTree = ""; }; - B9DF6B027952E0BE3781007ECC6436E7 /* SDWebImageOptionsProcessor.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageOptionsProcessor.h; path = SDWebImage/Core/SDWebImageOptionsProcessor.h; sourceTree = ""; }; - BCC0677B77FA6DFFDE007551F1660B1E /* UICollectionViewLayout+MJRefresh.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UICollectionViewLayout+MJRefresh.m"; path = "MJRefresh/UICollectionViewLayout+MJRefresh.m"; sourceTree = ""; }; - BE440D8DEC29075E20FE83DB3AB2620D /* AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFNetworking.h; path = AFNetworking/AFNetworking.h; sourceTree = ""; }; - BE6C3AB94897685F9464AA252C4EFB17 /* MJRefreshConst.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshConst.h; path = MJRefresh/MJRefreshConst.h; sourceTree = ""; }; - BEC2871B1357A63D88FCC0144C7847CD /* MJRefreshConfig.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshConfig.h; path = MJRefresh/MJRefreshConfig.h; sourceTree = ""; }; - BF154B0F2EB8913A8674795FD63311D2 /* SDImageAPNGCoder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageAPNGCoder.m; path = SDWebImage/Core/SDImageAPNGCoder.m; sourceTree = ""; }; - BF3675A98BB80F2630D08AB3BE31E1B7 /* SDImageFramePool.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageFramePool.m; path = SDWebImage/Private/SDImageFramePool.m; sourceTree = ""; }; - C23DF793769699E27A02E0B30615EF6F /* NSObject+MJKeyValue.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSObject+MJKeyValue.m"; path = "MJExtension/NSObject+MJKeyValue.m"; sourceTree = ""; }; - C3EC2E3BBB3895884BB4AA3B74A54476 /* SDImageCodersManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageCodersManager.m; path = SDWebImage/Core/SDImageCodersManager.m; sourceTree = ""; }; - C55407E10212267DCB2FC49D3260EF48 /* UIScrollView+MJExtension.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIScrollView+MJExtension.h"; path = "MJRefresh/UIScrollView+MJExtension.h"; sourceTree = ""; }; - C5D0E76AC56695893DB1713CA7212B8C /* MJExtension-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "MJExtension-umbrella.h"; sourceTree = ""; }; - C5D645FDA53D7713D436C992B2BC3E96 /* SDImageCacheConfig.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageCacheConfig.m; path = SDWebImage/Core/SDImageCacheConfig.m; sourceTree = ""; }; - C6C465F665338FA163A2F6623C933047 /* UIImageView+WebCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImageView+WebCache.m"; path = "SDWebImage/Core/UIImageView+WebCache.m"; sourceTree = ""; }; - C71B36DE1531E30C6C8E2592C55C0ED5 /* MJRefresh-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "MJRefresh-dummy.m"; sourceTree = ""; }; + 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 = ""; }; CAD1D653361EAFCC0E4FFD8252FC1E74 /* Pods-CustomKeyboard.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-CustomKeyboard.modulemap"; sourceTree = ""; }; - CC69297E62F679246B8FE5B49D774CF4 /* AFNetworking-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "AFNetworking-dummy.m"; sourceTree = ""; }; - CCDB436E5F20F839485E728CEF386187 /* MJRefreshAutoStateFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshAutoStateFooter.m; path = MJRefresh/Custom/Footer/Auto/MJRefreshAutoStateFooter.m; sourceTree = ""; }; - CEC061A3621F113DA97A66F89E6A844B /* AFURLResponseSerialization.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFURLResponseSerialization.m; path = AFNetworking/AFURLResponseSerialization.m; 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 = ""; }; CF1281E58AA1045D4B7F33FC56691C42 /* SDWebImage-SDWebImage */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = "SDWebImage-SDWebImage"; path = SDWebImage.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; - D0275B47D80FC8AE3A59DFAEA8C65E1C /* MJRefresh-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "MJRefresh-Info.plist"; sourceTree = ""; }; - D0B1FCAC31B9EF58F1FD85B83EA55B1C /* SDWebImageIndicator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageIndicator.h; path = SDWebImage/Core/SDWebImageIndicator.h; sourceTree = ""; }; - D13BE3E84BFB9462CF54B22B35F89ADC /* SDFileAttributeHelper.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDFileAttributeHelper.h; path = SDWebImage/Private/SDFileAttributeHelper.h; sourceTree = ""; }; - D28BB6B7AF2BC47AA045CB28AE578B56 /* MASViewConstraint.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASViewConstraint.m; path = Masonry/MASViewConstraint.m; sourceTree = ""; }; - D513B9FE4981B810C5EBD34AAD6D0CD7 /* MJRefreshStateHeader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshStateHeader.m; path = MJRefresh/Custom/Header/MJRefreshStateHeader.m; sourceTree = ""; }; + 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 = ""; }; D742A7EF918BC67B0884AF366F7415FD /* Pods-CustomKeyboard-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-CustomKeyboard-acknowledgements.plist"; sourceTree = ""; }; - D875CFB5AA1591E80BD3A95A94255894 /* AFNetworkActivityIndicatorManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFNetworkActivityIndicatorManager.h; path = "UIKit+AFNetworking/AFNetworkActivityIndicatorManager.h"; sourceTree = ""; }; - D915858ABB2794C80C0D2328483F75C4 /* NSObject+MJKeyValue.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSObject+MJKeyValue.h"; path = "MJExtension/NSObject+MJKeyValue.h"; sourceTree = ""; }; - D99D7FCB3FD62B8D8BF11087E1D6E47F /* SDWebImageDownloaderResponseModifier.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageDownloaderResponseModifier.h; path = SDWebImage/Core/SDWebImageDownloaderResponseModifier.h; sourceTree = ""; }; - DBEED872AB83B013F34A14A1823F4820 /* SDImageCodersManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageCodersManager.h; path = SDWebImage/Core/SDImageCodersManager.h; sourceTree = ""; }; - DBFD2ECA52ECDAAA78246FE8B02312A9 /* SDFileAttributeHelper.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDFileAttributeHelper.m; path = SDWebImage/Private/SDFileAttributeHelper.m; sourceTree = ""; }; - DC6CF0A46A4D9FFFBA2057678DF1978B /* SDAnimatedImage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDAnimatedImage.m; path = SDWebImage/Core/SDAnimatedImage.m; sourceTree = ""; }; - DC6DB03243923516662807D789FF26B1 /* UIView+WebCacheState.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIView+WebCacheState.h"; path = "SDWebImage/Core/UIView+WebCacheState.h"; 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 = ""; }; DCA062FD08AC9694D8D781B3492421C5 /* Pods-keyBoard */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = "Pods-keyBoard"; path = Pods_keyBoard.framework; sourceTree = BUILT_PRODUCTS_DIR; }; DCFE00F3CC8CED67258D7F7DD13F3156 /* Pods-keyBoard-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-keyBoard-frameworks.sh"; sourceTree = ""; }; - DDAE741F085915AF2475C918F1A17466 /* 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; }; - DDC08D9E69C76309DA07F96C62824633 /* NSData+ImageContentType.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSData+ImageContentType.h"; path = "SDWebImage/Core/NSData+ImageContentType.h"; sourceTree = ""; }; - DE966A3AAABAC126A570DC36F74E07AE /* NSLayoutConstraint+MASDebugAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSLayoutConstraint+MASDebugAdditions.m"; path = "Masonry/NSLayoutConstraint+MASDebugAdditions.m"; sourceTree = ""; }; - DEAC3EFF66D7CCDC2824B18A44FDBB3B /* MJRefresh.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = MJRefresh.modulemap; sourceTree = ""; }; - DF80C56AF1D41887B8622FAC95138810 /* MJRefresh.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = MJRefresh.release.xcconfig; sourceTree = ""; }; - DFD5A14F9DC74814903A901B625C5A94 /* SDImageAWebPCoder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageAWebPCoder.m; path = SDWebImage/Core/SDImageAWebPCoder.m; sourceTree = ""; }; - E0E66128C9FA5581B5257A03454E3761 /* MJExtension.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = MJExtension.modulemap; sourceTree = ""; }; - E135DFBB6A830F84DCF4A1D31534EE65 /* View+MASAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "View+MASAdditions.m"; path = "Masonry/View+MASAdditions.m"; sourceTree = ""; }; - E200433A892F1843DD9B8C05E3C226BE /* NSObject+MJCoding.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSObject+MJCoding.h"; path = "MJExtension/NSObject+MJCoding.h"; 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 = ""; }; E214C17CF404D45BDF92DD6C18D371FA /* Pods-keyBoard-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-keyBoard-acknowledgements.markdown"; sourceTree = ""; }; - E28F3972E6749440E493F6BCD8198F4F /* MJExtension-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "MJExtension-Info.plist"; sourceTree = ""; }; - E2EAE5E554B07101C740E6CB128A93A0 /* SDImageIOAnimatedCoder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageIOAnimatedCoder.m; path = SDWebImage/Core/SDImageIOAnimatedCoder.m; sourceTree = ""; }; - E310A44D757B0556FA6F2882D1565A8C /* NSString+MJExtension.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSString+MJExtension.m"; path = "MJExtension/NSString+MJExtension.m"; 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 = ""; }; E49D6D248DD1CEE584E6776B9164A1B2 /* MJRefresh */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = MJRefresh; path = MJRefresh.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - E553AE6B35449F8CB4BAA4FFE1DCAFAC /* MJRefreshComponent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshComponent.h; path = MJRefresh/Base/MJRefreshComponent.h; sourceTree = ""; }; - E5886305209187E582C024335BD55AE9 /* View+MASShorthandAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "View+MASShorthandAdditions.h"; path = "Masonry/View+MASShorthandAdditions.h"; sourceTree = ""; }; - E5AEFA07EBF944C0387D10A7BD7BC85F /* MASViewAttribute.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASViewAttribute.m; path = Masonry/MASViewAttribute.m; sourceTree = ""; }; - E7D9B8C39A19DDF2CE7619D44758B033 /* MJRefreshNormalHeader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshNormalHeader.m; path = MJRefresh/Custom/Header/MJRefreshNormalHeader.m; sourceTree = ""; }; - E8780E8A7822982224C2ACEBBC3B52B8 /* AFImageDownloader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFImageDownloader.h; path = "UIKit+AFNetworking/AFImageDownloader.h"; sourceTree = ""; }; - E97276CEE18BF4611E1C1D42736F6EAB /* SDMemoryCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDMemoryCache.h; path = SDWebImage/Core/SDMemoryCache.h; sourceTree = ""; }; - EA1E48B813787CAC28E89E7F260BFCD4 /* UIImage+MemoryCacheCost.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+MemoryCacheCost.m"; path = "SDWebImage/Core/UIImage+MemoryCacheCost.m"; sourceTree = ""; }; - EA46C1DE7820870BF842553EA6A951F9 /* UIImage+ForceDecode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+ForceDecode.h"; path = "SDWebImage/Core/UIImage+ForceDecode.h"; sourceTree = ""; }; - EAE5F401F42AA242D6CAE9E463DE5CD4 /* UIProgressView+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIProgressView+AFNetworking.h"; path = "UIKit+AFNetworking/UIProgressView+AFNetworking.h"; sourceTree = ""; }; - EAFBBF7E1270693113CDF0C1D9CBB512 /* MJRefreshFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshFooter.m; path = MJRefresh/Base/MJRefreshFooter.m; sourceTree = ""; }; - F0300A3A30BF1560E306C61ACCE11C1A /* UIButton+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIButton+AFNetworking.m"; path = "UIKit+AFNetworking/UIButton+AFNetworking.m"; sourceTree = ""; }; - F0C38163E5AA6D4BEAA1C7E79C82A930 /* SDAnimatedImageView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDAnimatedImageView.m; path = SDWebImage/Core/SDAnimatedImageView.m; sourceTree = ""; }; - F0CEEBB5DD628DB121172299787A25A9 /* SDImageCachesManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageCachesManager.m; path = SDWebImage/Core/SDImageCachesManager.m; sourceTree = ""; }; - F104350C0F7D19687DAC6BD75101DA7F /* SDWebImageDownloader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageDownloader.m; path = SDWebImage/Core/SDWebImageDownloader.m; sourceTree = ""; }; - F104F9FC5C4BB399EC2C2B96BD7714B8 /* SDWebImage-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "SDWebImage-Info.plist"; sourceTree = ""; }; - F37857D4A0467A12B54C180612695C52 /* AFNetworking-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "AFNetworking-prefix.pch"; sourceTree = ""; }; - F4E10DADB58D42AEAD6CD268CEB583E8 /* MJRefreshGifHeader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshGifHeader.h; path = MJRefresh/Custom/Header/MJRefreshGifHeader.h; sourceTree = ""; }; - F62E78180455B791A034CFBD4F4CE6A3 /* SDImageCoderHelper.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageCoderHelper.m; path = SDWebImage/Core/SDImageCoderHelper.m; sourceTree = ""; }; - F68941BD4F4913D60B00D4A8F049112A /* UIImage+MultiFormat.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+MultiFormat.m"; path = "SDWebImage/Core/UIImage+MultiFormat.m"; sourceTree = ""; }; - F74EE2D92793519D84E4B72CD6AB0C63 /* MJRefreshHeader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshHeader.m; path = MJRefresh/Base/MJRefreshHeader.m; sourceTree = ""; }; - F76369243ECD96D54BBB9C4A97EB6946 /* NSImage+Compatibility.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSImage+Compatibility.h"; path = "SDWebImage/Core/NSImage+Compatibility.h"; sourceTree = ""; }; - F7A20DE3DDDA450D1997F9A3184CD3C6 /* SDImageAssetManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageAssetManager.h; path = SDWebImage/Private/SDImageAssetManager.h; sourceTree = ""; }; - F7E0DB23007E49794165F74548446C13 /* SDWebImageCacheKeyFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageCacheKeyFilter.m; path = SDWebImage/Core/SDWebImageCacheKeyFilter.m; sourceTree = ""; }; - F934ACD20FEDAB980427B3D001DF8312 /* NSArray+MASAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSArray+MASAdditions.m"; path = "Masonry/NSArray+MASAdditions.m"; sourceTree = ""; }; - F9CEF650A6E8658ECF7704A7EE2E7452 /* MASConstraintMaker.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASConstraintMaker.h; path = Masonry/MASConstraintMaker.h; sourceTree = ""; }; - FB47049112F4F8EEA8F6068CB0393B3F /* SDAnimatedImageRep.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDAnimatedImageRep.h; path = SDWebImage/Core/SDAnimatedImageRep.h; sourceTree = ""; }; - FB792580573132155A61C027392EF360 /* MJExtension-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "MJExtension-dummy.m"; sourceTree = ""; }; - FB988F307C9B24539A026F84144A0402 /* MJRefreshComponent.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshComponent.m; path = MJRefresh/Base/MJRefreshComponent.m; sourceTree = ""; }; - FF09658FCA5560C3552AF5B4B7E7C6ED /* SDImageIOCoder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageIOCoder.h; path = SDWebImage/Core/SDImageIOCoder.h; sourceTree = ""; }; - FF49D60AE2D0E7C2857D88C5353083C3 /* SDAsyncBlockOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDAsyncBlockOperation.m; path = SDWebImage/Private/SDAsyncBlockOperation.m; sourceTree = ""; }; + 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 = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 0DDBBB716811E63091A5A45D29A5FEFA /* Frameworks */ = { + 0DE7FCDD6C04EC4E1E9ECB00A0604FB7 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 08DF3A0323B44ABF3FAAE0F291F8566E /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -774,10 +1146,11 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 2195E2C2C2334091D023B7EB98B24603 /* Frameworks */ = { + 1DB2A65061CA7DD5960E33B499AD1F7B /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + C828F9FE16619B2D51C4F3E40185DE85 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -798,18 +1171,19 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 5F8D0AA57E07244D2E43526654F67443 /* Frameworks */ = { + 68405B5F41E04D755317E63849131904 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - 83DE9F788F7FEF1F8FBE5407651F444D /* Frameworks */ = { + 7CFE8F67F3A1361064414896BC73914A /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - DC87E6C5364DC59641BC8A0676B5EA55 /* Foundation.framework in Frameworks */, + 98AB6B8EB7FF096BCE87488C5AB3DF1C /* Foundation.framework in Frameworks */, + C71935C30C1AEDF32B96670BD8FA64CE /* UIKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -821,371 +1195,304 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - E62253CBB3499DA4547AF2A780EC3E2F /* Frameworks */ = { + A12778F5B92D79BB1CB466B6E7808C73 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; + CA6527CF424B1AA12AF1D0BB36EBAF73 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4A2D7878579537881DD3859B3359F702 /* CoreGraphics.framework in Frameworks */, + 723D1925C39764631641D0DBFDF6833B /* Foundation.framework in Frameworks */, + A1A1266FD70CEB545FD7602CC33F2F7B /* QuartzCore.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D04C3487CC66436E0AC1085019C1D36C /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 659D38386A3E09422812283BF27D71D1 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E672724427269716049B769344D7C3DC /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 15B27182B591769C57B55544260DC886 /* Foundation.framework in Frameworks */, + D968461E31E8FF3FF6BA1DC621B0433B /* UIKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 016CE3C0DE69FA6E7375F8B485359AE7 /* Support Files */ = { + 004BCCE6E90EA8F999F5DD21EFC4736A /* Support Files */ = { isa = PBXGroup; children = ( - DEAC3EFF66D7CCDC2824B18A44FDBB3B /* MJRefresh.modulemap */, - C71B36DE1531E30C6C8E2592C55C0ED5 /* MJRefresh-dummy.m */, - D0275B47D80FC8AE3A59DFAEA8C65E1C /* MJRefresh-Info.plist */, - 72789BA685A26A276A98609F54509572 /* MJRefresh-prefix.pch */, - AECAC2F59ABD4A78D2B73C898E485890 /* MJRefresh-umbrella.h */, - 74CC813EBCFDBA413D1E8F2AE302E41A /* MJRefresh.debug.xcconfig */, - DF80C56AF1D41887B8622FAC95138810 /* MJRefresh.release.xcconfig */, - 852C84F2242375BE5446ADE5B9509933 /* ResourceBundle-MJRefresh.Privacy-MJRefresh-Info.plist */, + 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 */, ); name = "Support Files"; - path = "../Target Support Files/MJRefresh"; + path = "../Target Support Files/Masonry"; sourceTree = ""; }; - 03C5C200A0787E300053CFA8F53CA094 /* Frameworks */ = { + 055E201C6FE65C14750CE007D95094C3 /* DZNEmptyDataSet */ = { isa = PBXGroup; children = ( - 2859475DD957B3C624425C23759DE609 /* iOS */, + D6E369F88941EA9A46AF58BC88CC0720 /* UIScrollView+EmptyDataSet.h */, + 1C3AD08A39781246EBAC23F5B8A9BDD3 /* UIScrollView+EmptyDataSet.m */, + 6CE3F18721CC834AA1D80F2A9F218CA5 /* Support Files */, ); - name = Frameworks; + name = DZNEmptyDataSet; + path = DZNEmptyDataSet; sourceTree = ""; }; - 18AF1EE6F6DA0C51E0452AA62EF8B8ED /* Masonry */ = { + 139D61AB9CCEA3CD3FE43AE8F0DFA14F /* Support Files */ = { isa = PBXGroup; children = ( - 104166B53DA0CBE95AF12518EB609B7A /* MASCompositeConstraint.h */, - 0F7E589343BFFDCABC0FCDF6E321CDA2 /* MASCompositeConstraint.m */, - 71C9A7FB9BC0D7C0FA902D0643B08962 /* MASConstraint.h */, - 7C1791A7C256B13C227BF8DAE4C2EFE9 /* MASConstraint.m */, - 5AC074355067D4E88EB993DD28E44948 /* MASConstraint+Private.h */, - F9CEF650A6E8658ECF7704A7EE2E7452 /* MASConstraintMaker.h */, - 8ABF0BFFB097FE97D207EBE5498289D3 /* MASConstraintMaker.m */, - 52AD4C798F619843C6425BB666EE43A0 /* MASLayoutConstraint.h */, - 047628989EB45DFAC6DD4B6DDC61C1D7 /* MASLayoutConstraint.m */, - 23D13EEFDD6A912D7922FE8AE4E23D60 /* Masonry.h */, - 3F58F61640AAFD16139A83CC4EA55B1D /* MASUtilities.h */, - 2CCE60F6B1B48663415E0A4BC9662B33 /* MASViewAttribute.h */, - E5AEFA07EBF944C0387D10A7BD7BC85F /* MASViewAttribute.m */, - 266F6A7CA0ABF9B26D746459A14BAEBA /* MASViewConstraint.h */, - D28BB6B7AF2BC47AA045CB28AE578B56 /* MASViewConstraint.m */, - 93EB15003C1E2452E5C21AD7FF38A39D /* NSArray+MASAdditions.h */, - F934ACD20FEDAB980427B3D001DF8312 /* NSArray+MASAdditions.m */, - 1DA8FCC29DBFD3824ADEAD9F14A76E86 /* NSArray+MASShorthandAdditions.h */, - 5679D7FEFDE3E519C17C0EAAA7867122 /* NSLayoutConstraint+MASDebugAdditions.h */, - DE966A3AAABAC126A570DC36F74E07AE /* NSLayoutConstraint+MASDebugAdditions.m */, - 88799C33D6D0AAE2D395A1496F3A9E5D /* View+MASAdditions.h */, - E135DFBB6A830F84DCF4A1D31534EE65 /* View+MASAdditions.m */, - E5886305209187E582C024335BD55AE9 /* View+MASShorthandAdditions.h */, - 6EB624EDC7B2F6F92D5F6AEF8AAA4356 /* ViewController+MASAdditions.h */, - 33EBB93597383ED9EEA18C0A9BCE3B84 /* ViewController+MASAdditions.m */, - B9D225EE05CF747670C5F4383D1D8D95 /* Support Files */, + 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 */, ); - name = Masonry; - path = Masonry; + name = "Support Files"; + path = "../Target Support Files/SDWebImage"; sourceTree = ""; }; - 19D8D3FE289D2B2C36E0B1D672C942C8 /* Reachability */ = { + 1C8A19406FF58E9BA6BC427CA02E9857 /* Products */ = { isa = PBXGroup; children = ( - 523BDC065F0AF63F170A84FAF905FD26 /* AFNetworkReachabilityManager.h */, - B7BBB3446628A3BC637B9F57A5C49901 /* AFNetworkReachabilityManager.m */, + 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 */, ); - name = Reachability; + name = Products; sourceTree = ""; }; - 1B700D6AB864A19F1C70168CC9BAAEC5 /* Serialization */ = { + 1DF4B2EDEE04858C6D572415F9FFA5F7 /* Core */ = { isa = PBXGroup; children = ( - 5DD19473CA2658646B964B6124A31FB9 /* AFURLRequestSerialization.h */, - 74446596F2A689B17D9187482A194EEC /* AFURLRequestSerialization.m */, - 517973DC2D89829B73698FF20240431A /* AFURLResponseSerialization.h */, - CEC061A3621F113DA97A66F89E6A844B /* AFURLResponseSerialization.m */, - ); - name = Serialization; - sourceTree = ""; - }; - 1F956714C6A7CF7B7999AEB4E29D418F /* MJExtension */ = { - isa = PBXGroup; - children = ( - 569FA95248CF0B824C3928196386FFC2 /* MJExtension.h */, - 2D68500D4C2F7DB8B114E62F888BDD85 /* MJExtensionConst.h */, - 31F5F018A672BC56D29258EEBC019C32 /* MJExtensionConst.m */, - 0AFFFE7105483F8A94BFD883AD56221D /* MJFoundation.h */, - 4830CF5BA96EF2AA3AC7496D62A49A0D /* MJFoundation.m */, - 7D8FF130378AA0390E3754AB93673319 /* MJProperty.h */, - 87A1195922F05E5D23FF9A3C4509A854 /* MJProperty.m */, - 250848691A5C0FC662F372FB71E83AE5 /* MJPropertyKey.h */, - 12CCB648397BE0600012171A844509DE /* MJPropertyKey.m */, - 950F7A4DEA1A2D31E4A650C9526788F7 /* MJPropertyType.h */, - 7842E350E0D12563DE7C0EB363356BF8 /* MJPropertyType.m */, - 25ABF76DAF311B44A4F41DD3F9F04644 /* NSObject+MJClass.h */, - 5A50D4A4631B759E5D73FDFF78C8BF75 /* NSObject+MJClass.m */, - E200433A892F1843DD9B8C05E3C226BE /* NSObject+MJCoding.h */, - 9D403D54754F62E7ECBA2668B217E5FD /* NSObject+MJCoding.m */, - D915858ABB2794C80C0D2328483F75C4 /* NSObject+MJKeyValue.h */, - C23DF793769699E27A02E0B30615EF6F /* NSObject+MJKeyValue.m */, - 0C8185E7D34531047F63FFFBB2C6C9D3 /* NSObject+MJProperty.h */, - 4AFCF05D160C4A925AEC624ED1CD826F /* NSObject+MJProperty.m */, - 0A6C15EE27B77ABD56B0A0807D581260 /* NSString+MJExtension.h */, - E310A44D757B0556FA6F2882D1565A8C /* NSString+MJExtension.m */, - C006D91CB7EF7E3CDD3E746411DCC861 /* Resources */, - 93847A1A2F274DFFE13AFE589395B53B /* Support Files */, - ); - name = MJExtension; - path = MJExtension; - sourceTree = ""; - }; - 2859475DD957B3C624425C23759DE609 /* iOS */ = { - isa = PBXGroup; - children = ( - 18BF12DFF6188AFC43E6F26853B048F9 /* Foundation.framework */, - DDAE741F085915AF2475C918F1A17466 /* ImageIO.framework */, - 5BA0325112AB8CA7AB613D1A8ED2DB65 /* UIKit.framework */, - ); - name = iOS; - sourceTree = ""; - }; - 2FC4867627CDCD8FC332BB686C62FDE4 /* Core */ = { - isa = PBXGroup; - children = ( - 7A46DCA8F7BDEE6453116CAF6CBBAC40 /* NSBezierPath+SDRoundedCorners.h */, - B147B49E855B11A35493E26865607BDF /* NSBezierPath+SDRoundedCorners.m */, - 11F1BA773620708277D240BE4CD304E4 /* NSButton+WebCache.h */, - 008AD8F77F87E2DC5C0DB4CD71AC5858 /* NSButton+WebCache.m */, - DDC08D9E69C76309DA07F96C62824633 /* NSData+ImageContentType.h */, - 90687AA744E720C17FD8600B60F43FF5 /* NSData+ImageContentType.m */, - F76369243ECD96D54BBB9C4A97EB6946 /* NSImage+Compatibility.h */, - 9C040DD9465E298ACD105143A3265009 /* NSImage+Compatibility.m */, - 2CCDC185ACCEFD6ACB87234F081FC1A1 /* SDAnimatedImage.h */, - DC6CF0A46A4D9FFFBA2057678DF1978B /* SDAnimatedImage.m */, - 81D5F6E26D64BB94294CEC208FAEEBE2 /* SDAnimatedImagePlayer.h */, - B20A669086F5506692603D3336437ABD /* SDAnimatedImagePlayer.m */, - FB47049112F4F8EEA8F6068CB0393B3F /* SDAnimatedImageRep.h */, - 9954286F43C39384A1EADABA9AAE0B0D /* SDAnimatedImageRep.m */, - 8AACAEAAD31005B66599055215ADA658 /* SDAnimatedImageView.h */, - F0C38163E5AA6D4BEAA1C7E79C82A930 /* SDAnimatedImageView.m */, - 371EEAE238A16CCB71633D3E6EF40F2B /* SDAnimatedImageView+WebCache.h */, - 0C6DD7AD3672258C4407B4269B490F27 /* SDAnimatedImageView+WebCache.m */, - 34E2AA501576A0C5221012B9066EC56A /* SDAssociatedObject.h */, - 0C838D64A8654D1DDA15A6DDC98360A9 /* SDAssociatedObject.m */, - 42134A400043398C196C2BDF73B21075 /* SDAsyncBlockOperation.h */, - FF49D60AE2D0E7C2857D88C5353083C3 /* SDAsyncBlockOperation.m */, - 678A010D7D73785C1E08D97B5F67AAAA /* SDCallbackQueue.h */, - AF26D1DF8BE4D63027161EEBE6FDE7AE /* SDCallbackQueue.m */, - AC2514CF7A7B043E035CFB079E6FB5A0 /* SDDeviceHelper.h */, - 4090C24D16A324EB9D2A6747886BD217 /* SDDeviceHelper.m */, - 6DFD30C63C15966EA8BF3CAD55EB97F8 /* SDDiskCache.h */, - A113F5BE027C0A2BC1CC3F420069F969 /* SDDiskCache.m */, - 078FC3682AC6F2B8020DD6D0F6A1A818 /* SDDisplayLink.h */, - 48E4A519DF8188F67D6109DB1AF82FF9 /* SDDisplayLink.m */, - D13BE3E84BFB9462CF54B22B35F89ADC /* SDFileAttributeHelper.h */, - DBFD2ECA52ECDAAA78246FE8B02312A9 /* SDFileAttributeHelper.m */, - 5FD6594A1D1613C90FF5EF2CBD5CE123 /* SDGraphicsImageRenderer.h */, - 661BCD3C752D21E81C83DA14D3C4502A /* SDGraphicsImageRenderer.m */, - 7C38C5957F4EAC459AB28A71622C865C /* SDImageAPNGCoder.h */, - BF154B0F2EB8913A8674795FD63311D2 /* SDImageAPNGCoder.m */, - F7A20DE3DDDA450D1997F9A3184CD3C6 /* SDImageAssetManager.h */, - 19F5C3BFE7C9E2977EB241266B257ABE /* SDImageAssetManager.m */, - 7315702A1F332F57A8765F720EE5B18F /* SDImageAWebPCoder.h */, - DFD5A14F9DC74814903A901B625C5A94 /* SDImageAWebPCoder.m */, - 93D1581B25C7E0154AE410EBB56CE516 /* SDImageCache.h */, - 8332CB32D0FA2CE8D910AA5A9BE18D8B /* SDImageCache.m */, - 19E0C6994863739B688E61DCE0E025C3 /* SDImageCacheConfig.h */, - C5D645FDA53D7713D436C992B2BC3E96 /* SDImageCacheConfig.m */, - 97F65BC08A412ED6706647722A834532 /* SDImageCacheDefine.h */, - 9AF4B903EB65570DDDE8731659809CA1 /* SDImageCacheDefine.m */, - 0ACA8E457A64FBC07F850B4E390020D4 /* SDImageCachesManager.h */, - F0CEEBB5DD628DB121172299787A25A9 /* SDImageCachesManager.m */, - 9DBD448EB576D346FBA1D20A1BD13F1D /* SDImageCachesManagerOperation.h */, - 305FF55ADA3393924EFC2D4B6D38166D /* SDImageCachesManagerOperation.m */, - B3A54C7306CBDB1BC3189CCF492C92DE /* SDImageCoder.h */, - 01F1EC51FF11D8BE91D0807E9CB714CC /* SDImageCoder.m */, - 176CBDEEAB52421C3AA5CB3917B54885 /* SDImageCoderHelper.h */, - F62E78180455B791A034CFBD4F4CE6A3 /* SDImageCoderHelper.m */, - DBEED872AB83B013F34A14A1823F4820 /* SDImageCodersManager.h */, - C3EC2E3BBB3895884BB4AA3B74A54476 /* SDImageCodersManager.m */, - AB8EC26A51378B3F4C5559E371607480 /* SDImageFrame.h */, - 9B7D77CB378449CF4A7041A3EA89C102 /* SDImageFrame.m */, - 12C162655386843E5BE2582AC09CA762 /* SDImageFramePool.h */, - BF3675A98BB80F2630D08AB3BE31E1B7 /* SDImageFramePool.m */, - B60142D76441D9D2B7BA4991E7523577 /* SDImageGIFCoder.h */, - 42FE2C6A18379D9944FBBA606FB88133 /* SDImageGIFCoder.m */, - 34CEE2DA708B82493E132F274E2E9493 /* SDImageGraphics.h */, - 830D06A83C1E8E77E539514107F83812 /* SDImageGraphics.m */, - 8430A616C01FADC1B0DB9E5D08A03C35 /* SDImageHEICCoder.h */, - 20B21087EF80825B8FC789A191A95BAA /* SDImageHEICCoder.m */, - 13F0EE17165FE326BF8D348C181A1E71 /* SDImageIOAnimatedCoder.h */, - E2EAE5E554B07101C740E6CB128A93A0 /* SDImageIOAnimatedCoder.m */, - 0CB3E312C9D65596A37072C76944B850 /* SDImageIOAnimatedCoderInternal.h */, - FF09658FCA5560C3552AF5B4B7E7C6ED /* SDImageIOCoder.h */, - 21EE020A32A9ADF76D7C1AF1A9B28D63 /* SDImageIOCoder.m */, - 50DC89AF710F42BFF3D4C048EFAC8BB7 /* SDImageLoader.h */, - 7869EB02C0774141B550180F17DBF9F0 /* SDImageLoader.m */, - 80E9D6278C5650A6AD05F331651F6DEB /* SDImageLoadersManager.h */, - A1ECACF57484B51D17735566ED038104 /* SDImageLoadersManager.m */, - 2C0A8B13D619D89C3E57F4B83ACBF157 /* SDImageTransformer.h */, - 6E7A746456C4F5E2C887572055F6A833 /* SDImageTransformer.m */, - A294AA5EAB4FD3CAF8C4A072117591C1 /* SDInternalMacros.h */, - 06A2AED69705719F9BEBAEDC9D1D18C6 /* SDInternalMacros.m */, - E97276CEE18BF4611E1C1D42736F6EAB /* SDMemoryCache.h */, - A6CCAA7B0AD1373217438DACF7AB456C /* SDMemoryCache.m */, - 61B4061AC178FEE58C9618133524CF08 /* SDmetamacros.h */, - 1F0E8534D3C055E4D5D27EBF7422DA74 /* SDWeakProxy.h */, - 93A3B9C517383784D38DA222632F5FFB /* SDWeakProxy.m */, - 67DDCFED9CF39A1F995D9E7B12E35A7E /* SDWebImage.h */, - 9802609AB0266E444A1BD29FA119D9BC /* SDWebImageCacheKeyFilter.h */, - F7E0DB23007E49794165F74548446C13 /* SDWebImageCacheKeyFilter.m */, - 4A71363040CF6A8E6D918CEF79A555D5 /* SDWebImageCacheSerializer.h */, - 6C4CAA32BF7068345545D717BAAF7069 /* SDWebImageCacheSerializer.m */, - 7B6867FF0B2276E04032D8E5C44B4EB9 /* SDWebImageCompat.h */, - 7980625AB48FABAF33EDB825FF587011 /* SDWebImageCompat.m */, - 19C379703ED728112C6AD8D69CB97193 /* SDWebImageDefine.h */, - 6DE36A434A8BD3593CCBD95090373332 /* SDWebImageDefine.m */, - 00031196DD7FBA552243DCF5CEB19ABD /* SDWebImageDownloader.h */, - F104350C0F7D19687DAC6BD75101DA7F /* SDWebImageDownloader.m */, - 8A926EA8E3863425810DDC585C464587 /* SDWebImageDownloaderConfig.h */, - 1E8EE46DFF5945CB5FDB220509F5E1A0 /* SDWebImageDownloaderConfig.m */, - 29834704EC1453F0ACBDF5CAA435E7B0 /* SDWebImageDownloaderDecryptor.h */, - 1C27DC7D5FFFA31A8EA1C7B95F3079E1 /* SDWebImageDownloaderDecryptor.m */, - A1D6DA8B66269F171ED8918C664075F4 /* SDWebImageDownloaderOperation.h */, - 825CA08D9974B4E876CAFA68A0F53F93 /* SDWebImageDownloaderOperation.m */, - 969BDA148FEBCD19E1B7701E7F70E539 /* SDWebImageDownloaderRequestModifier.h */, - 06B71FC03BF92D5C7E3E050752C0E06C /* SDWebImageDownloaderRequestModifier.m */, - D99D7FCB3FD62B8D8BF11087E1D6E47F /* SDWebImageDownloaderResponseModifier.h */, - 4F51691B6717B6D9E4E3FE0977CF3163 /* SDWebImageDownloaderResponseModifier.m */, - 646B483EDAD1F8B7F96981EB5E185F2E /* SDWebImageError.h */, - B509365346F676352BBC6630F5F1FADB /* SDWebImageError.m */, - D0B1FCAC31B9EF58F1FD85B83EA55B1C /* SDWebImageIndicator.h */, - 0FC44A2AEE9BAA02332A14994FF0E2E0 /* SDWebImageIndicator.m */, - 02379CD5F0D938EE2DBABC8871CB17E5 /* SDWebImageManager.h */, - 09C03827CE30DECF1B8884688B6651D8 /* SDWebImageManager.m */, - 33152C1C1E9FE19D1E9C8D8BF0C963DA /* SDWebImageOperation.h */, - 76F97ACAD92849B1F665FD0FF282B3C8 /* SDWebImageOperation.m */, - B9DF6B027952E0BE3781007ECC6436E7 /* SDWebImageOptionsProcessor.h */, - ADF1D8C19CC2D66E65B4B1746316FFC5 /* SDWebImageOptionsProcessor.m */, - 0DC8E0CC70A7B84D1A1E1FAAF5AF5A4D /* SDWebImagePrefetcher.h */, - 916FC91BADACF2A6F0FF12F1385FC1D4 /* SDWebImagePrefetcher.m */, - 575E3DAA2F5DDC8FBD895B8BEA5FB8C6 /* SDWebImageTransition.h */, - A11030FED687E26E2A7953D880C8DDD7 /* SDWebImageTransition.m */, - 755B7205B482C6B79DEAE02978E7FD20 /* SDWebImageTransitionInternal.h */, - 9E2F76F628A20AA296860E039C6A51DE /* UIButton+WebCache.h */, - 4638EBD469283AF4DC5CBD3CE927D254 /* UIButton+WebCache.m */, - 851329DB564FCDDAD9A52952F487E28D /* UIColor+SDHexString.h */, - 10E420AEEA134E4CDDBAA68DEA103561 /* UIColor+SDHexString.m */, - 377FB4D51134D774594E6EAF0BB4DFAA /* UIImage+ExtendedCacheData.h */, - 8FC489301C2534B7DD53B90720E80BF3 /* UIImage+ExtendedCacheData.m */, - EA46C1DE7820870BF842553EA6A951F9 /* UIImage+ForceDecode.h */, - 840FE4FBC8DFDB4B1238B06FEA5AF259 /* UIImage+ForceDecode.m */, - 429C09B93893D24656048D336CE95D59 /* UIImage+GIF.h */, - 24F6DCD61BBDE3823CE167416B3799D1 /* UIImage+GIF.m */, - 4797723C6D7C918B816F46FCFB028F6F /* UIImage+MemoryCacheCost.h */, - EA1E48B813787CAC28E89E7F260BFCD4 /* UIImage+MemoryCacheCost.m */, - 03DE7669ACCB33ED7598791177D4881A /* UIImage+Metadata.h */, - 46F91B0801CEBD1D73003708566CC913 /* UIImage+Metadata.m */, - 897B6BFD5EA50E7440FD4FA3769B3C78 /* UIImage+MultiFormat.h */, - F68941BD4F4913D60B00D4A8F049112A /* UIImage+MultiFormat.m */, - AF6FBF6EC0693B752A91650764E380C8 /* UIImage+Transform.h */, - 14C4334FE2177757C132CBBCD17C11B5 /* UIImage+Transform.m */, - 982D370CD4E116E0C1917E832541C530 /* UIImageView+HighlightedWebCache.h */, - 56347C360CEDAA8246A01A213DEBBF8B /* UIImageView+HighlightedWebCache.m */, - 23078E14E88B14332A0B4BE57A2A9488 /* UIImageView+WebCache.h */, - C6C465F665338FA163A2F6623C933047 /* UIImageView+WebCache.m */, - A87E9EA0B6E9AB8C1E29A3AE50F278CB /* UIView+WebCache.h */, - 7D3CFDF279C9B9946089A89EFB72A50D /* UIView+WebCache.m */, - AED6E178EFE04C18394DE24CF7E24E01 /* UIView+WebCacheOperation.h */, - 3D5935FEEF657D48BF93BE04A41CF816 /* UIView+WebCacheOperation.m */, - DC6DB03243923516662807D789FF26B1 /* UIView+WebCacheState.h */, - 197BBC12418F4C1E7719181019D1E9EA /* UIView+WebCacheState.m */, - 96966FAF94AEBEB4718998C79115AD0F /* Resources */, + 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 */, ); name = Core; sourceTree = ""; }; - 3128165374A2707E315E77D530A52B15 /* MJRefresh */ = { + 278BA3F4B18D03DAFFA7B31C7D8082C1 /* NSURLSession */ = { isa = PBXGroup; children = ( - 2D2A2C7E78B1029B85E812A9CC5D4F58 /* MJRefresh.h */, - 7D4327E5DC3980134C42B829E8798AA4 /* MJRefreshAutoFooter.h */, - 568638C925360332377ACFB503131A76 /* MJRefreshAutoFooter.m */, - 1D9CC7A1A5CD78BA5BDFC0C1D94B2D4D /* MJRefreshAutoGifFooter.h */, - 2514349975FAC97A668A1C6665BD754F /* MJRefreshAutoGifFooter.m */, - 0073EB182F9CC003B9721B132AC0082F /* MJRefreshAutoNormalFooter.h */, - 7E6DD5C54D7EC67B674C64E88446BAA7 /* MJRefreshAutoNormalFooter.m */, - 3526591F674CF19FB39EF872089A7F49 /* MJRefreshAutoStateFooter.h */, - CCDB436E5F20F839485E728CEF386187 /* MJRefreshAutoStateFooter.m */, - 3126B87E909122AFEE37CA26F800E7D9 /* MJRefreshBackFooter.h */, - 19839A21E0B314D9E8C99EBD5D071916 /* MJRefreshBackFooter.m */, - 29AFC65F883E204F73DDE040C829BC77 /* MJRefreshBackGifFooter.h */, - 32EACA7B3E95EF3C511EEAED34B5C23A /* MJRefreshBackGifFooter.m */, - 087882A7DEA5E7EECA5B73EB89E95C00 /* MJRefreshBackNormalFooter.h */, - 14C952AD321D89B78D085CA0FBC817D9 /* MJRefreshBackNormalFooter.m */, - 1F8526067D06A009E96461455DBA1B40 /* MJRefreshBackStateFooter.h */, - 71B30FE27ADA94703A3F06804277A5C0 /* MJRefreshBackStateFooter.m */, - E553AE6B35449F8CB4BAA4FFE1DCAFAC /* MJRefreshComponent.h */, - FB988F307C9B24539A026F84144A0402 /* MJRefreshComponent.m */, - BEC2871B1357A63D88FCC0144C7847CD /* MJRefreshConfig.h */, - 2EFA72948DE45F4B6CAD9DA5C625D259 /* MJRefreshConfig.m */, - BE6C3AB94897685F9464AA252C4EFB17 /* MJRefreshConst.h */, - 8BECBF70665658E16C4E9DDD74C7161A /* MJRefreshConst.m */, - 53392BC7B7115E12AC2077F4447BF455 /* MJRefreshFooter.h */, - EAFBBF7E1270693113CDF0C1D9CBB512 /* MJRefreshFooter.m */, - F4E10DADB58D42AEAD6CD268CEB583E8 /* MJRefreshGifHeader.h */, - 275A2D66E7913A4B508816E187F4D3C3 /* MJRefreshGifHeader.m */, - 724FB5172055CF20AE6E6F4D007D8038 /* MJRefreshHeader.h */, - F74EE2D92793519D84E4B72CD6AB0C63 /* MJRefreshHeader.m */, - 5713367A1E361064DE338AB389631FF5 /* MJRefreshNormalHeader.h */, - E7D9B8C39A19DDF2CE7619D44758B033 /* MJRefreshNormalHeader.m */, - 73D1ED74B2085AA85B8213943DE4AD83 /* MJRefreshNormalTrailer.h */, - 8E7292A83C005323B245A7EF2737878F /* MJRefreshNormalTrailer.m */, - A20073D67775A184A6AEF2667BC7628C /* MJRefreshStateHeader.h */, - D513B9FE4981B810C5EBD34AAD6D0CD7 /* MJRefreshStateHeader.m */, - 036A5C31DE156FE1001CC60EF1E3E122 /* MJRefreshStateTrailer.h */, - 34B9AAE9B2C02781F4AC71AEDB56A439 /* MJRefreshStateTrailer.m */, - B6011963612818816E2CF40CED8B0112 /* MJRefreshTrailer.h */, - B1CE88DD0007C23B107D2BD3A6AB545B /* MJRefreshTrailer.m */, - 2E459098B6FF83AA9172F97696B64090 /* NSBundle+MJRefresh.h */, - 37DCC80FE271D2095A398F8D8F22C7E7 /* NSBundle+MJRefresh.m */, - 24B89B49F862DFF8218AA2D11CEDFD3E /* UICollectionViewLayout+MJRefresh.h */, - BCC0677B77FA6DFFDE007551F1660B1E /* UICollectionViewLayout+MJRefresh.m */, - C55407E10212267DCB2FC49D3260EF48 /* UIScrollView+MJExtension.h */, - 3B4BB6924504E595528A838685E1B608 /* UIScrollView+MJExtension.m */, - 4C64CBB1952BF537420E489E4AF7DED5 /* UIScrollView+MJRefresh.h */, - 8AF059A8B1C2B3EE76BCDE329D0C926E /* UIScrollView+MJRefresh.m */, - 35F55EE8682F170A101CA85DD55D1B58 /* UIView+MJExtension.h */, - 06B650CAE141ABD90E360415151BC9B9 /* UIView+MJExtension.m */, - 33D98C7E27F657F30141071B1B662940 /* Resources */, - 016CE3C0DE69FA6E7375F8B485359AE7 /* Support Files */, - ); - name = MJRefresh; - path = MJRefresh; - sourceTree = ""; - }; - 33D98C7E27F657F30141071B1B662940 /* Resources */ = { - isa = PBXGroup; - children = ( - 5FDFD2C717749B65FE64DACB99DF72A3 /* MJRefresh.bundle */, - 94F556719E0728E491D5BDF953E9A668 /* PrivacyInfo.xcprivacy */, - ); - name = Resources; - sourceTree = ""; - }; - 347AB39793E933B72AA519D8A60C8AFD /* NSURLSession */ = { - isa = PBXGroup; - children = ( - 2B8247E0ADA45F5408F3DE8313900894 /* AFCompatibilityMacros.h */, - 1C60E3EC4F7CE664E3A6586ED2AC0ED5 /* AFHTTPSessionManager.h */, - 8C0AB8960CBA6D24923E096B9378691C /* AFHTTPSessionManager.m */, - A95F96D9DAA700949C3A302C92FD9231 /* AFURLSessionManager.h */, - 7506ED7F0118C1C5FE230328CCC6543E /* AFURLSessionManager.m */, + E5F4E4918198D7216ABDC0BE4C9BFCE9 /* AFCompatibilityMacros.h */, + 8A3DF7C8B0CA95D284475EF487EC6944 /* AFHTTPSessionManager.h */, + 8CABC6887E9E2AF4A62642A0C780B4B3 /* AFHTTPSessionManager.m */, + 35618C07738616EC64E35AB9084E01C6 /* AFURLSessionManager.h */, + A6A924083322C61BD2DC82A438F46687 /* AFURLSessionManager.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; + sourceTree = ""; + }; 4098ED899C8DF8E013F9F260ECFAA236 /* Pods-keyBoard */ = { isa = PBXGroup; children = ( @@ -1203,6 +1510,15 @@ 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 = ( @@ -1219,211 +1535,363 @@ path = "Target Support Files/Pods-CustomKeyboard"; sourceTree = ""; }; - 502B3DC21E7D9121A0C4B98D3286C994 /* Bugly */ = { + 482C57567033D15CB5B58A3A51D16047 /* LookinServer */ = { isa = PBXGroup; children = ( - 88D3451B2C2D8161F934A9C946E320E9 /* Frameworks */, - E09502DD4B1D7ABBB4407C6ED07C0666 /* Support Files */, + FB435B3C1ABA904B9D4AEBB59855C935 /* Core */, + 73B1383B55A4637636F1D1641B1B4B2C /* Support Files */, + ); + name = LookinServer; + path = LookinServer; + sourceTree = ""; + }; + 49A74F626BD81F04B89DC8F68C0C8423 /* Masonry */ = { + 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 */, + ); + name = Masonry; + path = Masonry; + sourceTree = ""; + }; + 4DFD5EFE1D39A89202C706E005AEAC6C /* UIKit */ = { + 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 = ""; }; - 6365FA12681868274FAA98E6F51817F6 /* Support Files */ = { + 6CE3F18721CC834AA1D80F2A9F218CA5 /* Support Files */ = { isa = PBXGroup; children = ( - 7E72BDE0490314836A44AFEE2FD465C2 /* AFNetworking.modulemap */, - CC69297E62F679246B8FE5B49D774CF4 /* AFNetworking-dummy.m */, - 98E94877A92313B71CB6789264CC6752 /* AFNetworking-Info.plist */, - F37857D4A0467A12B54C180612695C52 /* AFNetworking-prefix.pch */, - 14D8DE9600B7E469FA4A83E84C149E08 /* AFNetworking-umbrella.h */, - 78744B8D1235EE30BFB429D8C13D63F4 /* AFNetworking.debug.xcconfig */, - 23D6F4D8D5B6512D7A50FF1054426C09 /* AFNetworking.release.xcconfig */, + 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/AFNetworking"; + path = "../Target Support Files/DZNEmptyDataSet"; sourceTree = ""; }; - 72657A79EE3B081E5F0D7C1166237E68 /* AFNetworking */ = { + 717E6458BD53164643C1A5869C11B538 /* iOS */ = { isa = PBXGroup; children = ( - BE440D8DEC29075E20FE83DB3AB2620D /* AFNetworking.h */, - 347AB39793E933B72AA519D8A60C8AFD /* NSURLSession */, - 19D8D3FE289D2B2C36E0B1D672C942C8 /* Reachability */, - D1B9DC187765592AAEEACCE698694E27 /* Security */, - 1B700D6AB864A19F1C70168CC9BAAEC5 /* Serialization */, - 6365FA12681868274FAA98E6F51817F6 /* Support Files */, - A63CD7E158D91CCE464486A00A29695D /* UIKit */, + 86A260983254EF2D214865E91D3787B2 /* CoreGraphics.framework */, + 3964617E5C241BE3E12D8F1D88607841 /* Foundation.framework */, + CFBDDF0554D720E199E1094AAEC3D171 /* ImageIO.framework */, + D673941813D9CA4EFFC6C32109054DC5 /* QuartzCore.framework */, + E1DF8BF780A4AD9606856AB857CA1D86 /* UIKit.framework */, ); - name = AFNetworking; - path = AFNetworking; + name = iOS; sourceTree = ""; }; - 72EAC702A61A19B6EC92D70B6CA9D4E8 /* Support Files */ = { + 73B1383B55A4637636F1D1641B1B4B2C /* Support Files */ = { isa = PBXGroup; children = ( - 2356B7A3F963324EEBA83CB0C527CC22 /* ResourceBundle-SDWebImage-SDWebImage-Info.plist */, - 38A043FDCD06C3C9914C9A22FB6B1D28 /* SDWebImage.modulemap */, - 34F1A2FD98EEB8019052FBD5528585C9 /* SDWebImage-dummy.m */, - F104F9FC5C4BB399EC2C2B96BD7714B8 /* SDWebImage-Info.plist */, - 801C19E603261CA9778C89D068D49697 /* SDWebImage-prefix.pch */, - 70330531B46EEB4398625F2AFC6683E5 /* SDWebImage-umbrella.h */, - 20B1DAD84F32D1AF296F0D63C5DEE9AB /* SDWebImage.debug.xcconfig */, - 25119C155F0BB240A5DDFB8155627C04 /* SDWebImage.release.xcconfig */, + 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/SDWebImage"; + path = "../Target Support Files/LookinServer"; sourceTree = ""; }; - 88D3451B2C2D8161F934A9C946E320E9 /* Frameworks */ = { + 85416DF4AE2111F696182FA844F2611A /* Support Files */ = { isa = PBXGroup; children = ( - 9784638759F544FA3CC67A7E0CA9454B /* Bugly.framework */, + 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 */, ); - name = Frameworks; + name = "Support Files"; + path = "../Target Support Files/MBProgressHUD"; sourceTree = ""; }; - 93847A1A2F274DFFE13AFE589395B53B /* Support Files */ = { + 8AB9F15B6060B4A24C4EA01AC9540849 /* Support Files */ = { isa = PBXGroup; children = ( - E0E66128C9FA5581B5257A03454E3761 /* MJExtension.modulemap */, - FB792580573132155A61C027392EF360 /* MJExtension-dummy.m */, - E28F3972E6749440E493F6BCD8198F4F /* MJExtension-Info.plist */, - B61705A318B7E4CE5BB4A9A618397777 /* MJExtension-prefix.pch */, - C5D0E76AC56695893DB1713CA7212B8C /* MJExtension-umbrella.h */, - 3316E3BF456739AB7A0F0FD1920F5F6B /* MJExtension.debug.xcconfig */, - 4B22EE0B7D2C1D1066750C4AB84FDA27 /* MJExtension.release.xcconfig */, - 1AFEE2DD6CE0A6302F3235AF172A2B77 /* ResourceBundle-MJExtension-MJExtension-Info.plist */, + 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 */, + ); + name = "Support Files"; + path = "../Target Support Files/MJRefresh"; + sourceTree = ""; + }; + 9F62E2D2D42206A4CD335DDB26C286FF /* Support Files */ = { + 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 */, ); name = "Support Files"; path = "../Target Support Files/MJExtension"; sourceTree = ""; }; - 96966FAF94AEBEB4718998C79115AD0F /* Resources */ = { + A369C1279A7423AC4561A1711312F059 /* MJRefresh */ = { isa = PBXGroup; children = ( - A9F5CF889820DAD55268C3832155A2E1 /* PrivacyInfo.xcprivacy */, + 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 */, ); - name = Resources; + name = MJRefresh; + path = MJRefresh; sourceTree = ""; }; - A63CD7E158D91CCE464486A00A29695D /* UIKit */ = { + A5DEA61008E4B3C548059441B307E57A /* Serialization */ = { isa = PBXGroup; children = ( - 246841FAF82F0BA847818A9594B81CCB /* AFAutoPurgingImageCache.h */, - 3FBCEF9827DD721BAF021C98F7311D30 /* AFAutoPurgingImageCache.m */, - E8780E8A7822982224C2ACEBBC3B52B8 /* AFImageDownloader.h */, - 61D0A0EB33F4B0A380D6DE9E8E5D56D7 /* AFImageDownloader.m */, - D875CFB5AA1591E80BD3A95A94255894 /* AFNetworkActivityIndicatorManager.h */, - 859BA7601F83844D2D2ABC395E386663 /* AFNetworkActivityIndicatorManager.m */, - 29DD9709CE876731037B630B8F1370DA /* UIActivityIndicatorView+AFNetworking.h */, - 4C41FE7B076060F0600FEC9D5AFF762A /* UIActivityIndicatorView+AFNetworking.m */, - 7AE552655E7E703CCEDD4BE44EFA5662 /* UIButton+AFNetworking.h */, - F0300A3A30BF1560E306C61ACCE11C1A /* UIButton+AFNetworking.m */, - AB321552F4E1B0F80966FCA9AF11848F /* UIImageView+AFNetworking.h */, - AF94F3E24B633799AB0B2B75B193A4F3 /* UIImageView+AFNetworking.m */, - 2008561C63F2B5CE8C1C38CF97F13753 /* UIKit+AFNetworking.h */, - EAE5F401F42AA242D6CAE9E463DE5CD4 /* UIProgressView+AFNetworking.h */, - 018B520CB407C3492F13C3767C15E377 /* UIProgressView+AFNetworking.m */, - 0044E51493E8CC5F8C46E1EC18F97722 /* UIRefreshControl+AFNetworking.h */, - B070DCCCA22D6ECC24DC0BD5CCEF5372 /* UIRefreshControl+AFNetworking.m */, - 9E3334C24AC0A37A21A6D9B9ECA94AB2 /* WKWebView+AFNetworking.h */, - 71A4B6E144674403F50435C67561B1BB /* WKWebView+AFNetworking.m */, + CA67A34B63E36E76FF453D2ABD613A39 /* AFURLRequestSerialization.h */, + 5C457050D64C2C7287BDFC768D33C9AE /* AFURLRequestSerialization.m */, + F3D6C729EB2C2561DF46F90B1EE029B4 /* AFURLResponseSerialization.h */, + 05D83C1EC3DD8D27EE1C07CFDE18D72E /* AFURLResponseSerialization.m */, ); - name = UIKit; + name = Serialization; sourceTree = ""; }; - AA7E5CA260B4C52744905877A30A95DD /* Products */ = { + A6678288D73D0E7B53AB75DF84AA65D4 /* Support Files */ = { isa = PBXGroup; children = ( - A4FA15D44DF6BAC7550EDEED10862AA3 /* AFNetworking */, - 1FFED36A657123030ABB700256D73F15 /* Masonry */, - 2B276B0A79173A1D6E83C9B4FB9A4A57 /* MJExtension */, - 43EAAD2AB7E6B407E80E95F643F93D22 /* MJExtension-MJExtension */, - E49D6D248DD1CEE584E6776B9164A1B2 /* MJRefresh */, - 7E3097CFEFDA621E9FB0E62009FF87FC /* MJRefresh-MJRefresh.Privacy */, - 0B4AAC15A428CDC2A62AF9CC27BEA609 /* Pods-CustomKeyboard */, - DCA062FD08AC9694D8D781B3492421C5 /* Pods-keyBoard */, - B0B214D775196BA7CA8E17E53048A493 /* SDWebImage */, - CF1281E58AA1045D4B7F33FC56691C42 /* SDWebImage-SDWebImage */, - ); - name = Products; - sourceTree = ""; - }; - B9D225EE05CF747670C5F4383D1D8D95 /* Support Files */ = { - isa = PBXGroup; - children = ( - 1170792DCF45BF664C43019D3E77D80F /* Masonry.modulemap */, - 5E8106411081DD6C7F5FE7804947412C /* Masonry-dummy.m */, - 9ADF16A9C4A54B7486F74B1F31DE3947 /* Masonry-Info.plist */, - 1C3E83B47A120437F73D41A878F182D1 /* Masonry-prefix.pch */, - 92D14A3D3FA826806436A8CFCBD915DA /* Masonry-umbrella.h */, - 4EF47C40D45E06BA89946B4C9F04A546 /* Masonry.debug.xcconfig */, - 396F4E7921EA26CDE8AAEADDD8CFBB49 /* Masonry.release.xcconfig */, + 18DB01964CBE026F2E6511875E1A98E2 /* Bugly.debug.xcconfig */, + 8C9727D0D56A9017D437CA50176F0474 /* Bugly.release.xcconfig */, ); name = "Support Files"; - path = "../Target Support Files/Masonry"; + path = "../Target Support Files/Bugly"; sourceTree = ""; }; - C006D91CB7EF7E3CDD3E746411DCC861 /* Resources */ = { + B94D7768568A9992200DB461E8CF687F /* Frameworks */ = { isa = PBXGroup; children = ( - 970B39752136D5831550118975DC4A91 /* PrivacyInfo.xcprivacy */, + 717E6458BD53164643C1A5869C11B538 /* iOS */, ); - name = Resources; + name = Frameworks; + sourceTree = ""; + }; + C5610FA28BEC5D4814F24C959B9C82BB /* SDWebImage */ = { + isa = PBXGroup; + children = ( + 1DF4B2EDEE04858C6D572415F9FFA5F7 /* Core */, + 139D61AB9CCEA3CD3FE43AE8F0DFA14F /* Support Files */, + ); + name = SDWebImage; + path = SDWebImage; sourceTree = ""; }; CF1408CF629C7361332E53B88F7BD30C = { isa = PBXGroup; children = ( 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */, - 03C5C200A0787E300053CFA8F53CA094 /* Frameworks */, - DCE595EEF85D396533FF4892F3008A92 /* Pods */, - AA7E5CA260B4C52744905877A30A95DD /* Products */, + B94D7768568A9992200DB461E8CF687F /* Frameworks */, + 3C8938BD791B748D62E0594E21A8F606 /* Pods */, + 1C8A19406FF58E9BA6BC427CA02E9857 /* Products */, F7ED90CD818DD0484BF7DB0E1E3B9AB2 /* Targets Support Files */, ); sourceTree = ""; }; - D1B9DC187765592AAEEACCE698694E27 /* Security */ = { + D98E67C1E6047B33AD3281F951D96C7F /* Resources */ = { isa = PBXGroup; children = ( - 85AD1C60C75A73E360E4320DD271A77D /* AFSecurityPolicy.h */, - 52AA08F30FFF4D9FF32F48E3AC195A6A /* AFSecurityPolicy.m */, + F320516E3A699EEF56C411E9C2DA9C29 /* PrivacyInfo.xcprivacy */, ); - name = Security; + name = Resources; sourceTree = ""; }; - D4CA9D10912142FCCA40F947B4FC5D1C /* SDWebImage */ = { + DB6A5FFB077AA72411EB46B8A77A31B0 /* Frameworks */ = { isa = PBXGroup; children = ( - 2FC4867627CDCD8FC332BB686C62FDE4 /* Core */, - 72EAC702A61A19B6EC92D70B6CA9D4E8 /* Support Files */, + 70E91E9355FAF7D2A8CA2A2112F06A60 /* Bugly.framework */, ); - name = SDWebImage; - path = SDWebImage; + name = Frameworks; sourceTree = ""; }; - DCE595EEF85D396533FF4892F3008A92 /* Pods */ = { + E11E673B56635EAB5EC9773B8D724830 /* MJExtension */ = { isa = PBXGroup; children = ( - 72657A79EE3B081E5F0D7C1166237E68 /* AFNetworking */, - 502B3DC21E7D9121A0C4B98D3286C994 /* Bugly */, - 18AF1EE6F6DA0C51E0452AA62EF8B8ED /* Masonry */, - 1F956714C6A7CF7B7999AEB4E29D418F /* MJExtension */, - 3128165374A2707E315E77D530A52B15 /* MJRefresh */, - D4CA9D10912142FCCA40F947B4FC5D1C /* SDWebImage */, + 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 = Pods; + name = MJExtension; + path = MJExtension; sourceTree = ""; }; - E09502DD4B1D7ABBB4407C6ED07C0666 /* Support Files */ = { + EAF375AA4ECFCEFB8A42837BED2CA767 /* Support Files */ = { isa = PBXGroup; children = ( - 4CD2E3B8C4EBAB8CE1F46D4D7B1B5CAA /* Bugly.debug.xcconfig */, - 6134DA50CBB0F618C7502B9B4E23963F /* Bugly.release.xcconfig */, + 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 */, ); name = "Support Files"; - path = "../Target Support Files/Bugly"; + path = "../Target Support Files/AFNetworking"; + sourceTree = ""; + }; + EE64A145CDD38964AF4945D376B599A2 /* MBProgressHUD */ = { + isa = PBXGroup; + children = ( + 2D069519EE909290F7C452231691CA88 /* MBProgressHUD.h */, + 8A6D5DE8BC7E18B47355B8494A426209 /* MBProgressHUD.m */, + 85416DF4AE2111F696182FA844F2611A /* Support Files */, + ); + name = MBProgressHUD; + path = MBProgressHUD; + sourceTree = ""; + }; + F364D65121D8297BD4970B4E36B87837 /* Resources */ = { + isa = PBXGroup; + children = ( + B9232C2E4F4A27C4FBD3F8EA3E351AF5 /* PrivacyInfo.xcprivacy */, + ); + name = Resources; sourceTree = ""; }; F7ED90CD818DD0484BF7DB0E1E3B9AB2 /* Targets Support Files */ = { @@ -1435,9 +1903,178 @@ name = "Targets Support Files"; sourceTree = ""; }; + F8863687E232B36E6A3336B80CEF9AEF /* Reachability */ = { + isa = PBXGroup; + children = ( + 62E02B7B42A91CD6887912774FAE6528 /* AFNetworkReachabilityManager.h */, + 0D18C326A9F4C285AD294832344E63FF /* AFNetworkReachabilityManager.m */, + ); + 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; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ + 09EE4349480B078AFE00E65B49E502BF /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + A6FCF74348D1907891FBDE3F2E331136 /* DZNEmptyDataSet-umbrella.h in Headers */, + 2EFF1EFA2FF0D2F1AE44A9DDBB932425 /* UIScrollView+EmptyDataSet.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 0A3C36B0909C1076801B26E74787825A /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; @@ -1597,19 +2234,107 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 66226021984AAF2F39AE410BEA754D6C /* Headers */ = { + 3A0259968FE382DF25C3F79CF30BA4DF /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 3FE4CEC187728FF5B98CECE3D92744E7 /* Pods-CustomKeyboard-umbrella.h in Headers */, + 34F918A5603258EEA91431BC4E1150F6 /* Pods-keyBoard-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; - 6EFC0393FC31641E19E2060FE077490A /* Headers */ = { + 3D4C17449A573C7CF2AE5D5EDDB5335C /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - BCFA1CA56CA625A754714006E0032750 /* Pods-keyBoard-umbrella.h in Headers */, + 821FF6B43F7ADAB6B60459D2966B33CB /* CALayer+Lookin.h in Headers */, + C9E8C9372C2DA29D302B058BE3AE9877 /* CALayer+LookinServer.h in Headers */, + 56F1B543BC54204336CB5E50B60F719F /* Color+Lookin.h in Headers */, + 93E8C78EAE0B7613201813966B8E04E2 /* Image+Lookin.h in Headers */, + BBF5FDA7D647517E2F904FE8E5596D96 /* LKS_AttrGroupsMaker.h in Headers */, + 9F89DCAA4092F3897E43E89842069A26 /* LKS_AttrModificationPatchHandler.h in Headers */, + CE86196C00DC1D658B6CB7D47A0233AA /* LKS_ConnectionManager.h in Headers */, + 5735091665AC18FAD028EB68786A85AE /* LKS_CustomAttrGroupsMaker.h in Headers */, + B2B5444DFE63D2835A7561C1D64C9344 /* LKS_CustomAttrModificationHandler.h in Headers */, + C4CC01ED368863C6E3220988FBC6CEFB /* LKS_CustomAttrSetterManager.h in Headers */, + A8AD2AE9695630E93DE504211EBAFBF1 /* LKS_CustomDisplayItemsMaker.h in Headers */, + 2A24F241D7D74FF6DEA953F9DD49391C /* LKS_EventHandlerMaker.h in Headers */, + 5D0DEC179A7B4143769C663082E2662A /* LKS_ExportManager.h in Headers */, + 9FB234EB4D8B5BCC699DB491E204594F /* LKS_GestureTargetActionsSearcher.h in Headers */, + C6FEC1088121FEA7DDC3384B7ECF3B44 /* LKS_Helper.h in Headers */, + 89B88FAD396608AAA9F935E471BB3CB9 /* LKS_HierarchyDetailsHandler.h in Headers */, + 7E4F0978B25350B2B28678A0BE7B3785 /* LKS_HierarchyDisplayItemsMaker.h in Headers */, + 4E964FFE29CFF8613C0029C913F39A05 /* LKS_InbuiltAttrModificationHandler.h in Headers */, + 32FF240AE9443A1D2CFE27F50B55F591 /* LKS_MultiplatformAdapter.h in Headers */, + AF185CDCA462AD6450543676951C82F9 /* LKS_ObjectRegistry.h in Headers */, + 2E86A7C77E43AEA4697979F1F848E68D /* LKS_RequestHandler.h in Headers */, + 1EC3AEA15AE416A53357261B37C622BD /* LKS_TraceManager.h in Headers */, + B2BC43DEC8DE2B9234693FE3782AB76C /* LKSConfigManager.h in Headers */, + CA56274BE7CBB3E759E0364785DF9799 /* Lookin_PTChannel.h in Headers */, + F62B0711DA506CCB3DF79F65134566C7 /* Lookin_PTPrivate.h in Headers */, + C9B63C6ED2ED691EA83D3EE65939444B /* Lookin_PTProtocol.h in Headers */, + 53C1722650FCAB2637867D0DC31FC3CB /* Lookin_PTUSBHub.h in Headers */, + 1C5CCB87E5B9C500F07A8244D7906295 /* LookinAppInfo.h in Headers */, + 1EDF5F5B68D4A76CE59D5B6CC7B6C469 /* LookinAttribute.h in Headers */, + 7E8A564A958AF81E5F63F34B8E550E58 /* LookinAttributeModification.h in Headers */, + 1B52E938D7999FC0CDA2AA22674948EB /* LookinAttributesGroup.h in Headers */, + 40AD5D0AB3ABF7F3A5A4A98BC5B84419 /* LookinAttributesSection.h in Headers */, + 9DFFD4780CA32B8E53D9F4FBC8B3F5AC /* LookinAttrIdentifiers.h in Headers */, + 0845A6CB7AE77A99CC475BD14101FE87 /* LookinAttrType.h in Headers */, + 9EBA682DA814406E9E5EF300587AF341 /* LookinAutoLayoutConstraint.h in Headers */, + 4A15ABB502D625EBE3E63100664AB822 /* LookinCodingValueType.h in Headers */, + 61EAFBCDC83B2C603918B3C9D9A73A18 /* LookinConnectionAttachment.h in Headers */, + 261C31F4038EC00D5961218C97905E21 /* LookinConnectionResponseAttachment.h in Headers */, + BFAC671767912906E90060B0F4BED5FB /* LookinCustomAttrModification.h in Headers */, + 6EFC0630CB2761A2B1FC47176CCD62D1 /* LookinCustomDisplayItemInfo.h in Headers */, + 27212D06F5EDE3BB10264D93075B2275 /* LookinDashboardBlueprint.h in Headers */, + E0B48B9D5D45AF3500FC718459D66E6C /* LookinDefines.h in Headers */, + C1D9802BE2A6410FFDFB1650FB9BA317 /* LookinDisplayItem.h in Headers */, + 1FD36A180D43C773D95D8E5BF719494C /* LookinDisplayItemDetail.h in Headers */, + 0B449236AF25C6C11B0DE3D6D0E4A19B /* LookinEventHandler.h in Headers */, + 150116E888969E8304BA3E2BB6529461 /* LookinHierarchyFile.h in Headers */, + 1CA85ECC202E5CF62530BAD7C0DCDAF2 /* LookinHierarchyInfo.h in Headers */, + 021ACCD4343D154E4782A5ECE222A8DF /* LookinIvarTrace.h in Headers */, + C992A335399F942237E754EE65C40CA5 /* LookinObject.h in Headers */, + EB646114ABEA7A4D6C2A724404778670 /* LookinServer.h in Headers */, + DD7F63D4E4640C7386877BB787740272 /* LookinServer-umbrella.h in Headers */, + A324722BA42F21E98F158EA6C133D715 /* LookinServerDefines.h in Headers */, + 67FCC0F9B42B1C20A66E99A3D56BED18 /* LookinStaticAsyncUpdateTask.h in Headers */, + 1D18A1A5D485D57192B021A8765C0AF5 /* LookinTuple.h in Headers */, + 332F2099D726E75CEFAF1F734104A066 /* LookinWeakContainer.h in Headers */, + 35D42759A562C482EA5DF574F75CF3B8 /* NSArray+Lookin.h in Headers */, + 4DA2C6099343CD55160ECB3EBDDFE1DF /* NSObject+Lookin.h in Headers */, + A93BA1C5A4FFEF3ACF371690485A2703 /* NSObject+LookinServer.h in Headers */, + 3B1C72DC480AB19BD55B6275750D62FE /* NSSet+Lookin.h in Headers */, + BBA61EF31BFDFA6FCA34DC4EBE6E1D9A /* NSString+Lookin.h in Headers */, + 117F4B6F653A8DA2637C5C93B4993884 /* Peertalk.h in Headers */, + 4EC8DBADA7BB954276351A639EB4398D /* UIBlurEffect+LookinServer.h in Headers */, + C2033A68F13923BF9B3EE19F39FC1411 /* UIColor+LookinServer.h in Headers */, + E82964ED7092CDCDAD08BC596A57B43A /* UIImage+LookinServer.h in Headers */, + D559CC4D0695CEE05F3B4C1C06475044 /* UIImageView+LookinServer.h in Headers */, + A6728DA26A7C457B78A7A3CCFA9D9A10 /* UILabel+LookinServer.h in Headers */, + A1ACD509069144C27542774A41FE0243 /* UITableView+LookinServer.h in Headers */, + 683D708C157C95ADB467BDD2230BD4E3 /* UITextField+LookinServer.h in Headers */, + 231A40F14D020AE2F61AA5C3289E6CF9 /* UITextView+LookinServer.h in Headers */, + F6A0D6EA1B5DC3FE04DC4A1B0A914121 /* UIView+LookinServer.h in Headers */, + 3800EA1B83FDE869FB2E4B049F519962 /* UIViewController+LookinServer.h in Headers */, + 6525ECE1CAFC1259F9E6E5FDDE6CF218 /* UIVisualEffectView+LookinServer.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5F83BB683AB24A3D1254696689952DDF /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + C2F8C43CFD4C890405F217DA7E00C839 /* Pods-CustomKeyboard-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B5D73FBBE3085418AA04A3B4B8D080B8 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + F2C9F9038FBEFD951516694AE873A2B9 /* MBProgressHUD.h in Headers */, + C993A4D0CFA51E567F458CA65C1298AA /* MBProgressHUD-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1662,22 +2387,25 @@ }; 18BD026D2210082A239FC15D072FD5BF /* Pods-keyBoard */ = { isa = PBXNativeTarget; - buildConfigurationList = FCE3E8712CE5CB67BC702E493D7E2243 /* Build configuration list for PBXNativeTarget "Pods-keyBoard" */; + buildConfigurationList = 782EAA470306AEE25A91F4D884D6AD6E /* Build configuration list for PBXNativeTarget "Pods-keyBoard" */; buildPhases = ( - 6EFC0393FC31641E19E2060FE077490A /* Headers */, - AFB5D9B93B578996ABD51507560BD64E /* Sources */, - 83DE9F788F7FEF1F8FBE5407651F444D /* Frameworks */, - 9CB9573035BE4B2A4B846ACC7B123B63 /* Resources */, + 3A0259968FE382DF25C3F79CF30BA4DF /* Headers */, + AEF1343FDA3F6E742726D597D7E0570E /* Sources */, + 1DB2A65061CA7DD5960E33B499AD1F7B /* Frameworks */, + E9B44FCD0123A8B6D20585E9C817C88A /* Resources */, ); buildRules = ( ); dependencies = ( - 0721A67E09079773C9FD71FC8AD5FC9D /* PBXTargetDependency */, - 42FDF14E242A83A309A5E0E9AD872BFB /* PBXTargetDependency */, - 3A51A97E9A7AF97FA982A4106AD313E7 /* PBXTargetDependency */, - 3B75BE7D78DA9D8EB2007A2C8507D93E /* PBXTargetDependency */, - A0F34F7F072B46F24802F53958145C52 /* PBXTargetDependency */, - 10BF5B7304DB404D9CB72D3A79065773 /* PBXTargetDependency */, + EF556CFA1E9B7BDBE8171EFFB9676A85 /* PBXTargetDependency */, + 117209812DCBEFB0C5846054A3AE6664 /* PBXTargetDependency */, + 5C288E02D6DD19A2FF27DB1C61FD8902 /* PBXTargetDependency */, + 89188B8B09AE72A473BCC9353B236078 /* PBXTargetDependency */, + 1FB4C6ADE9A85CA47926C2FE331288BC /* PBXTargetDependency */, + 670CFAE70888104AABF0C66D5302C07C /* PBXTargetDependency */, + 222BFDBDCCD855B408C58D8265F0C976 /* PBXTargetDependency */, + 770E92594EC7A0E0380ACF1E0A9FDB95 /* PBXTargetDependency */, + 5488E3BAEC96E0C6CA758459B72E0F95 /* PBXTargetDependency */, ); name = "Pods-keyBoard"; productName = Pods_keyBoard; @@ -1696,7 +2424,7 @@ buildRules = ( ); dependencies = ( - 88E2D8F9CA39C89731F3AE8B00D15E67 /* PBXTargetDependency */, + EE61A46DF554B3E5C29DB10DCBB3618A /* PBXTargetDependency */, ); name = SDWebImage; productName = SDWebImage; @@ -1715,7 +2443,7 @@ buildRules = ( ); dependencies = ( - 394032A92C21422B814C089279FA7D6F /* PBXTargetDependency */, + 578B4FEE3B5BBEBE31FFA9C174A0B42C /* PBXTargetDependency */, ); name = MJExtension; productName = MJExtension; @@ -1740,6 +2468,24 @@ productReference = 1FFED36A657123030ABB700256D73F15 /* Masonry */; productType = "com.apple.product-type.framework"; }; + 638FEAAFC575BB76BC6AC055CDDA3506 /* LookinServer */ = { + isa = PBXNativeTarget; + buildConfigurationList = E7624967EDC883D80ED3DA81C495736B /* Build configuration list for PBXNativeTarget "LookinServer" */; + buildPhases = ( + 3D4C17449A573C7CF2AE5D5EDDB5335C /* Headers */, + 8AF957863B2E92075C7B36542829939B /* Sources */, + 7CFE8F67F3A1361064414896BC73914A /* Frameworks */, + D518E37278D48F046F4C76EA0E72D5AC /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = LookinServer; + productName = LookinServer; + productReference = 25664483ABF4DC8EC03E7472AA04333B /* LookinServer */; + productType = "com.apple.product-type.framework"; + }; 6868056D761E163D10FDAF8CF1C4D9B8 /* MJRefresh */ = { isa = PBXNativeTarget; buildConfigurationList = 29BB59B7B51BC6194771995E3356CF70 /* Build configuration list for PBXNativeTarget "MJRefresh" */; @@ -1752,20 +2498,38 @@ buildRules = ( ); dependencies = ( - F4DB95A938613EB239394D9BC7D85E47 /* PBXTargetDependency */, + 5D247EA99693B7B23340BCC7FCB64DA1 /* PBXTargetDependency */, ); name = MJRefresh; productName = MJRefresh; productReference = E49D6D248DD1CEE584E6776B9164A1B2 /* MJRefresh */; productType = "com.apple.product-type.framework"; }; + 82B0A41D3031FF27D78E17B0A9A46FB0 /* MBProgressHUD */ = { + isa = PBXNativeTarget; + buildConfigurationList = 945C0F2B41CBADE68A142120AE9A4AF3 /* Build configuration list for PBXNativeTarget "MBProgressHUD" */; + buildPhases = ( + B5D73FBBE3085418AA04A3B4B8D080B8 /* Headers */, + A29E3C9E62E3E86A20CAE1E7632313FC /* Sources */, + CA6527CF424B1AA12AF1D0BB36EBAF73 /* Frameworks */, + E664BDFE0B44D742638A43686ACB3008 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = MBProgressHUD; + productName = MBProgressHUD; + productReference = 8B8FAB0D627B17EDE1366984278705D9 /* MBProgressHUD */; + productType = "com.apple.product-type.framework"; + }; 94CFBA7D633ECA58DF85C327B035E6A3 /* SDWebImage-SDWebImage */ = { isa = PBXNativeTarget; - buildConfigurationList = 3A3BFFB46D4AE092AC96BD3D9D624546 /* Build configuration list for PBXNativeTarget "SDWebImage-SDWebImage" */; + buildConfigurationList = E1B78FF12090122B97AE1A33AD172B8C /* Build configuration list for PBXNativeTarget "SDWebImage-SDWebImage" */; buildPhases = ( - 14B98376E3B2827487D1B5BA7E349E67 /* Sources */, - 5F8D0AA57E07244D2E43526654F67443 /* Frameworks */, - F94894A2558471C720587EA6709F2019 /* Resources */, + AD25BCFFC542199E6A56D85CF9FB3D3B /* Sources */, + 68405B5F41E04D755317E63849131904 /* Frameworks */, + E40003F128ACA565E0AF6D7254C64D86 /* Resources */, ); buildRules = ( ); @@ -1778,11 +2542,11 @@ }; B26054DF1DEA11585A231AF6D1D80D5E /* MJRefresh-MJRefresh.Privacy */ = { isa = PBXNativeTarget; - buildConfigurationList = 68B32BA86F0CEE6E06F49B0F2C62CD73 /* Build configuration list for PBXNativeTarget "MJRefresh-MJRefresh.Privacy" */; + buildConfigurationList = 0B91AB5AF396DEF5CC076D126E4738A7 /* Build configuration list for PBXNativeTarget "MJRefresh-MJRefresh.Privacy" */; buildPhases = ( - A1FDE66B11377A083FC25DE4671B3305 /* Sources */, - 2195E2C2C2334091D023B7EB98B24603 /* Frameworks */, - FF140DFA44CFFB4A12C0595EC42174A6 /* Resources */, + 8986B9155B9BA0DA7D02654B069F0887 /* Sources */, + 0DE7FCDD6C04EC4E1E9ECB00A0604FB7 /* Frameworks */, + 021D9F4B66A6BEEC09A45D59909CBDE6 /* Resources */, ); buildRules = ( ); @@ -1795,11 +2559,11 @@ }; B32AF3F43989CBA171BB1FB3957A4509 /* MJExtension-MJExtension */ = { isa = PBXNativeTarget; - buildConfigurationList = 4650649B39AEE2A0C6FEE8FF9B18E065 /* Build configuration list for PBXNativeTarget "MJExtension-MJExtension" */; + buildConfigurationList = 95B0FCBEC38B41A89EDFDA2284E4CF2F /* Build configuration list for PBXNativeTarget "MJExtension-MJExtension" */; buildPhases = ( - 83E45E911DCE522BC4265AAB5CBA73D3 /* Sources */, - E62253CBB3499DA4547AF2A780EC3E2F /* Frameworks */, - AA2ABB6111F2F1BE117241EC515B268B /* Resources */, + D5A57C43D4D146DC812EB6C4160745DD /* Sources */, + A12778F5B92D79BB1CB466B6E7808C73 /* Frameworks */, + D4B34D2916BE13E436CD1FF18F0BC0CB /* Resources */, ); buildRules = ( ); @@ -1812,20 +2576,43 @@ }; D9B2DB11933DB55A80A118934E6680AB /* Pods-CustomKeyboard */ = { isa = PBXNativeTarget; - buildConfigurationList = DA39DBDB0F7D05D976CC7C6A67459F5F /* Build configuration list for PBXNativeTarget "Pods-CustomKeyboard" */; + buildConfigurationList = B1224CED7ED3E4B356E8F429D6C62F7E /* Build configuration list for PBXNativeTarget "Pods-CustomKeyboard" */; buildPhases = ( - 66226021984AAF2F39AE410BEA754D6C /* Headers */, - 253ADC0B42FA607A67D61C10A572535E /* Sources */, - 0DDBBB716811E63091A5A45D29A5FEFA /* Frameworks */, - E41CF6701928D5454D4C51832F5D994D /* Resources */, + 5F83BB683AB24A3D1254696689952DDF /* Headers */, + E8CCE3C7763C30E81A067AE9AC1B8915 /* Sources */, + D04C3487CC66436E0AC1085019C1D36C /* Frameworks */, + 8DF763B35C7183D33FE173339E261549 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 33AF3D0CC306E3DD56CCD4562DC58ABA /* PBXTargetDependency */, + 6D842140C98E51FF8C3EC4AC689EC108 /* PBXTargetDependency */, + AEC4F62BB393A387D98BB39E07E54A5E /* PBXTargetDependency */, + BD5EEFF9A8B5208454EE5C08E29DEC6F /* PBXTargetDependency */, + 32CDD4F647C6AFB9D8EF74E8A88163CD /* PBXTargetDependency */, + ); + name = "Pods-CustomKeyboard"; + productName = Pods_CustomKeyboard; + productReference = 0B4AAC15A428CDC2A62AF9CC27BEA609 /* Pods-CustomKeyboard */; + productType = "com.apple.product-type.framework"; + }; + F1BCD9702276377FB5B3BDB6EAF709D7 /* DZNEmptyDataSet */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1CF7CA11A791652D6975B2EDE2FC6719 /* Build configuration list for PBXNativeTarget "DZNEmptyDataSet" */; + buildPhases = ( + 09EE4349480B078AFE00E65B49E502BF /* Headers */, + 06020C44A2C925372A030239192BBF6C /* Sources */, + E672724427269716049B769344D7C3DC /* Frameworks */, + FD378D1F5CAFCC3C5D44074788563A1C /* Resources */, ); buildRules = ( ); dependencies = ( ); - name = "Pods-CustomKeyboard"; - productName = Pods_CustomKeyboard; - productReference = 0B4AAC15A428CDC2A62AF9CC27BEA609 /* Pods-CustomKeyboard */; + name = DZNEmptyDataSet; + productName = DZNEmptyDataSet; + productReference = 5DA4577FE3BC4A03751108FFED07B385 /* DZNEmptyDataSet */; productType = "com.apple.product-type.framework"; }; /* End PBXNativeTarget section */ @@ -1848,13 +2635,16 @@ mainGroup = CF1408CF629C7361332E53B88F7BD30C; minimizedProjectReferenceProxies = 0; preferredProjectObjectVersion = 77; - productRefGroup = AA7E5CA260B4C52744905877A30A95DD /* Products */; + productRefGroup = 1C8A19406FF58E9BA6BC427CA02E9857 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 0130B3724283586C0E9D2A112D4F2AA1 /* AFNetworking */, 4A68CFD979D413A619DF631BB121D98F /* Bugly */, + F1BCD9702276377FB5B3BDB6EAF709D7 /* DZNEmptyDataSet */, + 638FEAAFC575BB76BC6AC055CDDA3506 /* LookinServer */, 55AF53E6C77A10ED4985E04D74A8878E /* Masonry */, + 82B0A41D3031FF27D78E17B0A9A46FB0 /* MBProgressHUD */, 4D3BA58D0583DF37575CACAB3DDADC85 /* MJExtension */, B32AF3F43989CBA171BB1FB3957A4509 /* MJExtension-MJExtension */, 6868056D761E163D10FDAF8CF1C4D9B8 /* MJRefresh */, @@ -1868,6 +2658,14 @@ /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ + 021D9F4B66A6BEEC09A45D59909CBDE6 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + BBD85F9E0E25710317253841091C391F /* PrivacyInfo.xcprivacy in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 1B0BF833FF02F4B145B7A6461734A0F1 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -1893,6 +2691,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 8DF763B35C7183D33FE173339E261549 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 9BB224D4E89ABC2539ABBEBDC9696C8F /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -1900,22 +2705,37 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 9CB9573035BE4B2A4B846ACC7B123B63 /* Resources */ = { + D4B34D2916BE13E436CD1FF18F0BC0CB /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2FEE980BEE23B8E0C7EBB70445EC8C9A /* PrivacyInfo.xcprivacy in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D518E37278D48F046F4C76EA0E72D5AC /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - AA2ABB6111F2F1BE117241EC515B268B /* Resources */ = { + E40003F128ACA565E0AF6D7254C64D86 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 1C73BC7EEF39CC3D3A21EACAD858413D /* PrivacyInfo.xcprivacy in Resources */, + EBC9AA5D4A55F79BB5CBF6CC92719FAF /* PrivacyInfo.xcprivacy in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - E41CF6701928D5454D4C51832F5D994D /* Resources */ = { + E664BDFE0B44D742638A43686ACB3008 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E9B44FCD0123A8B6D20585E9C817C88A /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( @@ -1929,25 +2749,25 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - F94894A2558471C720587EA6709F2019 /* Resources */ = { + FD378D1F5CAFCC3C5D44074788563A1C /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 0BADC710EA22BBCD76E59748C2A56ECF /* PrivacyInfo.xcprivacy in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - FF140DFA44CFFB4A12C0595EC42174A6 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - AF1A6353DEDBE196A10C8897F94DDA8E /* PrivacyInfo.xcprivacy in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 06020C44A2C925372A030239192BBF6C /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + AFD1D411A9387DCEC6F0034653E23787 /* DZNEmptyDataSet-dummy.m in Sources */, + 5F5426608460A8B17C1AE5C2351BAA19 /* UIScrollView+EmptyDataSet.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 090A96B9D443BC38DD5A251A9EE646AE /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -2046,40 +2866,106 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 14B98376E3B2827487D1B5BA7E349E67 /* Sources */ = { + 8986B9155B9BA0DA7D02654B069F0887 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - 253ADC0B42FA607A67D61C10A572535E /* Sources */ = { + 8AF957863B2E92075C7B36542829939B /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - A3148D9EB39C7BFAF4F85E3378F3EF80 /* Pods-CustomKeyboard-dummy.m in Sources */, + 0BE3B8DB6034364E7CF3AE9D01C7C0B4 /* CALayer+Lookin.m in Sources */, + 7D736CE5AD0A987D2A7D2FD72E31BF41 /* CALayer+LookinServer.m in Sources */, + 6002CB94684D7C786700D2A294146AEC /* Color+Lookin.m in Sources */, + 50096BAC0F3270FB111E76D32714E579 /* Image+Lookin.m in Sources */, + AFDC0B8255B2F3CED8E609F8A3BD1CDB /* LKS_AttrGroupsMaker.m in Sources */, + 6BC2A615678C8BAE9F34ABA68BFDEF78 /* LKS_AttrModificationPatchHandler.m in Sources */, + 6C57809DCEA4B6C0CA79918A69FD75DE /* LKS_ConnectionManager.m in Sources */, + FFC6D50089FA32FD7AAF25747E56EA60 /* LKS_CustomAttrGroupsMaker.m in Sources */, + 928A1ED0692DF0229F66A87135F93F2A /* LKS_CustomAttrModificationHandler.m in Sources */, + B565C08CE947CF591B1D3582272D5E1D /* LKS_CustomAttrSetterManager.m in Sources */, + 3E3D09700A62280A9EB8D65B97335ED8 /* LKS_CustomDisplayItemsMaker.m in Sources */, + 27CC45A4ABE5B40723D35310D05CD146 /* LKS_EventHandlerMaker.m in Sources */, + C8771885BEA9EA0BD2E2C474587325E2 /* LKS_ExportManager.m in Sources */, + B79864F972C51037B350802D8CD48024 /* LKS_GestureTargetActionsSearcher.m in Sources */, + 69F6E66A089C40FB1063DE15499BCFDE /* LKS_Helper.m in Sources */, + 78A3C3994AFFC6A2D4970AEB6D797CE5 /* LKS_HierarchyDetailsHandler.m in Sources */, + 89EAB8D0452D0E2114ED971B10D98CC3 /* LKS_HierarchyDisplayItemsMaker.m in Sources */, + 7C8782A3078662BC2EF639A9608A2C82 /* LKS_InbuiltAttrModificationHandler.m in Sources */, + 2759D8D4FCE58812ADECB348E369C6F0 /* LKS_MultiplatformAdapter.m in Sources */, + 6960FF2C4D61A09722930B33B1C7135D /* LKS_ObjectRegistry.m in Sources */, + AE69A3B75BEEB9E2C54168BF0C502BC6 /* LKS_RequestHandler.m in Sources */, + 810C8D7902163BBA0185A4A112B2DFD6 /* LKS_TraceManager.m in Sources */, + A9BEDE2ADF9D1E0D0D1A241806A1A486 /* LKSConfigManager.m in Sources */, + D091F05269EE0566B665B00C7D912F8E /* Lookin_PTChannel.m in Sources */, + 0C79142D1349DD9A969F47A0A8AAA0CB /* Lookin_PTProtocol.m in Sources */, + 20E738E52B4712385489A62374C74C7F /* Lookin_PTUSBHub.m in Sources */, + 464A0100327C8531D86BDC31737CCF75 /* LookinAppInfo.m in Sources */, + 8A256CA266FB314BBD4DB2287DAEF247 /* LookinAttribute.m in Sources */, + 2DDA5F044BC698BC5D48A7CFDDBF71E3 /* LookinAttributeModification.m in Sources */, + 74ABF19BACB99F862DB62AA14508AFA0 /* LookinAttributesGroup.m in Sources */, + 7C53FB6BBB0CBAA879F1603B0FEDB80B /* LookinAttributesSection.m in Sources */, + F8616FAFEE1124368CB96473CE20CDB4 /* LookinAttrIdentifiers.m in Sources */, + 1FDEA3FFA45F29C1331723E9579D66A5 /* LookinAutoLayoutConstraint.m in Sources */, + A6B2B022993BBC55550CFBB0A0C78209 /* LookinConnectionAttachment.m in Sources */, + 9887678D7D6BC165694560D92AF2C31A /* LookinConnectionResponseAttachment.m in Sources */, + 85BB8B4B5C29C5EEC52282F33A4CAF23 /* LookinCustomAttrModification.m in Sources */, + E7FEAB9F421F7EBAF021F792D8E9C4D6 /* LookinCustomDisplayItemInfo.m in Sources */, + 447BBB1BCA8E0F2D23634888BED6DA81 /* LookinDashboardBlueprint.m in Sources */, + B81566F19789EBD9BE2714E2A6059D36 /* LookinDisplayItem.m in Sources */, + BC7A1933CCF40C3C5E2E4A70AD2D0657 /* LookinDisplayItemDetail.m in Sources */, + 9E6B00AF2ECE462D4D3C42AFC02F2AD7 /* LookinEventHandler.m in Sources */, + 6CE8701D161A4BC0860FAF3951762A34 /* LookinHierarchyFile.m in Sources */, + 9DDDCFC08B54A61C519DA78F94464E6B /* LookinHierarchyInfo.m in Sources */, + D89C7D5455E3E8E2D7EC6B880253BD9B /* LookinIvarTrace.m in Sources */, + 5A8BC91257FF6B36237BF09A7A6EADF6 /* LookinObject.m in Sources */, + A9609EEBDD5FD40292925E80ED84D5DF /* LookinServer-dummy.m in Sources */, + 9A89C16038149623A1DF06D47E7F953A /* LookinStaticAsyncUpdateTask.m in Sources */, + 9E3C5CB1C97B2ED16218956999BFF7AC /* LookinTuple.m in Sources */, + 2CDC7B9EAD356E35FEAF526EEA6A8E91 /* LookinWeakContainer.m in Sources */, + D1230E19DD1507E6370B80DF6653AC2A /* NSArray+Lookin.m in Sources */, + F6A2DEEA8E8B92D365AFDDBD5E8C1218 /* NSObject+Lookin.m in Sources */, + FA6DA93357E2E9E9AADDFB3E39DEB6C2 /* NSObject+LookinServer.m in Sources */, + 5490C03887ACF6C4EAC25ADFBB509CE5 /* NSSet+Lookin.m in Sources */, + 2460C08042AF8B7D0492A062F755986E /* NSString+Lookin.m in Sources */, + F8F1B1196CAA5114BA9A95AA7E6D6AEB /* UIBlurEffect+LookinServer.m in Sources */, + 41A4AAE7E6024E7AAB83DD22FB42D34D /* UIColor+LookinServer.m in Sources */, + 68C3E98F8B9D6035962F29AE025DA891 /* UIImage+LookinServer.m in Sources */, + 392F62298E0D8C669229E132D791BBF5 /* UIImageView+LookinServer.m in Sources */, + B5C521FFB8E09DFE348238E21556842F /* UILabel+LookinServer.m in Sources */, + F3F4A6309BD95DFAA4DCC60A4E07C515 /* UITableView+LookinServer.m in Sources */, + 3BB69CB142D744367868F834912993CB /* UITextField+LookinServer.m in Sources */, + 9B06400877E40C173F5A1C9761F288CB /* UITextView+LookinServer.m in Sources */, + 9B1EF09A8A473D92C1258B00791BF5F0 /* UIView+LookinServer.m in Sources */, + DF525E5405FAD3B98B0C2D966EB2DD95 /* UIViewController+LookinServer.m in Sources */, + 1EDC6F899051F0E858270F7556AF2F12 /* UIVisualEffectView+LookinServer.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 83E45E911DCE522BC4265AAB5CBA73D3 /* Sources */ = { + A29E3C9E62E3E86A20CAE1E7632313FC /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 11D4DC1FCE5647EEA8484AA4A880AF8F /* MBProgressHUD.m in Sources */, + 104D9196010D2A8C52C0C19E9C9D52E8 /* MBProgressHUD-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + AD25BCFFC542199E6A56D85CF9FB3D3B /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - A1FDE66B11377A083FC25DE4671B3305 /* Sources */ = { + AEF1343FDA3F6E742726D597D7E0570E /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - AFB5D9B93B578996ABD51507560BD64E /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 3CE201A6CFF26BD49792F9A8E4C822A5 /* Pods-keyBoard-dummy.m in Sources */, + 5A1E04C829BF2C50593ADDBC1A69429F /* Pods-keyBoard-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2106,6 +2992,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + D5A57C43D4D146DC812EB6C4160745DD /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; DA0B6A6F9B3EDF226BF081DAC7E777E7 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -2156,120 +3049,125 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + E8CCE3C7763C30E81A067AE9AC1B8915 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8F30C8026F48C60D5B2CAE9CFC166004 /* Pods-CustomKeyboard-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 0721A67E09079773C9FD71FC8AD5FC9D /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = AFNetworking; - target = 0130B3724283586C0E9D2A112D4F2AA1 /* AFNetworking */; - targetProxy = F4298358FEAF506C773B2D34F3DF6B12 /* PBXContainerItemProxy */; - }; - 10BF5B7304DB404D9CB72D3A79065773 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = SDWebImage; - target = 3847153A6E5EEFB86565BA840768F429 /* SDWebImage */; - targetProxy = F236FEF1E37470AFA015925961D566A3 /* PBXContainerItemProxy */; - }; - 394032A92C21422B814C089279FA7D6F /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = "MJExtension-MJExtension"; - target = B32AF3F43989CBA171BB1FB3957A4509 /* MJExtension-MJExtension */; - targetProxy = 23C4ACB33CF11EF7F294BFEFDFEE525F /* PBXContainerItemProxy */; - }; - 3A51A97E9A7AF97FA982A4106AD313E7 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = MJExtension; - target = 4D3BA58D0583DF37575CACAB3DDADC85 /* MJExtension */; - targetProxy = D31947E4B8C395A2964CC7C4CA10B4B3 /* PBXContainerItemProxy */; - }; - 3B75BE7D78DA9D8EB2007A2C8507D93E /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = MJRefresh; - target = 6868056D761E163D10FDAF8CF1C4D9B8 /* MJRefresh */; - targetProxy = D00922B5D33413CCF1E3D4753D9B5522 /* PBXContainerItemProxy */; - }; - 42FDF14E242A83A309A5E0E9AD872BFB /* PBXTargetDependency */ = { + 117209812DCBEFB0C5846054A3AE6664 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = Bugly; target = 4A68CFD979D413A619DF631BB121D98F /* Bugly */; - targetProxy = ED8283C03EBD084126ED5759CD5B7EF5 /* PBXContainerItemProxy */; + targetProxy = B680C6AEDC2C7072F4BCC65FA83A00F2 /* PBXContainerItemProxy */; }; - 88E2D8F9CA39C89731F3AE8B00D15E67 /* PBXTargetDependency */ = { + 1FB4C6ADE9A85CA47926C2FE331288BC /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = "SDWebImage-SDWebImage"; - target = 94CFBA7D633ECA58DF85C327B035E6A3 /* SDWebImage-SDWebImage */; - targetProxy = 8C46BC742135C578AA462516574ECF6A /* PBXContainerItemProxy */; + name = MBProgressHUD; + target = 82B0A41D3031FF27D78E17B0A9A46FB0 /* MBProgressHUD */; + targetProxy = 67F0F8485CEFCEAF14CFFCC3F2461F7C /* PBXContainerItemProxy */; }; - A0F34F7F072B46F24802F53958145C52 /* PBXTargetDependency */ = { + 222BFDBDCCD855B408C58D8265F0C976 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = MJRefresh; + target = 6868056D761E163D10FDAF8CF1C4D9B8 /* MJRefresh */; + targetProxy = DF6BBAC9AED95181B9D6A27C2AED4872 /* PBXContainerItemProxy */; + }; + 32CDD4F647C6AFB9D8EF74E8A88163CD /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = Masonry; target = 55AF53E6C77A10ED4985E04D74A8878E /* Masonry */; - targetProxy = 7F4A11CEA9C42F01CCC8FD8CF31E0D31 /* PBXContainerItemProxy */; + targetProxy = 551922F754B651AFCAAB56605458A1A4 /* PBXContainerItemProxy */; }; - F4DB95A938613EB239394D9BC7D85E47 /* PBXTargetDependency */ = { + 33AF3D0CC306E3DD56CCD4562DC58ABA /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = AFNetworking; + target = 0130B3724283586C0E9D2A112D4F2AA1 /* AFNetworking */; + targetProxy = F34B1D580EA71604D4CC7C4C5807E366 /* PBXContainerItemProxy */; + }; + 5488E3BAEC96E0C6CA758459B72E0F95 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = SDWebImage; + target = 3847153A6E5EEFB86565BA840768F429 /* SDWebImage */; + targetProxy = 5D9596750911C6C3E3B693FA7242334B /* PBXContainerItemProxy */; + }; + 578B4FEE3B5BBEBE31FFA9C174A0B42C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "MJExtension-MJExtension"; + target = B32AF3F43989CBA171BB1FB3957A4509 /* MJExtension-MJExtension */; + targetProxy = F4000FEC7CADA56B75E5CC31E64EC891 /* PBXContainerItemProxy */; + }; + 5C288E02D6DD19A2FF27DB1C61FD8902 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = DZNEmptyDataSet; + target = F1BCD9702276377FB5B3BDB6EAF709D7 /* DZNEmptyDataSet */; + targetProxy = AA9226BB33C3F9E019FB415C2032A082 /* PBXContainerItemProxy */; + }; + 5D247EA99693B7B23340BCC7FCB64DA1 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "MJRefresh-MJRefresh.Privacy"; target = B26054DF1DEA11585A231AF6D1D80D5E /* MJRefresh-MJRefresh.Privacy */; - targetProxy = 74C35E0C9F3979D774EBA89927D5F9BE /* PBXContainerItemProxy */; + targetProxy = BBBA8C59A31486B3AE2F16C6A4AAAB66 /* PBXContainerItemProxy */; + }; + 670CFAE70888104AABF0C66D5302C07C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = MJExtension; + target = 4D3BA58D0583DF37575CACAB3DDADC85 /* MJExtension */; + targetProxy = ED58197BE1BA80A23DFAA0D475221386 /* PBXContainerItemProxy */; + }; + 6D842140C98E51FF8C3EC4AC689EC108 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = DZNEmptyDataSet; + target = F1BCD9702276377FB5B3BDB6EAF709D7 /* DZNEmptyDataSet */; + targetProxy = B0F47C29852712CF2F2C1E658ECD1809 /* PBXContainerItemProxy */; + }; + 770E92594EC7A0E0380ACF1E0A9FDB95 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Masonry; + target = 55AF53E6C77A10ED4985E04D74A8878E /* Masonry */; + targetProxy = E2B36932A623A0432422370F519C4507 /* PBXContainerItemProxy */; + }; + 89188B8B09AE72A473BCC9353B236078 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = LookinServer; + target = 638FEAAFC575BB76BC6AC055CDDA3506 /* LookinServer */; + targetProxy = 332EDC024ABBEE82955E7E88C302D2E4 /* PBXContainerItemProxy */; + }; + AEC4F62BB393A387D98BB39E07E54A5E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = MBProgressHUD; + target = 82B0A41D3031FF27D78E17B0A9A46FB0 /* MBProgressHUD */; + targetProxy = A311284721E0C3165FAA791C3EE6961E /* PBXContainerItemProxy */; + }; + BD5EEFF9A8B5208454EE5C08E29DEC6F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = MJExtension; + target = 4D3BA58D0583DF37575CACAB3DDADC85 /* MJExtension */; + targetProxy = AD74DB90134D3DB33FAC2C873C0764E9 /* PBXContainerItemProxy */; + }; + EE61A46DF554B3E5C29DB10DCBB3618A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "SDWebImage-SDWebImage"; + target = 94CFBA7D633ECA58DF85C327B035E6A3 /* SDWebImage-SDWebImage */; + targetProxy = 8C2E663FC9840B2B7BABEF079AD58862 /* PBXContainerItemProxy */; + }; + EF556CFA1E9B7BDBE8171EFFB9676A85 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = AFNetworking; + target = 0130B3724283586C0E9D2A112D4F2AA1 /* AFNetworking */; + targetProxy = 45076E4E15CD2B80A147FBC40CD1D7BD /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ - 03A5A25907B9F099CB1930F2C4AA0E3F /* Release */ = { + 1A69165A21A7A1CC42A38CF8ADE98215 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 4B22EE0B7D2C1D1066750C4AB84FDA27 /* MJExtension.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; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - WRAPPER_EXTENSION = bundle; - }; - name = Release; - }; - 0A6B03880AA76C2476846FABA9DAB99A /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 74CC813EBCFDBA413D1E8F2AE302E41A /* 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; - }; - 16DD238F86190BFED9FB2F16A83B2A56 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 20B1DAD84F32D1AF296F0D63C5DEE9AB /* 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; - }; - 2D1085CA7BD144CABF012FC10C6C9120 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 4EF47C40D45E06BA89946B4C9F04A546 /* Masonry.debug.xcconfig */; + baseConfigurationReference = 2DAD93B79D27664FE05E862A2C992A45 /* LookinServer.release.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -2281,30 +3179,30 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = NO; ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_PREFIX_HEADER = "Target Support Files/Masonry/Masonry-prefix.pch"; + GCC_PREFIX_HEADER = "Target Support Files/LookinServer/LookinServer-prefix.pch"; GENERATE_INFOPLIST_FILE = NO; - INFOPLIST_FILE = "Target Support Files/Masonry/Masonry-Info.plist"; + INFOPLIST_FILE = "Target Support Files/LookinServer/LookinServer-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MODULEMAP_FILE = "Target Support Files/Masonry/Masonry.modulemap"; - PRODUCT_MODULE_NAME = Masonry; - PRODUCT_NAME = Masonry; + MODULEMAP_FILE = "Target Support Files/LookinServer/LookinServer.modulemap"; + PRODUCT_MODULE_NAME = LookinServer; + PRODUCT_NAME = LookinServer; 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 = Debug; + name = Release; }; - 4CF8CD0C5349DA6326EF3FCF43C53402 /* Debug */ = { + 1D73A0661FBB5E8564C1FE75B669DC24 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 35BFA337F4E1FDE67C773A82CCDFD6DA /* Pods-keyBoard.debug.xcconfig */; buildSettings = { @@ -2343,65 +3241,9 @@ }; name = Debug; }; - 51753BD6FE635BB9421BCA4C05F63C6A /* Release */ = { + 227E6E64001CE57ED070BAB9C31DCAEC /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = DF80C56AF1D41887B8622FAC95138810 /* MJRefresh.release.xcconfig */; - buildSettings = { - 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; - GCC_PREFIX_HEADER = "Target Support Files/MJRefresh/MJRefresh-prefix.pch"; - GENERATE_INFOPLIST_FILE = NO; - INFOPLIST_FILE = "Target Support Files/MJRefresh/MJRefresh-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - MODULEMAP_FILE = "Target Support Files/MJRefresh/MJRefresh.modulemap"; - PRODUCT_MODULE_NAME = MJRefresh; - PRODUCT_NAME = MJRefresh; - 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; - }; - 5B8933506DB0D0650A36E47F8AB90C24 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 3316E3BF456739AB7A0F0FD1920F5F6B /* 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; - }; - 5EB0D7D4CF48681DA30DD58C2E33B044 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = A6E8FF241173D596A21D4D4B7D86A810 /* Pods-keyBoard.release.xcconfig */; + baseConfigurationReference = 1D774D8146EBC82B4A77204A273761B8 /* Pods-CustomKeyboard.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; CLANG_ENABLE_OBJC_WEAK = NO; @@ -2415,7 +3257,7 @@ 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"; + INFOPLIST_FILE = "Target Support Files/Pods-CustomKeyboard/Pods-CustomKeyboard-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( @@ -2424,7 +3266,7 @@ "@loader_path/Frameworks", ); MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-keyBoard/Pods-keyBoard.modulemap"; + MODULEMAP_FILE = "Target Support Files/Pods-CustomKeyboard/Pods-CustomKeyboard.modulemap"; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; @@ -2439,9 +3281,155 @@ }; name = Release; }; - 614F7847ADAD2F1EEC9E48FAEC955108 /* Debug */ = { + 2D1085CA7BD144CABF012FC10C6C9120 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 74CC813EBCFDBA413D1E8F2AE302E41A /* MJRefresh.debug.xcconfig */; + baseConfigurationReference = B9AC91A4E70DD8F8592A5811E8617578 /* Masonry.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/Masonry/Masonry-prefix.pch"; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = "Target Support Files/Masonry/Masonry-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/Masonry/Masonry.modulemap"; + PRODUCT_MODULE_NAME = Masonry; + PRODUCT_NAME = Masonry; + 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; + }; + 35044A57510DB3F4E442A9C16E980E4A /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 61A50E7751555885AEB4247687F5DF05 /* DZNEmptyDataSet.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/DZNEmptyDataSet/DZNEmptyDataSet-prefix.pch"; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = "Target Support Files/DZNEmptyDataSet/DZNEmptyDataSet-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/DZNEmptyDataSet/DZNEmptyDataSet.modulemap"; + PRODUCT_MODULE_NAME = DZNEmptyDataSet; + PRODUCT_NAME = DZNEmptyDataSet; + 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; + }; + 427CF48FABE82C6FC8208160FDF4A9CE /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 57BCCC946B3042A20D0C8F15D69FF943 /* 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; + }; + 49CEA33268972C89BF290FCBF8F9DFC0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 52832E51BDED300B58102A301664AD5A /* DZNEmptyDataSet.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/DZNEmptyDataSet/DZNEmptyDataSet-prefix.pch"; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = "Target Support Files/DZNEmptyDataSet/DZNEmptyDataSet-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/DZNEmptyDataSet/DZNEmptyDataSet.modulemap"; + PRODUCT_MODULE_NAME = DZNEmptyDataSet; + PRODUCT_NAME = DZNEmptyDataSet; + 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; + }; + 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 */; buildSettings = { CLANG_ENABLE_OBJC_WEAK = NO; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -2472,6 +3460,137 @@ 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; + }; + 532B03D3A70665C5D6CA2E785045C97B /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 3E2A55F2F78E11DEDCF2FA119B3E1912 /* MJExtension.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; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + WRAPPER_EXTENSION = bundle; + }; + name = Release; + }; + 614F7847ADAD2F1EEC9E48FAEC955108 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D2BBA8DCCC9E2658211368C22BE1B033 /* MJRefresh.debug.xcconfig */; + buildSettings = { + 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; + GCC_PREFIX_HEADER = "Target Support Files/MJRefresh/MJRefresh-prefix.pch"; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = "Target Support Files/MJRefresh/MJRefresh-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/MJRefresh/MJRefresh.modulemap"; + PRODUCT_MODULE_NAME = MJRefresh; + PRODUCT_NAME = MJRefresh; + 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; + }; + 618AB008538F74AAF983C04297207BB6 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9641B4F4D8DDE2072CB32BF4C9C2882A /* LookinServer.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/LookinServer/LookinServer-prefix.pch"; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = "Target Support Files/LookinServer/LookinServer-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/LookinServer/LookinServer.modulemap"; + PRODUCT_MODULE_NAME = LookinServer; + PRODUCT_NAME = LookinServer; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_INSTALL_OBJC_HEADER = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 7BB5AE2225500DE9658B6277FED45BCD /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0D6215D1BCCE125B8DF73E38013CBBDC /* Pods-CustomKeyboard.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-CustomKeyboard/Pods-CustomKeyboard-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-CustomKeyboard/Pods-CustomKeyboard.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 = ""; }; @@ -2543,9 +3662,9 @@ }; name = Debug; }; - 8F0B92FB18A57B370BAEDBF212E77B0A /* Release */ = { + 9669D2FC1FEC5C37C0500815A8CFF6B8 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 1D774D8146EBC82B4A77204A273761B8 /* Pods-CustomKeyboard.release.xcconfig */; + baseConfigurationReference = A6E8FF241173D596A21D4D4B7D86A810 /* Pods-keyBoard.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; CLANG_ENABLE_OBJC_WEAK = NO; @@ -2559,7 +3678,7 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = NO; ENABLE_USER_SCRIPT_SANDBOXING = NO; - INFOPLIST_FILE = "Target Support Files/Pods-CustomKeyboard/Pods-CustomKeyboard-Info.plist"; + 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 = ( @@ -2568,7 +3687,7 @@ "@loader_path/Frameworks", ); MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-CustomKeyboard/Pods-CustomKeyboard.modulemap"; + MODULEMAP_FILE = "Target Support Files/Pods-keyBoard/Pods-keyBoard.modulemap"; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; @@ -2583,16 +3702,16 @@ }; name = Release; }; - 91762687457A2879115FDE4E6963488E /* Release */ = { + 9C1EE0C94CDE25779693BCA7261B5989 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = DF80C56AF1D41887B8622FAC95138810 /* MJRefresh.release.xcconfig */; + baseConfigurationReference = 0C31E11F6B40D55EB650013FAC1B59C0 /* SDWebImage.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; + 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"; @@ -2664,7 +3783,7 @@ }; 9E9FB1E032B56896F9380263D45A0F9A /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 4B22EE0B7D2C1D1066750C4AB84FDA27 /* MJExtension.release.xcconfig */; + baseConfigurationReference = 3E2A55F2F78E11DEDCF2FA119B3E1912 /* MJExtension.release.xcconfig */; buildSettings = { CLANG_ENABLE_OBJC_WEAK = NO; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -2703,7 +3822,7 @@ }; 9F519E5162C0E51D10B7E999E2FD0125 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 25119C155F0BB240A5DDFB8155627C04 /* SDWebImage.release.xcconfig */; + baseConfigurationReference = 0C31E11F6B40D55EB650013FAC1B59C0 /* SDWebImage.release.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -2741,7 +3860,7 @@ }; B04295D726C1883ADA40A304483D7E33 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 20B1DAD84F32D1AF296F0D63C5DEE9AB /* SDWebImage.debug.xcconfig */; + baseConfigurationReference = 5998234B9DD3C83BCD1DE88EDDEA5DF6 /* SDWebImage.debug.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -2778,7 +3897,7 @@ }; B26FBB655ABB114E4C0D589843814D6C /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 6134DA50CBB0F618C7502B9B4E23963F /* Bugly.release.xcconfig */; + baseConfigurationReference = 8C9727D0D56A9017D437CA50176F0474 /* Bugly.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; @@ -2794,12 +3913,27 @@ }; name = Release; }; - BDDCA6E1F27BB61FB8D92F4302765543 /* Debug */ = { + B83818605FEB0030D2B6D7FF64325A19 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 0D6215D1BCCE125B8DF73E38013CBBDC /* Pods-CustomKeyboard.debug.xcconfig */; + baseConfigurationReference = D2BBA8DCCC9E2658211368C22BE1B033 /* 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; + }; + BCD70A0BB22D0C72BAF7207A7D4F44BD /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 2940A878AE956B2190BA5A68D63DC5AD /* MBProgressHUD.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*]" = ""; @@ -2810,32 +3944,70 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = NO; ENABLE_USER_SCRIPT_SANDBOXING = NO; - INFOPLIST_FILE = "Target Support Files/Pods-CustomKeyboard/Pods-CustomKeyboard-Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/MBProgressHUD/MBProgressHUD-prefix.pch"; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = "Target Support Files/MBProgressHUD/MBProgressHUD-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-CustomKeyboard/Pods-CustomKeyboard.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/MBProgressHUD/MBProgressHUD.modulemap"; + PRODUCT_MODULE_NAME = MBProgressHUD; + PRODUCT_NAME = MBProgressHUD; 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 */; + 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/MBProgressHUD/MBProgressHUD-prefix.pch"; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = "Target Support Files/MBProgressHUD/MBProgressHUD-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/MBProgressHUD/MBProgressHUD.modulemap"; + PRODUCT_MODULE_NAME = MBProgressHUD; + PRODUCT_NAME = MBProgressHUD; + 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; + }; CBAFED52B4B51F600FAF2141BA449F2E /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 4CD2E3B8C4EBAB8CE1F46D4D7B1B5CAA /* Bugly.debug.xcconfig */; + baseConfigurationReference = 18DB01964CBE026F2E6511875E1A98E2 /* Bugly.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; @@ -2852,7 +4024,7 @@ }; CEE7FEC0A1B23DE7053203A448EEB294 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 78744B8D1235EE30BFB429D8C13D63F4 /* AFNetworking.debug.xcconfig */; + baseConfigurationReference = 5104591E28208BB976FFAD3D7AFA2F58 /* AFNetworking.debug.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -2889,7 +4061,7 @@ }; D0AB0AEF4014B926FCD853D3AE0A370A /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 396F4E7921EA26CDE8AAEADDD8CFBB49 /* Masonry.release.xcconfig */; + baseConfigurationReference = F53F6F5B0D7E0FF60505964233E5C608 /* Masonry.release.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -2927,7 +4099,7 @@ }; DA533AA9B577872DAFB44EF2CF26C49A /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 23D6F4D8D5B6512D7A50FF1054426C09 /* AFNetworking.release.xcconfig */; + baseConfigurationReference = C6F66997EF28E05B21EB7F13B379645A /* AFNetworking.release.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -2963,26 +4135,9 @@ }; name = Release; }; - E41C0991D6353467CA87E00582A5976C /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 25119C155F0BB240A5DDFB8155627C04 /* 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; - }; EC66105EE15F9DC9B6F20F58FB67957D /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 3316E3BF456739AB7A0F0FD1920F5F6B /* MJExtension.debug.xcconfig */; + baseConfigurationReference = 57BCCC946B3042A20D0C8F15D69FF943 /* MJExtension.debug.xcconfig */; buildSettings = { CLANG_ENABLE_OBJC_WEAK = NO; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -3018,9 +4173,44 @@ }; name = Debug; }; + FE5AD58E2A362D4BD062D63BEF049BC0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 45EDC4788D38048F75B7F3CD0BEF1783 /* 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; + }; /* 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 = ( + 35044A57510DB3F4E442A9C16E980E4A /* Debug */, + 49CEA33268972C89BF290FCBF8F9DFC0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 29BB59B7B51BC6194771995E3356CF70 /* Build configuration list for PBXNativeTarget "MJRefresh" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -3039,24 +4229,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 3A3BFFB46D4AE092AC96BD3D9D624546 /* Build configuration list for PBXNativeTarget "SDWebImage-SDWebImage" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 16DD238F86190BFED9FB2F16A83B2A56 /* Debug */, - E41C0991D6353467CA87E00582A5976C /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 4650649B39AEE2A0C6FEE8FF9B18E065 /* Build configuration list for PBXNativeTarget "MJExtension-MJExtension" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 5B8933506DB0D0650A36E47F8AB90C24 /* Debug */, - 03A5A25907B9F099CB1930F2C4AA0E3F /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -3075,11 +4247,11 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 68B32BA86F0CEE6E06F49B0F2C62CD73 /* Build configuration list for PBXNativeTarget "MJRefresh-MJRefresh.Privacy" */ = { + 782EAA470306AEE25A91F4D884D6AD6E /* Build configuration list for PBXNativeTarget "Pods-keyBoard" */ = { isa = XCConfigurationList; buildConfigurations = ( - 0A6B03880AA76C2476846FABA9DAB99A /* Debug */, - 91762687457A2879115FDE4E6963488E /* Release */, + 1D73A0661FBB5E8564C1FE75B669DC24 /* Debug */, + 9669D2FC1FEC5C37C0500815A8CFF6B8 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -3093,6 +4265,24 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 945C0F2B41CBADE68A142120AE9A4AF3 /* Build configuration list for PBXNativeTarget "MBProgressHUD" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + BCD70A0BB22D0C72BAF7207A7D4F44BD /* Debug */, + BE0CDEB7BE0A402663AFCC2111742430 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 95B0FCBEC38B41A89EDFDA2284E4CF2F /* Build configuration list for PBXNativeTarget "MJExtension-MJExtension" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 427CF48FABE82C6FC8208160FDF4A9CE /* Debug */, + 532B03D3A70665C5D6CA2E785045C97B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 9CC7AA793D9397C15E010F8242EE1046 /* Build configuration list for PBXAggregateTarget "Bugly" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -3111,20 +4301,29 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - DA39DBDB0F7D05D976CC7C6A67459F5F /* Build configuration list for PBXNativeTarget "Pods-CustomKeyboard" */ = { + B1224CED7ED3E4B356E8F429D6C62F7E /* Build configuration list for PBXNativeTarget "Pods-CustomKeyboard" */ = { isa = XCConfigurationList; buildConfigurations = ( - BDDCA6E1F27BB61FB8D92F4302765543 /* Debug */, - 8F0B92FB18A57B370BAEDBF212E77B0A /* Release */, + 7BB5AE2225500DE9658B6277FED45BCD /* Debug */, + 227E6E64001CE57ED070BAB9C31DCAEC /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - FCE3E8712CE5CB67BC702E493D7E2243 /* Build configuration list for PBXNativeTarget "Pods-keyBoard" */ = { + E1B78FF12090122B97AE1A33AD172B8C /* Build configuration list for PBXNativeTarget "SDWebImage-SDWebImage" */ = { isa = XCConfigurationList; buildConfigurations = ( - 4CF8CD0C5349DA6326EF3FCF43C53402 /* Debug */, - 5EB0D7D4CF48681DA30DD58C2E33B044 /* Release */, + 50BA0438712A00B9F9ECCE17AD68D287 /* Debug */, + 9C1EE0C94CDE25779693BCA7261B5989 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E7624967EDC883D80ED3DA81C495736B /* Build configuration list for PBXNativeTarget "LookinServer" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 618AB008538F74AAF983C04297207BB6 /* Debug */, + 1A69165A21A7A1CC42A38CF8ADE98215 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/DZNEmptyDataSet.xcscheme b/Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/DZNEmptyDataSet.xcscheme new file mode 100644 index 0000000..d7058cf --- /dev/null +++ b/Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/DZNEmptyDataSet.xcscheme @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/LookinServer.xcscheme b/Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/LookinServer.xcscheme new file mode 100644 index 0000000..a0dc613 --- /dev/null +++ b/Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/LookinServer.xcscheme @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/MBProgressHUD.xcscheme b/Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/MBProgressHUD.xcscheme new file mode 100644 index 0000000..b16f8c7 --- /dev/null +++ b/Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/MBProgressHUD.xcscheme @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pods/Target Support Files/AFNetworking/AFNetworking.debug.xcconfig b/Pods/Target Support Files/AFNetworking/AFNetworking.debug.xcconfig index 1300513..c2fa64b 100644 --- a/Pods/Target Support Files/AFNetworking/AFNetworking.debug.xcconfig +++ b/Pods/Target Support Files/AFNetworking/AFNetworking.debug.xcconfig @@ -1,3 +1,4 @@ +APPLICATION_EXTENSION_API_ONLY = YES CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 diff --git a/Pods/Target Support Files/AFNetworking/AFNetworking.release.xcconfig b/Pods/Target Support Files/AFNetworking/AFNetworking.release.xcconfig index 1300513..c2fa64b 100644 --- a/Pods/Target Support Files/AFNetworking/AFNetworking.release.xcconfig +++ b/Pods/Target Support Files/AFNetworking/AFNetworking.release.xcconfig @@ -1,3 +1,4 @@ +APPLICATION_EXTENSION_API_ONLY = YES CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 diff --git a/Pods/Target Support Files/DZNEmptyDataSet/DZNEmptyDataSet-Info.plist b/Pods/Target Support Files/DZNEmptyDataSet/DZNEmptyDataSet-Info.plist new file mode 100644 index 0000000..e446dd0 --- /dev/null +++ b/Pods/Target Support Files/DZNEmptyDataSet/DZNEmptyDataSet-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.8.1 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Pods/Target Support Files/DZNEmptyDataSet/DZNEmptyDataSet-dummy.m b/Pods/Target Support Files/DZNEmptyDataSet/DZNEmptyDataSet-dummy.m new file mode 100644 index 0000000..9166203 --- /dev/null +++ b/Pods/Target Support Files/DZNEmptyDataSet/DZNEmptyDataSet-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_DZNEmptyDataSet : NSObject +@end +@implementation PodsDummy_DZNEmptyDataSet +@end diff --git a/Pods/Target Support Files/DZNEmptyDataSet/DZNEmptyDataSet-prefix.pch b/Pods/Target Support Files/DZNEmptyDataSet/DZNEmptyDataSet-prefix.pch new file mode 100644 index 0000000..beb2a24 --- /dev/null +++ b/Pods/Target Support Files/DZNEmptyDataSet/DZNEmptyDataSet-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/DZNEmptyDataSet/DZNEmptyDataSet-umbrella.h b/Pods/Target Support Files/DZNEmptyDataSet/DZNEmptyDataSet-umbrella.h new file mode 100644 index 0000000..3015560 --- /dev/null +++ b/Pods/Target Support Files/DZNEmptyDataSet/DZNEmptyDataSet-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 "UIScrollView+EmptyDataSet.h" + +FOUNDATION_EXPORT double DZNEmptyDataSetVersionNumber; +FOUNDATION_EXPORT const unsigned char DZNEmptyDataSetVersionString[]; + diff --git a/Pods/Target Support Files/DZNEmptyDataSet/DZNEmptyDataSet.debug.xcconfig b/Pods/Target Support Files/DZNEmptyDataSet/DZNEmptyDataSet.debug.xcconfig new file mode 100644 index 0000000..af03d2b --- /dev/null +++ b/Pods/Target Support Files/DZNEmptyDataSet/DZNEmptyDataSet.debug.xcconfig @@ -0,0 +1,14 @@ +APPLICATION_EXTENSION_API_ONLY = YES +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = $(inherited) -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}/DZNEmptyDataSet +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/DZNEmptyDataSet/DZNEmptyDataSet.modulemap b/Pods/Target Support Files/DZNEmptyDataSet/DZNEmptyDataSet.modulemap new file mode 100644 index 0000000..854066e --- /dev/null +++ b/Pods/Target Support Files/DZNEmptyDataSet/DZNEmptyDataSet.modulemap @@ -0,0 +1,6 @@ +framework module DZNEmptyDataSet { + umbrella header "DZNEmptyDataSet-umbrella.h" + + export * + module * { export * } +} diff --git a/Pods/Target Support Files/DZNEmptyDataSet/DZNEmptyDataSet.release.xcconfig b/Pods/Target Support Files/DZNEmptyDataSet/DZNEmptyDataSet.release.xcconfig new file mode 100644 index 0000000..af03d2b --- /dev/null +++ b/Pods/Target Support Files/DZNEmptyDataSet/DZNEmptyDataSet.release.xcconfig @@ -0,0 +1,14 @@ +APPLICATION_EXTENSION_API_ONLY = YES +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = $(inherited) -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}/DZNEmptyDataSet +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/LookinServer/LookinServer-Info.plist b/Pods/Target Support Files/LookinServer/LookinServer-Info.plist new file mode 100644 index 0000000..eafed42 --- /dev/null +++ b/Pods/Target Support Files/LookinServer/LookinServer-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.2.8 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Pods/Target Support Files/LookinServer/LookinServer-dummy.m b/Pods/Target Support Files/LookinServer/LookinServer-dummy.m new file mode 100644 index 0000000..f86bacf --- /dev/null +++ b/Pods/Target Support Files/LookinServer/LookinServer-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_LookinServer : NSObject +@end +@implementation PodsDummy_LookinServer +@end diff --git a/Pods/Target Support Files/LookinServer/LookinServer-prefix.pch b/Pods/Target Support Files/LookinServer/LookinServer-prefix.pch new file mode 100644 index 0000000..beb2a24 --- /dev/null +++ b/Pods/Target Support Files/LookinServer/LookinServer-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/LookinServer/LookinServer-umbrella.h b/Pods/Target Support Files/LookinServer/LookinServer-umbrella.h new file mode 100644 index 0000000..a3dddb0 --- /dev/null +++ b/Pods/Target Support Files/LookinServer/LookinServer-umbrella.h @@ -0,0 +1,87 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "CALayer+LookinServer.h" +#import "NSObject+LookinServer.h" +#import "UIBlurEffect+LookinServer.h" +#import "UIColor+LookinServer.h" +#import "UIImage+LookinServer.h" +#import "UIImageView+LookinServer.h" +#import "UILabel+LookinServer.h" +#import "UITableView+LookinServer.h" +#import "UITextField+LookinServer.h" +#import "UITextView+LookinServer.h" +#import "UIView+LookinServer.h" +#import "UIViewController+LookinServer.h" +#import "UIVisualEffectView+LookinServer.h" +#import "LKS_ConnectionManager.h" +#import "LKS_RequestHandler.h" +#import "LKS_AttrModificationPatchHandler.h" +#import "LKS_CustomAttrModificationHandler.h" +#import "LKS_HierarchyDetailsHandler.h" +#import "LKS_InbuiltAttrModificationHandler.h" +#import "LookinServer.h" +#import "LKSConfigManager.h" +#import "LKS_AttrGroupsMaker.h" +#import "LKS_CustomAttrGroupsMaker.h" +#import "LKS_CustomAttrSetterManager.h" +#import "LKS_CustomDisplayItemsMaker.h" +#import "LKS_EventHandlerMaker.h" +#import "LKS_ExportManager.h" +#import "LKS_GestureTargetActionsSearcher.h" +#import "LKS_Helper.h" +#import "LKS_HierarchyDisplayItemsMaker.h" +#import "LKS_MultiplatformAdapter.h" +#import "LKS_ObjectRegistry.h" +#import "LKS_TraceManager.h" +#import "LookinServerDefines.h" +#import "CALayer+Lookin.h" +#import "Color+Lookin.h" +#import "Image+Lookin.h" +#import "NSArray+Lookin.h" +#import "NSObject+Lookin.h" +#import "NSSet+Lookin.h" +#import "NSString+Lookin.h" +#import "LookinAppInfo.h" +#import "LookinAttribute.h" +#import "LookinAttributeModification.h" +#import "LookinAttributesGroup.h" +#import "LookinAttributesSection.h" +#import "LookinAttrIdentifiers.h" +#import "LookinAttrType.h" +#import "LookinAutoLayoutConstraint.h" +#import "LookinCodingValueType.h" +#import "LookinConnectionAttachment.h" +#import "LookinConnectionResponseAttachment.h" +#import "LookinCustomAttrModification.h" +#import "LookinCustomDisplayItemInfo.h" +#import "LookinDashboardBlueprint.h" +#import "LookinDefines.h" +#import "LookinDisplayItem.h" +#import "LookinDisplayItemDetail.h" +#import "LookinEventHandler.h" +#import "LookinHierarchyFile.h" +#import "LookinHierarchyInfo.h" +#import "LookinObject.h" +#import "LookinStaticAsyncUpdateTask.h" +#import "LookinTuple.h" +#import "LookinWeakContainer.h" +#import "Lookin_PTChannel.h" +#import "Lookin_PTPrivate.h" +#import "Lookin_PTProtocol.h" +#import "Lookin_PTUSBHub.h" +#import "Peertalk.h" +#import "LookinIvarTrace.h" + +FOUNDATION_EXPORT double LookinServerVersionNumber; +FOUNDATION_EXPORT const unsigned char LookinServerVersionString[]; + diff --git a/Pods/Target Support Files/LookinServer/LookinServer.debug.xcconfig b/Pods/Target Support Files/LookinServer/LookinServer.debug.xcconfig new file mode 100644 index 0000000..4b85527 --- /dev/null +++ b/Pods/Target Support Files/LookinServer/LookinServer.debug.xcconfig @@ -0,0 +1,14 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/LookinServer +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) SHOULD_COMPILE_LOOKIN_SERVER=1 +OTHER_LDFLAGS = $(inherited) -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}/LookinServer +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +SWIFT_ACTIVE_COMPILATION_CONDITIONS = $(inherited) SHOULD_COMPILE_LOOKIN_SERVER +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Pods/Target Support Files/LookinServer/LookinServer.modulemap b/Pods/Target Support Files/LookinServer/LookinServer.modulemap new file mode 100644 index 0000000..96c186b --- /dev/null +++ b/Pods/Target Support Files/LookinServer/LookinServer.modulemap @@ -0,0 +1,6 @@ +framework module LookinServer { + umbrella header "LookinServer-umbrella.h" + + export * + module * { export * } +} diff --git a/Pods/Target Support Files/LookinServer/LookinServer.release.xcconfig b/Pods/Target Support Files/LookinServer/LookinServer.release.xcconfig new file mode 100644 index 0000000..4b85527 --- /dev/null +++ b/Pods/Target Support Files/LookinServer/LookinServer.release.xcconfig @@ -0,0 +1,14 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/LookinServer +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) SHOULD_COMPILE_LOOKIN_SERVER=1 +OTHER_LDFLAGS = $(inherited) -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}/LookinServer +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +SWIFT_ACTIVE_COMPILATION_CONDITIONS = $(inherited) SHOULD_COMPILE_LOOKIN_SERVER +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Pods/Target Support Files/MBProgressHUD/MBProgressHUD-Info.plist b/Pods/Target Support Files/MBProgressHUD/MBProgressHUD-Info.plist new file mode 100644 index 0000000..c2e6784 --- /dev/null +++ b/Pods/Target Support Files/MBProgressHUD/MBProgressHUD-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.2.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Pods/Target Support Files/MBProgressHUD/MBProgressHUD-dummy.m b/Pods/Target Support Files/MBProgressHUD/MBProgressHUD-dummy.m new file mode 100644 index 0000000..67a74df --- /dev/null +++ b/Pods/Target Support Files/MBProgressHUD/MBProgressHUD-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_MBProgressHUD : NSObject +@end +@implementation PodsDummy_MBProgressHUD +@end diff --git a/Pods/Target Support Files/MBProgressHUD/MBProgressHUD-prefix.pch b/Pods/Target Support Files/MBProgressHUD/MBProgressHUD-prefix.pch new file mode 100644 index 0000000..beb2a24 --- /dev/null +++ b/Pods/Target Support Files/MBProgressHUD/MBProgressHUD-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/MBProgressHUD/MBProgressHUD-umbrella.h b/Pods/Target Support Files/MBProgressHUD/MBProgressHUD-umbrella.h new file mode 100644 index 0000000..8522a01 --- /dev/null +++ b/Pods/Target Support Files/MBProgressHUD/MBProgressHUD-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 "MBProgressHUD.h" + +FOUNDATION_EXPORT double MBProgressHUDVersionNumber; +FOUNDATION_EXPORT const unsigned char MBProgressHUDVersionString[]; + diff --git a/Pods/Target Support Files/MBProgressHUD/MBProgressHUD.debug.xcconfig b/Pods/Target Support Files/MBProgressHUD/MBProgressHUD.debug.xcconfig new file mode 100644 index 0000000..1420ca0 --- /dev/null +++ b/Pods/Target Support Files/MBProgressHUD/MBProgressHUD.debug.xcconfig @@ -0,0 +1,14 @@ +APPLICATION_EXTENSION_API_ONLY = YES +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = $(inherited) -framework "CoreGraphics" -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}/MBProgressHUD +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/MBProgressHUD/MBProgressHUD.modulemap b/Pods/Target Support Files/MBProgressHUD/MBProgressHUD.modulemap new file mode 100644 index 0000000..dbb3f94 --- /dev/null +++ b/Pods/Target Support Files/MBProgressHUD/MBProgressHUD.modulemap @@ -0,0 +1,6 @@ +framework module MBProgressHUD { + umbrella header "MBProgressHUD-umbrella.h" + + export * + module * { export * } +} diff --git a/Pods/Target Support Files/MBProgressHUD/MBProgressHUD.release.xcconfig b/Pods/Target Support Files/MBProgressHUD/MBProgressHUD.release.xcconfig new file mode 100644 index 0000000..1420ca0 --- /dev/null +++ b/Pods/Target Support Files/MBProgressHUD/MBProgressHUD.release.xcconfig @@ -0,0 +1,14 @@ +APPLICATION_EXTENSION_API_ONLY = YES +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = $(inherited) -framework "CoreGraphics" -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}/MBProgressHUD +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/MJExtension/MJExtension.debug.xcconfig b/Pods/Target Support Files/MJExtension/MJExtension.debug.xcconfig index 7f94d90..f93d497 100644 --- a/Pods/Target Support Files/MJExtension/MJExtension.debug.xcconfig +++ b/Pods/Target Support Files/MJExtension/MJExtension.debug.xcconfig @@ -1,3 +1,4 @@ +APPLICATION_EXTENSION_API_ONLY = YES CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/MJExtension GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 diff --git a/Pods/Target Support Files/MJExtension/MJExtension.release.xcconfig b/Pods/Target Support Files/MJExtension/MJExtension.release.xcconfig index 7f94d90..f93d497 100644 --- a/Pods/Target Support Files/MJExtension/MJExtension.release.xcconfig +++ b/Pods/Target Support Files/MJExtension/MJExtension.release.xcconfig @@ -1,3 +1,4 @@ +APPLICATION_EXTENSION_API_ONLY = YES CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/MJExtension GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 diff --git a/Pods/Target Support Files/Masonry/Masonry.debug.xcconfig b/Pods/Target Support Files/Masonry/Masonry.debug.xcconfig index 233437f..a9f80ee 100644 --- a/Pods/Target Support Files/Masonry/Masonry.debug.xcconfig +++ b/Pods/Target Support Files/Masonry/Masonry.debug.xcconfig @@ -1,3 +1,4 @@ +APPLICATION_EXTENSION_API_ONLY = YES CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Masonry GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 diff --git a/Pods/Target Support Files/Masonry/Masonry.release.xcconfig b/Pods/Target Support Files/Masonry/Masonry.release.xcconfig index 233437f..a9f80ee 100644 --- a/Pods/Target Support Files/Masonry/Masonry.release.xcconfig +++ b/Pods/Target Support Files/Masonry/Masonry.release.xcconfig @@ -1,3 +1,4 @@ +APPLICATION_EXTENSION_API_ONLY = YES CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Masonry GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 diff --git a/Pods/Target Support Files/Pods-CustomKeyboard/Pods-CustomKeyboard-acknowledgements.markdown b/Pods/Target Support Files/Pods-CustomKeyboard/Pods-CustomKeyboard-acknowledgements.markdown index 102af75..91a0011 100644 --- a/Pods/Target Support Files/Pods-CustomKeyboard/Pods-CustomKeyboard-acknowledgements.markdown +++ b/Pods/Target Support Files/Pods-CustomKeyboard/Pods-CustomKeyboard-acknowledgements.markdown @@ -1,3 +1,106 @@ # Acknowledgements This application makes use of the following third party libraries: + +## AFNetworking + +Copyright (c) 2011-2020 Alamofire Software Foundation (http://alamofire.org/) + +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. + + +## DZNEmptyDataSet + +The MIT License (MIT) + +Copyright (c) 2016 Ignacio Romero Zurbuchen iromero@dzen.cl + +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. + + +## MBProgressHUD + +Copyright © 2009-2020 Matej Bukovinski + +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. + +## MJExtension + +Copyright (c) 2013-2019 MJExtension (https://github.com/CoderMJLee/MJExtension) + +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. + + +## Masonry + +Copyright (c) 2011-2012 Masonry Team - https://github.com/Masonry + +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. Generated by CocoaPods - https://cocoapods.org diff --git a/Pods/Target Support Files/Pods-CustomKeyboard/Pods-CustomKeyboard-acknowledgements.plist b/Pods/Target Support Files/Pods-CustomKeyboard/Pods-CustomKeyboard-acknowledgements.plist index 7acbad1..d17d9dd 100644 --- a/Pods/Target Support Files/Pods-CustomKeyboard/Pods-CustomKeyboard-acknowledgements.plist +++ b/Pods/Target Support Files/Pods-CustomKeyboard/Pods-CustomKeyboard-acknowledgements.plist @@ -12,6 +12,139 @@ Type PSGroupSpecifier + + FooterText + Copyright (c) 2011-2020 Alamofire Software Foundation (http://alamofire.org/) + +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 + AFNetworking + Type + PSGroupSpecifier + + + FooterText + The MIT License (MIT) + +Copyright (c) 2016 Ignacio Romero Zurbuchen iromero@dzen.cl + +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 + DZNEmptyDataSet + Type + PSGroupSpecifier + + + FooterText + Copyright © 2009-2020 Matej Bukovinski + +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 + MBProgressHUD + Type + PSGroupSpecifier + + + FooterText + Copyright (c) 2013-2019 MJExtension (https://github.com/CoderMJLee/MJExtension) + +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 + MJExtension + Type + PSGroupSpecifier + + + FooterText + Copyright (c) 2011-2012 Masonry Team - https://github.com/Masonry + +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 + Masonry + Type + PSGroupSpecifier + FooterText Generated by CocoaPods - https://cocoapods.org diff --git a/Pods/Target Support Files/Pods-CustomKeyboard/Pods-CustomKeyboard.debug.xcconfig b/Pods/Target Support Files/Pods-CustomKeyboard/Pods-CustomKeyboard.debug.xcconfig index 26f2c77..ebe87d3 100644 --- a/Pods/Target Support Files/Pods-CustomKeyboard/Pods-CustomKeyboard.debug.xcconfig +++ b/Pods/Target Support Files/Pods-CustomKeyboard/Pods-CustomKeyboard.debug.xcconfig @@ -1,5 +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}/Masonry" 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}/Masonry/Masonry.framework/Headers" +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' '@executable_path/../../Frameworks' +OTHER_LDFLAGS = $(inherited) -framework "AFNetworking" -framework "CoreGraphics" -framework "DZNEmptyDataSet" -framework "Foundation" -framework "MBProgressHUD" -framework "MJExtension" -framework "Masonry" -framework "QuartzCore" -framework "UIKit" +OTHER_MODULE_VERIFIER_FLAGS = $(inherited) "-F${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "-F${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet" "-F${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "-F${PODS_CONFIGURATION_BUILD_DIR}/MJExtension" "-F${PODS_CONFIGURATION_BUILD_DIR}/Masonry" 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-CustomKeyboard/Pods-CustomKeyboard.release.xcconfig b/Pods/Target Support Files/Pods-CustomKeyboard/Pods-CustomKeyboard.release.xcconfig index 26f2c77..ebe87d3 100644 --- a/Pods/Target Support Files/Pods-CustomKeyboard/Pods-CustomKeyboard.release.xcconfig +++ b/Pods/Target Support Files/Pods-CustomKeyboard/Pods-CustomKeyboard.release.xcconfig @@ -1,5 +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}/Masonry" 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}/Masonry/Masonry.framework/Headers" +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' '@executable_path/../../Frameworks' +OTHER_LDFLAGS = $(inherited) -framework "AFNetworking" -framework "CoreGraphics" -framework "DZNEmptyDataSet" -framework "Foundation" -framework "MBProgressHUD" -framework "MJExtension" -framework "Masonry" -framework "QuartzCore" -framework "UIKit" +OTHER_MODULE_VERIFIER_FLAGS = $(inherited) "-F${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "-F${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet" "-F${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "-F${PODS_CONFIGURATION_BUILD_DIR}/MJExtension" "-F${PODS_CONFIGURATION_BUILD_DIR}/Masonry" 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-acknowledgements.markdown b/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard-acknowledgements.markdown index 7de4a89..50a280f 100644 --- a/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard-acknowledgements.markdown +++ b/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard-acknowledgements.markdown @@ -29,6 +29,65 @@ THE SOFTWARE. Copyright (C) 2017 Tencent Bugly, Inc. All rights reserved. +## DZNEmptyDataSet + +The MIT License (MIT) + +Copyright (c) 2016 Ignacio Romero Zurbuchen iromero@dzen.cl + +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 + +Copyright (c) [2023] [LI KAI] + +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. + +## MBProgressHUD + +Copyright © 2009-2020 Matej Bukovinski + +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. + ## MJExtension Copyright (c) 2013-2019 MJExtension (https://github.com/CoderMJLee/MJExtension) 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 fd6aa88..37285fe 100644 --- a/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard-acknowledgements.plist +++ b/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard-acknowledgements.plist @@ -52,6 +52,83 @@ THE SOFTWARE. Type PSGroupSpecifier + + FooterText + The MIT License (MIT) + +Copyright (c) 2016 Ignacio Romero Zurbuchen iromero@dzen.cl + +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 + DZNEmptyDataSet + Type + PSGroupSpecifier + + + FooterText + MIT License + +Copyright (c) [2023] [LI KAI] + +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 + GPL-3.0 + Title + LookinServer + Type + PSGroupSpecifier + + + FooterText + Copyright © 2009-2020 Matej Bukovinski + +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 + MBProgressHUD + Type + PSGroupSpecifier + FooterText Copyright (c) 2013-2019 MJExtension (https://github.com/CoderMJLee/MJExtension) 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 06b5aa0..fd18c4b 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,5 +1,8 @@ ${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}/LookinServer/LookinServer.framework +${BUILT_PRODUCTS_DIR}/MBProgressHUD/MBProgressHUD.framework ${BUILT_PRODUCTS_DIR}/MJExtension/MJExtension.framework ${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework ${BUILT_PRODUCTS_DIR}/Masonry/Masonry.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 66a1534..9d28c83 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,4 +1,7 @@ ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AFNetworking.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DZNEmptyDataSet.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 ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MJRefresh.framework ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Masonry.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 06b5aa0..1b381a7 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,5 +1,7 @@ ${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}/MBProgressHUD/MBProgressHUD.framework ${BUILT_PRODUCTS_DIR}/MJExtension/MJExtension.framework ${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework ${BUILT_PRODUCTS_DIR}/Masonry/Masonry.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 66a1534..80f5e3c 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,4 +1,6 @@ ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AFNetworking.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DZNEmptyDataSet.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 ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Masonry.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 b731e30..39e15c2 100755 --- a/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard-frameworks.sh +++ b/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard-frameworks.sh @@ -177,6 +177,9 @@ 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}/LookinServer/LookinServer.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" install_framework "${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework" @@ -184,6 +187,8 @@ if [[ "$CONFIGURATION" == "Debug" ]]; then 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}/MBProgressHUD/MBProgressHUD.framework" install_framework "${BUILT_PRODUCTS_DIR}/MJExtension/MJExtension.framework" install_framework "${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework" install_framework "${BUILT_PRODUCTS_DIR}/Masonry/Masonry.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 2e2ca3c..59c94b4 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}/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}/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" "${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}/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}/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) -ObjC -l"c++" -l"z" -framework "AFNetworking" -framework "Bugly" -framework "Foundation" -framework "ImageIO" -framework "MJExtension" -framework "MJRefresh" -framework "Masonry" -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}/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 "Foundation" -framework "ImageIO" -framework "LookinServer" -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}/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 2e2ca3c..8547576 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}/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}/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}/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}/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 "Foundation" -framework "ImageIO" -framework "MJExtension" -framework "MJRefresh" -framework "Masonry" -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}/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 "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" 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/KBAuthManager.h b/Shared/KBAuthManager.h new file mode 100644 index 0000000..b43bf2b --- /dev/null +++ b/Shared/KBAuthManager.h @@ -0,0 +1,56 @@ +// +// KBAuthManager.h +// 主 App 与键盘扩展共享使用 +// +// 通过 Keychain Sharing 统一管理用户登录态(access/refresh token)。 +// 线程安全;在保存/清空时同时发送进程内通知与 Darwin 跨进程通知, +// 以便键盘扩展正运行在其他 App 时也能及时感知变更。 +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// Darwin 跨进程通知名称:当令牌更新或清除时发送,用于提示 App/扩展刷新缓存。 +extern NSString * const kKBDarwinAuthChanged; + +/// 进程内通知(NSNotificationCenter):令牌更新或清除时发送。 +extern NSNotificationName const KBAuthChangedNotification; + +/// 简单的会话容器;可按需扩展字段。 +@interface KBAuthSession : NSObject +@property (nonatomic, copy, nullable) NSString *accessToken; +@property (nonatomic, copy, nullable) NSString *refreshToken; +@property (nonatomic, strong, nullable) NSDate *expiryDate; // 可选:过期时间 +@property (nonatomic, copy, nullable) NSString *userIdentifier; // 可选:如“用 Apple 登录”的 userIdentifier +@end + +/// 基于“共享钥匙串”的鉴权管理器(使用 Keychain Sharing 访问组)。 +@interface KBAuthManager : NSObject + ++ (instancetype)shared; + +/// 当前会话(内存缓存),在加载/保存/清除后更新。 +@property (atomic, strong, readonly, nullable) KBAuthSession *current; + +/// 是否已登录:存在 accessToken 且未明显过期(未设置过期时间则只要有 token 即视为已登录)。 +- (BOOL)isLoggedIn; + +/// 从钥匙串加载到内存;通常首次访问时会自动加载。 +- (void)reloadFromKeychain; + +/// 保存令牌到“共享钥匙串”并通知观察者。 +- (BOOL)saveAccessToken:(NSString *)accessToken + refreshToken:(nullable NSString *)refreshToken + expiryDate:(nullable NSDate *)expiryDate + userIdentifier:(nullable NSString *)userIdentifier; + +/// 从钥匙串与内存中清除令牌,并通知观察者。 +- (void)signOut; + +/// 便捷方法:若存在有效令牌,返回 `Authorization` 请求头;否则返回空字典。 +- (NSDictionary *)authorizationHeader; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Shared/KBAuthManager.m b/Shared/KBAuthManager.m new file mode 100644 index 0000000..dca7319 --- /dev/null +++ b/Shared/KBAuthManager.m @@ -0,0 +1,211 @@ +// +// KBAuthManager.m +// +// 关键点: +// - 使用固定的 service/account 将 KBAuthSession 序列化后保存到钥匙串; +// - 通过 kSecAttrAccessGroup 指定 Keychain Sharing 访问组,实现 App 与扩展共享; +// - 保存/清除时发送 Darwin 跨进程通知,便于对端刷新缓存; +// + +#import "KBAuthManager.h" +#import +#import "KBConfig.h" // 需要共享钥匙串访问组常量,见 KBConfig.h 中的说明 + +NSString * const kKBDarwinAuthChanged = @"com.keyBoardst.auth.changed"; +NSNotificationName const KBAuthChangedNotification = @"KBAuthChangedNotification"; + +static NSString * const kKBKCService = @"com.keyBoardst.auth"; // 钥匙串 service 名 +static NSString * const kKBKCAccount = @"session"; // 钥匙串 account 键 + +// 用于 Keychain Sharing 的访问组;必须与两个 target 的 entitlements 配置一致。 +// 示例(Capabilities 中勾选 Keychain Sharing 后的值): +// $(AppIdentifierPrefix)com.keyBoardst.shared +// 运行时会被展开为:TN6HHV45BB.com.keyBoardst.shared +#ifndef KB_KEYCHAIN_ACCESS_GROUP +#define KB_KEYCHAIN_ACCESS_GROUP @"TN6HHV45BB.com.keyBoardst.shared" +#endif + +// 过期宽限:若过期时间距离当前 <= 该阈值,则视为已过期。 +static const NSTimeInterval kKBExpiryGrace = 5.0; // 秒 + +@implementation KBAuthSession + ++ (BOOL)supportsSecureCoding { return YES; } + +- (void)encodeWithCoder:(NSCoder *)coder { + [coder encodeObject:self.accessToken forKey:@"accessToken"]; + [coder encodeObject:self.refreshToken forKey:@"refreshToken"]; + [coder encodeObject:self.expiryDate forKey:@"expiryDate"]; + [coder encodeObject:self.userIdentifier forKey:@"userIdentifier"]; +} + +- (instancetype)initWithCoder:(NSCoder *)coder { + if (self = [super init]) { + _accessToken = [coder decodeObjectOfClass:NSString.class forKey:@"accessToken"]; + _refreshToken = [coder decodeObjectOfClass:NSString.class forKey:@"refreshToken"]; + _expiryDate = [coder decodeObjectOfClass:NSDate.class forKey:@"expiryDate"]; + _userIdentifier = [coder decodeObjectOfClass:NSString.class forKey:@"userIdentifier"]; + } + return self; +} + +@end + +@interface KBAuthManager () +@property (atomic, strong, readwrite, nullable) KBAuthSession *current; +@end + +@implementation KBAuthManager + ++ (instancetype)shared { + static KBAuthManager *m; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ m = [KBAuthManager new]; }); + return m; +} + +#if DEBUG +static inline void KBLog(NSString *fmt, ...) { + va_list args; va_start(args, fmt); + NSString *msg = [[NSString alloc] initWithFormat:fmt arguments:args]; + va_end(args); + NSLog(@"[KBAuth] %@", msg); +} +#endif + +- (instancetype)init { + if (self = [super init]) { + [self reloadFromKeychain]; + // 监听 Darwin 跨进程通知(App 与扩展之间) + CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), + (__bridge const void *)(self), + KBAuthDarwinCallback, + (__bridge CFStringRef)kKBDarwinAuthChanged, + NULL, + CFNotificationSuspensionBehaviorDeliverImmediately); + } + return self; +} + +static void KBAuthDarwinCallback(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { + KBAuthManager *self = (__bridge KBAuthManager *)observer; + [self reloadFromKeychain]; +} + +- (void)dealloc { + CFNotificationCenterRemoveObserver(CFNotificationCenterGetDarwinNotifyCenter(), (__bridge const void *)(self), (__bridge CFStringRef)kKBDarwinAuthChanged, NULL); +} + +- (BOOL)isLoggedIn { + KBAuthSession *s = self.current; + if (s.accessToken.length == 0) return NO; + if (!s.expiryDate) return YES; // 未设置过期时间时,只要有 token 即视为已登录 + return ([s.expiryDate timeIntervalSinceNow] > kKBExpiryGrace); +} + +#pragma mark - Public + +- (void)reloadFromKeychain { + NSData *data = [self keychainRead]; + KBAuthSession *session = nil; + if (data.length > 0) { + @try { + session = [NSKeyedUnarchiver unarchivedObjectOfClass:KBAuthSession.class fromData:data error:NULL]; + } @catch (__unused NSException *e) { session = nil; } + } + self.current = session; + [[NSNotificationCenter defaultCenter] postNotificationName:KBAuthChangedNotification object:nil]; // 进程内通知 +} + +- (BOOL)saveAccessToken:(NSString *)accessToken + refreshToken:(NSString *)refreshToken + expiryDate:(NSDate *)expiryDate + userIdentifier:(NSString *)userIdentifier { + KBAuthSession *s = [KBAuthSession new]; + s.accessToken = accessToken ?: @""; + s.refreshToken = refreshToken; + s.expiryDate = expiryDate; + s.userIdentifier = userIdentifier; + + NSError *err = nil; + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:s requiringSecureCoding:YES error:&err]; + if (err || data.length == 0) return NO; + + BOOL ok = [self keychainWrite:data]; + if (ok) { + self.current = s; + // 进程内通知 + [[NSNotificationCenter defaultCenter] postNotificationName:KBAuthChangedNotification object:nil]; + // 跨进程通知(App <-> 扩展) + CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), (__bridge CFStringRef)kKBDarwinAuthChanged, NULL, NULL, true); + } + return ok; +} + +- (void)signOut { + [self keychainDelete]; + self.current = nil; + [[NSNotificationCenter defaultCenter] postNotificationName:KBAuthChangedNotification object:nil]; + CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), (__bridge CFStringRef)kKBDarwinAuthChanged, NULL, NULL, true); +} + +- (NSDictionary *)authorizationHeader { + NSString *t = self.current.accessToken; + if (t.length == 0) return @{}; // 未登录返回空头部 + return @{ @"Authorization": [@"Bearer " stringByAppendingString:t] }; +} + +#pragma mark - Keychain (shared) + +- (NSMutableDictionary *)baseKCQuery { + NSMutableDictionary *q = [@{ (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword, + (__bridge id)kSecAttrService: kKBKCService, + (__bridge id)kSecAttrAccount: kKBKCAccount } mutableCopy]; + // 指定共享访问组(App 与扩展共用同一组) + q[(__bridge id)kSecAttrAccessGroup] = KB_KEYCHAIN_ACCESS_GROUP; + return q; +} + +- (BOOL)keychainWrite:(NSData *)data { + if (!data) return NO; + NSMutableDictionary *query = [self baseKCQuery]; + SecItemDelete((__bridge CFDictionaryRef)query); + + // 设置属性 + query[(__bridge id)kSecValueData] = data; + // 访问控制:设备首次解锁后可读,不随备份迁移 + query[(__bridge id)kSecAttrAccessible] = (__bridge id)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly; + + OSStatus status = SecItemAdd((__bridge CFDictionaryRef)query, NULL); +#if DEBUG + if (status != errSecSuccess) { + KBLog(@"SecItemAdd failed status=%ld group=%@", (long)status, KB_KEYCHAIN_ACCESS_GROUP); + } else { + KBLog(@"SecItemAdd ok group=%@", KB_KEYCHAIN_ACCESS_GROUP); + } +#endif + return (status == errSecSuccess); +} + +- (NSData *)keychainRead { + NSMutableDictionary *query = [self baseKCQuery]; + query[(__bridge id)kSecReturnData] = @YES; + query[(__bridge id)kSecMatchLimit] = (__bridge id)kSecMatchLimitOne; + + CFTypeRef dataRef = NULL; + OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &dataRef); +#if DEBUG + if (status != errSecSuccess) { + KBLog(@"SecItemCopyMatching status=%ld group=%@ (item not found or no entitlement)", (long)status, KB_KEYCHAIN_ACCESS_GROUP); + } else { + KBLog(@"SecItemCopyMatching ok group=%@", KB_KEYCHAIN_ACCESS_GROUP); + } +#endif + if (status != errSecSuccess || !dataRef) return nil; + return (__bridge_transfer NSData *)dataRef; +} + +- (void)keychainDelete { + NSDictionary *query = [self baseKCQuery]; + SecItemDelete((__bridge CFDictionaryRef)query); +} + +@end diff --git a/Shared/KBConfig.h b/Shared/KBConfig.h new file mode 100644 index 0000000..f98849a --- /dev/null +++ b/Shared/KBConfig.h @@ -0,0 +1,44 @@ +// +// KBConfig.h +// 主 App 与键盘扩展共用的配置/宏。 +// +// 在此处修改后,会通过 PCH 被两个 target 同步引用。 +// + +#ifndef KBConfig_h +#define KBConfig_h + +// 基础baseUrl +#ifndef KB_BASE_URL +#define KB_BASE_URL @"https://m1.apifoxmock.com/m1/5438099-5113192-default/" +#endif + +// Universal Links 通用链接 +#ifndef KB_UL_BASE +#define KB_UL_BASE @"https://your.domain/ul" +#endif + +#define KB_UL_LOGIN KB_UL_BASE @"/login" +#define KB_UL_SETTINGS KB_UL_BASE @"/settings" + +#endif /* KBConfig_h */ + +// --- 认证/共享钥匙串 配置 --- +// 若已在 Capabilities 中启用 Keychain Sharing,并添加访问组: +// $(AppIdentifierPrefix)com.keyBoardst.shared +// 运行时会展开为:TN6HHV45BB.com.keyBoardst.shared +// KBAuthManager 通过下面的宏定位访问组;如需修改,可在 Build Settings 或前缀头中覆盖该宏。 +#ifndef KB_KEYCHAIN_ACCESS_GROUP +#define KB_KEYCHAIN_ACCESS_GROUP @"TN6HHV45BB.com.keyBoardst.shared" +#endif + +// 键盘扩展的 Bundle Identifier(用于 App 侧检测是否已添加该键盘) +#ifndef KB_KEYBOARD_EXTENSION_BUNDLE_ID +#define KB_KEYBOARD_EXTENSION_BUNDLE_ID @"com.keyBoardst.CustomKeyboard" +#endif + +// --- 常用宏 --- +// 弱引用 self(在 block 中避免循环引用):使用处直接写 KBWeakSelf; +#ifndef KBWeakSelf +#define KBWeakSelf __weak __typeof(self) weakSelf = self; +#endif diff --git a/Shared/KBKeyboardPermissionManager.h b/Shared/KBKeyboardPermissionManager.h new file mode 100644 index 0000000..5699d56 --- /dev/null +++ b/Shared/KBKeyboardPermissionManager.h @@ -0,0 +1,37 @@ +// +// KBKeyboardPermissionManager.h +// 主 App/键盘扩展 共用的“键盘启用 + 完全访问”权限管理 +// + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSInteger, KBFARecord) { + KBFARecordUnknown = 0, + KBFARecordDenied = 1, + KBFARecordGranted = 2, +}; + +/// 统一权限管理(App 与扩展均可使用) +@interface KBKeyboardPermissionManager : NSObject + ++ (instancetype)shared; + +/// App 侧:是否已添加并启用了自定义键盘(通过遍历 activeInputModes 粗略判断) +- (BOOL)isKeyboardEnabled; + +/// 最后一次由扩展上报的“完全访问”状态(来源:扩展运行后写入共享钥匙串) +- (KBFARecord)lastKnownFullAccess; + +/// 扩展侧:上报“完全访问”状态(写入共享钥匙串,以便 App 读取) +- (void)reportFullAccessFromExtension:(BOOL)granted; + +/// App 侧:若未满足“已启用键盘 + 完全访问(或未知)”则展示引导页(KBPermissionViewController) +- (void)presentPermissionIfNeededFrom:(UIViewController *)presenting; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/Shared/KBKeyboardPermissionManager.m b/Shared/KBKeyboardPermissionManager.m new file mode 100644 index 0000000..b59b23e --- /dev/null +++ b/Shared/KBKeyboardPermissionManager.m @@ -0,0 +1,94 @@ +// +// KBKeyboardPermissionManager.m +// + +#import "KBKeyboardPermissionManager.h" +#import +#import "KBConfig.h" + +// Keychain 存储:记录上次扩展上报的“完全访问”状态 +static NSString * const kKBPermService = @"com.keyBoardst.perm"; +static NSString * const kKBPermAccount = @"full_access"; // 保存一个字节/数字:0/1/2 + +@implementation KBKeyboardPermissionManager + ++ (instancetype)shared { + static KBKeyboardPermissionManager *m; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ m = [KBKeyboardPermissionManager new]; }); + return m; +} + +#pragma mark - App side + +- (BOOL)isKeyboardEnabled { + // 与 AppDelegate 中同思路:遍历 activeInputModes,匹配自家扩展 bundle id + for (UITextInputMode *mode in [UITextInputMode activeInputModes]) { + NSString *identifier = nil; + @try { identifier = [mode valueForKey:@"identifier"]; } @catch (__unused NSException *e) { identifier = nil; } + if ([identifier isKindOfClass:NSString.class] && [identifier rangeOfString:KB_KEYBOARD_EXTENSION_BUNDLE_ID].location != NSNotFound) { + return YES; + } + } + return NO; +} + +- (KBFARecord)lastKnownFullAccess { + NSData *data = [self keychainRead]; + if (data.length == 0) return KBFARecordUnknown; + uint8_t v = 0; [data getBytes:&v length:1]; + if (v > KBFARecordGranted) v = KBFARecordUnknown; + return (KBFARecord)v; +} + +- (void)presentPermissionIfNeededFrom:(UIViewController *)presenting { + BOOL enabled = [self isKeyboardEnabled]; + KBFARecord fa = [self lastKnownFullAccess]; + // 策略: + // - 未启用键盘:一定引导; + // - 已启用键盘:仅当明确知道“完全访问被拒绝”才引导;Unknown 不打扰(等待扩展上报)。 + BOOL needGuide = (!enabled) || (enabled && fa == KBFARecordDenied); + if (!needGuide || !presenting) return; + + Class cls = NSClassFromString(@"KBPermissionViewController"); + if (!cls) return; // 主 App 才存在该类 + UIViewController *guide = [cls new]; + guide.modalPresentationStyle = UIModalPresentationFullScreen; + [presenting presentViewController:guide animated:YES completion:nil]; +} + +#pragma mark - Extension side + +- (void)reportFullAccessFromExtension:(BOOL)granted { + uint8_t v = granted ? KBFARecordGranted : KBFARecordDenied; + NSData *data = [NSData dataWithBytes:&v length:1]; + [self keychainWrite:data]; +} + +#pragma mark - Keychain shared blob + +- (NSMutableDictionary *)baseKCQuery { + NSMutableDictionary *q = [@{ (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword, + (__bridge id)kSecAttrService: kKBPermService, + (__bridge id)kSecAttrAccount: kKBPermAccount } mutableCopy]; + q[(__bridge id)kSecAttrAccessGroup] = KB_KEYCHAIN_ACCESS_GROUP; + return q; +} + +- (BOOL)keychainWrite:(NSData *)data { + NSMutableDictionary *query = [self baseKCQuery]; + SecItemDelete((__bridge CFDictionaryRef)query); + query[(__bridge id)kSecValueData] = data ?: [NSData data]; + query[(__bridge id)kSecAttrAccessible] = (__bridge id)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly; + OSStatus st = SecItemAdd((__bridge CFDictionaryRef)query, NULL); + return (st == errSecSuccess); +} + +- (NSData *)keychainRead { + NSMutableDictionary *query = [self baseKCQuery]; + query[(__bridge id)kSecReturnData] = @YES; + query[(__bridge id)kSecMatchLimit] = (__bridge id)kSecMatchLimitOne; + CFTypeRef dataRef = NULL; OSStatus st = SecItemCopyMatching((__bridge CFDictionaryRef)query, &dataRef); + if (st != errSecSuccess || !dataRef) return nil; + return (__bridge_transfer NSData *)dataRef; +} + +@end diff --git a/Shared/KBLocalizationManager.h b/Shared/KBLocalizationManager.h new file mode 100644 index 0000000..ba6430c --- /dev/null +++ b/Shared/KBLocalizationManager.h @@ -0,0 +1,57 @@ +// +// KBLocalizationManager.h +// 多语言管理(App 与键盘扩展共用) +// 功能: +// - 运行时切换语言(不依赖系统设置) +// - 可选跨 Target 同步(共享钥匙串),让 App 与扩展语言一致 +// - 提供便捷宏 KBLocalized(key) +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// 当前语言变更通知(不附带 userInfo) +extern NSString * const KBLocalizationDidChangeNotification; + +/// 轻量多语言管理器:支持运行时切换、跨 Target 同步 +@interface KBLocalizationManager : NSObject + +/// 单例 ++ (instancetype)shared; + +/// 当前语言代码(如:"en"、"zh-Hans"、"ja")。 +/// 默认会在受支持语言中,按系统首选语言择优匹配。 +@property (nonatomic, copy, readonly) NSString *currentLanguageCode; + +/// 支持的语言代码列表。默认 @[@"en", @"zh-Hans"]。 +/// 建议在启动早期设置;或设置后再调用 `-setCurrentLanguageCode:persist:` 以刷新。 +@property (nonatomic, copy) NSArray *supportedLanguageCodes; + +/// 设置当前语言。 +/// @param code 语言代码 +/// @param persist 是否持久化到共享钥匙串(以便 App 与扩展共享该选择) +- (void)setCurrentLanguageCode:(NSString *)code persist:(BOOL)persist; + +/// 清除用户选择,恢复为系统最佳匹配。 +- (void)resetToSystemLanguage; + +/// 从默认表(Localizable.strings)取文案。 +- (NSString *)localizedStringForKey:(NSString *)key; + +/// 指定表名(不含扩展名)取文案。 +- (NSString *)localizedStringForKey:(NSString *)key + table:(nullable NSString *)table + value:(nullable NSString *)value; + +/// 基于一组“偏好语言”计算最佳支持语言。 +- (NSString *)bestSupportedLanguageForPreferred:(NSArray *)preferred; + +@end + +/// 便捷宏:与 NSLocalizedString 类似,但遵循 KBLocalizationManager 当前语言 +#ifndef KBLocalized +#define KBLocalized(key) [[KBLocalizationManager shared] localizedStringForKey:(key)] +#endif + +NS_ASSUME_NONNULL_END diff --git a/Shared/KBLocalizationManager.m b/Shared/KBLocalizationManager.m new file mode 100644 index 0000000..d9cc341 --- /dev/null +++ b/Shared/KBLocalizationManager.m @@ -0,0 +1,180 @@ +// +// KBLocalizationManager.m +// 多语言管理实现 +// + +#import "KBLocalizationManager.h" +#import +#import "KBConfig.h" + +/// 语言变更通知名称 +NSString * const KBLocalizationDidChangeNotification = @"KBLocalizationDidChangeNotification"; + +// 通过共享钥匙串跨 Target 持久化语言选择 +static NSString * const kKBLocService = @"com.keyBoardst.loc"; +static NSString * const kKBLocAccount = @"lang"; // 保存 UTF8 的语言代码 + +@interface KBLocalizationManager () +@property (nonatomic, copy, readwrite) NSString *currentLanguageCode; // 当前语言代码 +@property (nonatomic, strong) NSBundle *langBundle; // 对应语言的 .lproj 资源包 +@end + +// 避免 +shared 初始化阶段递归触发自身: +// 这里提供一个 C 级别的工具函数,构建钥匙串查询,不依赖实例或 +shared。 +static inline NSMutableDictionary *KBLocBaseKCQuery(void) { + NSMutableDictionary *q = [@{ (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword, + (__bridge id)kSecAttrService: kKBLocService, + (__bridge id)kSecAttrAccount: kKBLocAccount } mutableCopy]; + if (KB_KEYCHAIN_ACCESS_GROUP.length > 0) { + q[(__bridge id)kSecAttrAccessGroup] = KB_KEYCHAIN_ACCESS_GROUP; + } + return q; +} + +@implementation KBLocalizationManager + ++ (instancetype)shared { + static KBLocalizationManager *m; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ + m = [KBLocalizationManager new]; + // 默认支持语言;可在启动时由外部重置 + m.supportedLanguageCodes = @[ @"en", @"zh-Hans" ]; + // 启动读取:先取共享钥匙串,再按系统偏好回退 + NSString *saved = [[self class] kc_read]; + if (saved.length == 0) { + saved = [m bestSupportedLanguageForPreferred:[NSLocale preferredLanguages]] ?: @"en"; + } + [m applyLanguage:saved]; + }); + return m; +} + +#pragma mark - 对外 API + +- (void)setSupportedLanguageCodes:(NSArray *)supportedLanguageCodes { + // 归一化:去重、去空 + NSMutableOrderedSet *set = [NSMutableOrderedSet orderedSet]; + for (NSString *c in supportedLanguageCodes) { + if (c.length) { [set addObject:c]; } + } + _supportedLanguageCodes = set.array.count ? set.array : @[ @"en" ]; + // 若当前语言不再受支持,则按最佳匹配切回(不持久化,仅内存),并广播变更 + if (self.currentLanguageCode.length && ![set containsObject:self.currentLanguageCode]) { + NSString *best = [self bestSupportedLanguageForPreferred:@[self.currentLanguageCode]]; + [self applyLanguage:best ?: _supportedLanguageCodes.firstObject]; + [[NSNotificationCenter defaultCenter] postNotificationName:KBLocalizationDidChangeNotification object:nil]; + } +} + +- (void)setCurrentLanguageCode:(NSString *)code persist:(BOOL)persist { + if (code.length == 0) return; // 忽略空值 + if ([code isEqualToString:self.currentLanguageCode]) return; // 无变更 + [self applyLanguage:code]; + if (persist) { [[self class] kc_write:code]; } // 需同步到 App/扩展 + [[NSNotificationCenter defaultCenter] postNotificationName:KBLocalizationDidChangeNotification object:nil]; +} + +- (void)resetToSystemLanguage { + NSString *best = [self bestSupportedLanguageForPreferred:[NSLocale preferredLanguages]] ?: @"en"; + [self setCurrentLanguageCode:best persist:NO]; +} + +- (NSString *)localizedStringForKey:(NSString *)key { + return [self localizedStringForKey:key table:nil value:key]; +} + +- (NSString *)localizedStringForKey:(NSString *)key table:(NSString *)table value:(NSString *)value { + if (key.length == 0) return @""; + NSBundle *bundle = self.langBundle ?: NSBundle.mainBundle; + NSString *tbl = table ?: @"Localizable"; + // 使用 bundle API,避免 NSLocalizedString 被系统语言钉死 + NSString *str = [bundle localizedStringForKey:key value:value table:tbl]; + return str ?: (value ?: key); +} + +- (NSString *)bestSupportedLanguageForPreferred:(NSArray *)preferred { + if (self.supportedLanguageCodes.count == 0) return @"en"; + // 1) 完全匹配 + for (NSString *p in preferred) { + NSString *pLC = p.lowercaseString; + for (NSString *s in self.supportedLanguageCodes) { + if ([pLC isEqualToString:s.lowercaseString]) { return s; } + } + } + // 2) 前缀匹配:如 zh-Hans-CN -> zh-Hans, en-GB -> en + for (NSString *p in preferred) { + NSString *pLC = p.lowercaseString; + for (NSString *s in self.supportedLanguageCodes) { + NSString *sLC = s.lowercaseString; + if ([pLC hasPrefix:[sLC stringByAppendingString:@"-"]] || [pLC hasPrefix:[sLC stringByAppendingString:@"_"]]) { + return s; + } + // also allow reverse: when supported is regional (rare) + if ([sLC hasPrefix:[pLC stringByAppendingString:@"-"]] || [sLC hasPrefix:[pLC stringByAppendingString:@"_"]]) { + return s; + } + } + } + // 3) 特殊处理中文:将 zh-Hant/zh-TW/zh-HK 映射到 zh-Hant(若受支持) + for (NSString *p in preferred) { + NSString *pLC = p.lowercaseString; + if ([pLC hasPrefix:@"zh-hant"] || [pLC hasPrefix:@"zh-tw"] || [pLC hasPrefix:@"zh-hk"]) { + for (NSString *s in self.supportedLanguageCodes) { + if ([s.lowercaseString isEqualToString:@"zh-hant"]) { return s; } + } + } + if ([pLC hasPrefix:@"zh-hans"] || [pLC hasPrefix:@"zh-cn"]) { + for (NSString *s in self.supportedLanguageCodes) { + if ([s.lowercaseString isEqualToString:@"zh-hans"]) { return s; } + } + } + } + // 4) 兜底:取第一个受支持语言 + return self.supportedLanguageCodes.firstObject ?: @"en"; +} + +#pragma mark - 内部实现 + +- (void)applyLanguage:(NSString *)code { + _currentLanguageCode = [code copy]; + // 基于当前 Target(App 或扩展)的主 bundle 加载 .lproj 资源 + NSString *path = [NSBundle.mainBundle pathForResource:code ofType:@"lproj"]; + if (!path) { + // 尝试去区域后缀:如 en-GB -> en + NSString *shortCode = [[code componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"-_"]] firstObject]; + if (shortCode.length > 0) { + path = [NSBundle.mainBundle pathForResource:shortCode ofType:@"lproj"]; + } + } + if (path) { + self.langBundle = [NSBundle bundleWithPath:path]; + } else { + self.langBundle = NSBundle.mainBundle; // 兜底 + } +} + +#pragma mark - 钥匙串读写(App/扩展共享) + ++ (BOOL)kc_write:(NSString *)lang { + NSMutableDictionary *q = KBLocBaseKCQuery(); + SecItemDelete((__bridge CFDictionaryRef)q); + if (lang.length == 0) return YES; // 等价于删除 + NSData *data = [lang dataUsingEncoding:NSUTF8StringEncoding]; + q[(__bridge id)kSecValueData] = data ?: [NSData data]; + q[(__bridge id)kSecAttrAccessible] = (__bridge id)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly; + OSStatus st = SecItemAdd((__bridge CFDictionaryRef)q, NULL); + return (st == errSecSuccess); +} + ++ (NSString *)kc_read { + NSMutableDictionary *q = KBLocBaseKCQuery(); + 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; + NSString *lang = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + return lang; +} + +@end diff --git a/Shared/Localization/en.lproj/Localizable.strings b/Shared/Localization/en.lproj/Localizable.strings new file mode 100644 index 0000000..dd69c3e --- /dev/null +++ b/Shared/Localization/en.lproj/Localizable.strings @@ -0,0 +1,20 @@ +/* + Localizable.strings (English) + Keys shared by App and Keyboard extension +*/ + +"perm_title_enable" = "Enable Keyboard"; +"perm_steps" = "1 Enable Keyboard > 2 Allow Full Access"; +"perm_open_settings" = "Open in Settings"; +"perm_help" = "Can't find the keyboard? Go to Settings > General > Keyboard > Keyboards > Add New Keyboard"; + +// Home page & language test +"home_title" = "Home"; +"home_input_placeholder" = "Type here to test the keyboard"; +"home_item_lang_test" = "Language Test"; +"home_item_keyboard_permission" = "Keyboard Permission Guide"; + +"lang_test_title" = "Language Test"; +"lang_toggle" = "Toggle Language"; +"current_lang" = "Current: %@"; +"common_back" = "Back"; diff --git a/Shared/Localization/zh-Hans.lproj/Localizable.strings b/Shared/Localization/zh-Hans.lproj/Localizable.strings new file mode 100644 index 0000000..00a3f7a --- /dev/null +++ b/Shared/Localization/zh-Hans.lproj/Localizable.strings @@ -0,0 +1,20 @@ +/* + Localizable.strings (简体中文) + App 与键盘扩展共用的文案 Key +*/ + +"perm_title_enable" = "启用输入法"; +"perm_steps" = "1 开启键盘 > 2 允许完全访问"; +"perm_open_settings" = "去设置中开启"; +"perm_help" = "没有找到键盘? 请前往 设置 > 通用 > 键盘 > 键盘 > 添加新键盘"; + +// 首页与多语言测试 +"home_title" = "首页"; +"home_input_placeholder" = "在此输入,测试键盘"; +"home_item_lang_test" = "多语言测试"; +"home_item_keyboard_permission" = "键盘权限引导"; + +"lang_test_title" = "多语言测试"; +"lang_toggle" = "切换语言"; +"current_lang" = "当前:%@"; +"common_back" = "返回"; diff --git a/keyBoard.xcodeproj/project.pbxproj b/keyBoard.xcodeproj/project.pbxproj index 39e8cd7..3ff85de 100644 --- a/keyBoard.xcodeproj/project.pbxproj +++ b/keyBoard.xcodeproj/project.pbxproj @@ -8,6 +8,13 @@ /* Begin PBXBuildFile section */ 043FBCD22EAF97630036AFE1 /* KBPermissionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 04C6EAE12EAF940F0089C901 /* KBPermissionViewController.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 */; }; + 04A9FE1A2EB892460020DB6D /* KBLocalizationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 04A9FE192EB892460020DB6D /* KBLocalizationManager.m */; }; + 04A9FE1B2EB892460020DB6D /* KBLocalizationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 04A9FE192EB892460020DB6D /* KBLocalizationManager.m */; }; + 04A9FE202EB893F10020DB6D /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 04A9FE1E2EB893F10020DB6D /* Localizable.strings */; }; + 04A9FE212EB893F10020DB6D /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 04A9FE1E2EB893F10020DB6D /* Localizable.strings */; }; 04C6EABA2EAF86530089C901 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 04C6EAAE2EAF86530089C901 /* Assets.xcassets */; }; 04C6EABC2EAF86530089C901 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 04C6EAB12EAF86530089C901 /* LaunchScreen.storyboard */; }; 04C6EABD2EAF86530089C901 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 04C6EAB42EAF86530089C901 /* Main.storyboard */; }; @@ -17,19 +24,41 @@ 04C6EACE2EAF87020089C901 /* CustomKeyboard.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 04C6EAC62EAF87020089C901 /* CustomKeyboard.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 04C6EAD82EAF870B0089C901 /* KeyboardViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 04C6EAD62EAF870B0089C901 /* KeyboardViewController.m */; }; 04C6EADD2EAF8CEB0089C901 /* KBToolBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 04C6EADC2EAF8CEB0089C901 /* KBToolBar.m */; }; - 04FC95582EAFAF51007BD342 /* MASConstraintMaker.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC954B2EAFAF51007BD342 /* MASConstraintMaker.m */; }; - 04FC95592EAFAF51007BD342 /* MASViewConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95532EAFAF51007BD342 /* MASViewConstraint.m */; }; - 04FC955A2EAFAF51007BD342 /* MASViewAttribute.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95542EAFAF51007BD342 /* MASViewAttribute.m */; }; - 04FC955B2EAFAF51007BD342 /* NSArray+MASAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC954D2EAFAF51007BD342 /* NSArray+MASAdditions.m */; }; - 04FC955C2EAFAF51007BD342 /* View+MASAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC954E2EAFAF51007BD342 /* View+MASAdditions.m */; }; - 04FC955D2EAFAF51007BD342 /* MASCompositeConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC954A2EAFAF51007BD342 /* MASCompositeConstraint.m */; }; - 04FC955E2EAFAF51007BD342 /* MASConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95512EAFAF51007BD342 /* MASConstraint.m */; }; - 04FC955F2EAFAF51007BD342 /* NSLayoutConstraint+MASDebugAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC953D2EAFAF51007BD342 /* NSLayoutConstraint+MASDebugAdditions.m */; }; - 04FC95602EAFAF51007BD342 /* MASLayoutConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC954C2EAFAF51007BD342 /* MASLayoutConstraint.m */; }; - 04FC95612EAFAF51007BD342 /* ViewController+MASAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95462EAFAF51007BD342 /* ViewController+MASAdditions.m */; }; - 04FC95622EAFAF51007BD342 /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = 04FC953B2EAFAF51007BD342 /* LICENSE */; }; - 04FC95632EAFAF51007BD342 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 04FC95562EAFAF51007BD342 /* README.md */; }; + 04FC95672EB0546C007BD342 /* KBKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95652EB0546C007BD342 /* KBKey.m */; }; + 04FC956A2EB05497007BD342 /* KBKeyButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95692EB05497007BD342 /* KBKeyButton.m */; }; + 04FC956D2EB054B7007BD342 /* KBKeyboardView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC956C2EB054B7007BD342 /* KBKeyboardView.m */; }; + 04FC95702EB09516007BD342 /* KBFunctionView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC956F2EB09516007BD342 /* KBFunctionView.m */; }; + 04FC95732EB09570007BD342 /* KBFunctionBarView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95722EB09570007BD342 /* KBFunctionBarView.m */; }; + 04FC95762EB095DE007BD342 /* KBFunctionPasteView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95752EB095DE007BD342 /* KBFunctionPasteView.m */; }; + 04FC95792EB09BC8007BD342 /* KBKeyBoardMainView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95782EB09BC8007BD342 /* KBKeyBoardMainView.m */; }; + 04FC95B22EB0B2CC007BD342 /* KBSettingView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95B12EB0B2CC007BD342 /* KBSettingView.m */; }; + 04FC95C92EB1E4C9007BD342 /* BaseNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95C82EB1E4C9007BD342 /* BaseNavigationController.m */; }; + 04FC95CC2EB1E780007BD342 /* BaseTabBarController.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95CB2EB1E780007BD342 /* BaseTabBarController.m */; }; + 04FC95CF2EB1E7A1007BD342 /* HomeVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95CE2EB1E7A1007BD342 /* HomeVC.m */; }; + 04FC95D22EB1E7AE007BD342 /* MyVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95D12EB1E7AE007BD342 /* MyVC.m */; }; + 04FC95D72EB1EA16007BD342 /* BaseTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95D62EB1EA16007BD342 /* BaseTableView.m */; }; + 04FC95D82EB1EA16007BD342 /* BaseCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95D42EB1EA16007BD342 /* BaseCell.m */; }; + 04FC95DD2EB202A3007BD342 /* KBGuideVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95DC2EB202A3007BD342 /* KBGuideVC.m */; }; + 04FC95E52EB220B5007BD342 /* UIColor+Extension.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95E42EB220B5007BD342 /* UIColor+Extension.m */; }; + 04FC95E92EB23B67007BD342 /* KBNetworkManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95E72EB23B67007BD342 /* KBNetworkManager.m */; }; + 04FC95F12EB339A7007BD342 /* LoginViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95F02EB339A7007BD342 /* LoginViewController.m */; }; + 04FC95F42EB339C1007BD342 /* AppleSignInManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95F32EB339C1007BD342 /* AppleSignInManager.m */; }; + 04FC96142EB34E00007BD342 /* KBLoginSheetViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC96122EB34E00007BD342 /* KBLoginSheetViewController.m */; }; + 04FC97002EB30A00007BD342 /* KBGuideTopCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC96FF2EB30A00007BD342 /* KBGuideTopCell.m */; }; + 04FC97032EB30A00007BD342 /* KBGuideKFCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC97022EB30A00007BD342 /* KBGuideKFCell.m */; }; + 04FC97062EB30A00007BD342 /* KBGuideUserCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC97052EB30A00007BD342 /* KBGuideUserCell.m */; }; + 04FC97092EB31B14007BD342 /* KBHUD.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC97082EB31B14007BD342 /* KBHUD.m */; }; + 04FC970E2EB334F8007BD342 /* UIImageView+KBWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC970B2EB334F8007BD342 /* UIImageView+KBWebImage.m */; }; + 04FC970F2EB334F8007BD342 /* KBWebImageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC970D2EB334F8007BD342 /* KBWebImageManager.m */; }; 7A36414DFDA5BEC9B7D2E318 /* Pods_CustomKeyboard.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2C1092FB2B452F95B15D4263 /* Pods_CustomKeyboard.framework */; }; + A1B2C3D42EB0A0A100000001 /* KBFunctionTagCell.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C3D32EB0A0A100000001 /* KBFunctionTagCell.m */; }; + A1B2C3E22EB0C0A100000001 /* KBNetworkManager.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C3E12EB0C0A100000001 /* KBNetworkManager.m */; }; + A1B2C3F42EB35A9900000001 /* KBFullAccessGuideView.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C3F22EB35A9900000001 /* KBFullAccessGuideView.m */; }; + A1B2C4002EB4A0A100000003 /* KBAuthManager.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C4002EB4A0A100000002 /* KBAuthManager.m */; }; + A1B2C4002EB4A0A100000004 /* KBAuthManager.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C4002EB4A0A100000002 /* KBAuthManager.m */; }; + 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 */; }; ECC9EE02174D86E8D792472F /* Pods_keyBoard.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 967065BB5230E43F293B3AF9 /* Pods_keyBoard.framework */; }; /* End PBXBuildFile section */ @@ -58,6 +87,14 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 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 = ""; }; + 04A9FE152EB873C80020DB6D /* UIViewController+Extension.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIViewController+Extension.m"; sourceTree = ""; }; + 04A9FE182EB892460020DB6D /* KBLocalizationManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBLocalizationManager.h; sourceTree = ""; }; + 04A9FE192EB892460020DB6D /* KBLocalizationManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBLocalizationManager.m; sourceTree = ""; }; + 04A9FE1C2EB893F10020DB6D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; + 04A9FE1D2EB893F10020DB6D /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = ""; }; 04C6EAAC2EAF86530089C901 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 04C6EAAD2EAF86530089C901 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 04C6EAAE2EAF86530089C901 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; @@ -77,37 +114,76 @@ 04C6EAE02EAF940F0089C901 /* KBPermissionViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBPermissionViewController.h; sourceTree = ""; }; 04C6EAE12EAF940F0089C901 /* KBPermissionViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBPermissionViewController.m; sourceTree = ""; }; 04FC953A2EAFAE56007BD342 /* KeyBoardPrefixHeader.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeyBoardPrefixHeader.pch; sourceTree = ""; }; - 04FC953B2EAFAF51007BD342 /* LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; - 04FC953C2EAFAF51007BD342 /* MASCompositeConstraint.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MASCompositeConstraint.h; sourceTree = ""; }; - 04FC953D2EAFAF51007BD342 /* NSLayoutConstraint+MASDebugAdditions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSLayoutConstraint+MASDebugAdditions.m"; sourceTree = ""; }; - 04FC953E2EAFAF51007BD342 /* MASConstraint+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MASConstraint+Private.h"; sourceTree = ""; }; - 04FC953F2EAFAF51007BD342 /* MASLayoutConstraint.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MASLayoutConstraint.h; sourceTree = ""; }; - 04FC95402EAFAF51007BD342 /* NSArray+MASShorthandAdditions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSArray+MASShorthandAdditions.h"; sourceTree = ""; }; - 04FC95412EAFAF51007BD342 /* MASConstraintMaker.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MASConstraintMaker.h; sourceTree = ""; }; - 04FC95422EAFAF51007BD342 /* View+MASAdditions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "View+MASAdditions.h"; sourceTree = ""; }; - 04FC95432EAFAF51007BD342 /* NSArray+MASAdditions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSArray+MASAdditions.h"; sourceTree = ""; }; - 04FC95442EAFAF51007BD342 /* MASUtilities.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MASUtilities.h; sourceTree = ""; }; - 04FC95452EAFAF51007BD342 /* MASViewAttribute.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MASViewAttribute.h; sourceTree = ""; }; - 04FC95462EAFAF51007BD342 /* ViewController+MASAdditions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "ViewController+MASAdditions.m"; sourceTree = ""; }; - 04FC95472EAFAF51007BD342 /* MASViewConstraint.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MASViewConstraint.h; sourceTree = ""; }; - 04FC95482EAFAF51007BD342 /* MASConstraint.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MASConstraint.h; sourceTree = ""; }; - 04FC95492EAFAF51007BD342 /* NSLayoutConstraint+MASDebugAdditions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSLayoutConstraint+MASDebugAdditions.h"; sourceTree = ""; }; - 04FC954A2EAFAF51007BD342 /* MASCompositeConstraint.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MASCompositeConstraint.m; sourceTree = ""; }; - 04FC954B2EAFAF51007BD342 /* MASConstraintMaker.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MASConstraintMaker.m; sourceTree = ""; }; - 04FC954C2EAFAF51007BD342 /* MASLayoutConstraint.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MASLayoutConstraint.m; sourceTree = ""; }; - 04FC954D2EAFAF51007BD342 /* NSArray+MASAdditions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSArray+MASAdditions.m"; sourceTree = ""; }; - 04FC954E2EAFAF51007BD342 /* View+MASAdditions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "View+MASAdditions.m"; sourceTree = ""; }; - 04FC954F2EAFAF51007BD342 /* View+MASShorthandAdditions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "View+MASShorthandAdditions.h"; sourceTree = ""; }; - 04FC95502EAFAF51007BD342 /* Masonry.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Masonry.h; sourceTree = ""; }; - 04FC95512EAFAF51007BD342 /* MASConstraint.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MASConstraint.m; sourceTree = ""; }; - 04FC95522EAFAF51007BD342 /* ViewController+MASAdditions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ViewController+MASAdditions.h"; sourceTree = ""; }; - 04FC95532EAFAF51007BD342 /* MASViewConstraint.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MASViewConstraint.m; sourceTree = ""; }; - 04FC95542EAFAF51007BD342 /* MASViewAttribute.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MASViewAttribute.m; sourceTree = ""; }; - 04FC95562EAFAF51007BD342 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; + 04FC95642EB0546C007BD342 /* KBKey.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBKey.h; sourceTree = ""; }; + 04FC95652EB0546C007BD342 /* KBKey.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBKey.m; sourceTree = ""; }; + 04FC95682EB05497007BD342 /* KBKeyButton.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBKeyButton.h; sourceTree = ""; }; + 04FC95692EB05497007BD342 /* KBKeyButton.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBKeyButton.m; sourceTree = ""; }; + 04FC956B2EB054B7007BD342 /* KBKeyboardView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBKeyboardView.h; sourceTree = ""; }; + 04FC956C2EB054B7007BD342 /* KBKeyboardView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBKeyboardView.m; sourceTree = ""; }; + 04FC956E2EB09516007BD342 /* KBFunctionView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBFunctionView.h; sourceTree = ""; }; + 04FC956F2EB09516007BD342 /* KBFunctionView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBFunctionView.m; sourceTree = ""; }; + 04FC95712EB09570007BD342 /* KBFunctionBarView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBFunctionBarView.h; sourceTree = ""; }; + 04FC95722EB09570007BD342 /* KBFunctionBarView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBFunctionBarView.m; sourceTree = ""; }; + 04FC95742EB095DE007BD342 /* KBFunctionPasteView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBFunctionPasteView.h; sourceTree = ""; }; + 04FC95752EB095DE007BD342 /* KBFunctionPasteView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBFunctionPasteView.m; sourceTree = ""; }; + 04FC95772EB09BC8007BD342 /* KBKeyBoardMainView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBKeyBoardMainView.h; sourceTree = ""; }; + 04FC95782EB09BC8007BD342 /* KBKeyBoardMainView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBKeyBoardMainView.m; sourceTree = ""; }; + 04FC95B02EB0B2CC007BD342 /* KBSettingView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBSettingView.h; sourceTree = ""; }; + 04FC95B12EB0B2CC007BD342 /* KBSettingView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBSettingView.m; sourceTree = ""; }; + 04FC95C72EB1E4C9007BD342 /* BaseNavigationController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BaseNavigationController.h; sourceTree = ""; }; + 04FC95C82EB1E4C9007BD342 /* BaseNavigationController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BaseNavigationController.m; sourceTree = ""; }; + 04FC95CA2EB1E780007BD342 /* BaseTabBarController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BaseTabBarController.h; sourceTree = ""; }; + 04FC95CB2EB1E780007BD342 /* BaseTabBarController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BaseTabBarController.m; sourceTree = ""; }; + 04FC95CD2EB1E7A1007BD342 /* HomeVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeVC.h; sourceTree = ""; }; + 04FC95CE2EB1E7A1007BD342 /* HomeVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HomeVC.m; sourceTree = ""; }; + 04FC95D02EB1E7AE007BD342 /* MyVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MyVC.h; sourceTree = ""; }; + 04FC95D12EB1E7AE007BD342 /* MyVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MyVC.m; sourceTree = ""; }; + 04FC95D32EB1EA16007BD342 /* BaseCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BaseCell.h; sourceTree = ""; }; + 04FC95D42EB1EA16007BD342 /* BaseCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BaseCell.m; sourceTree = ""; }; + 04FC95D52EB1EA16007BD342 /* BaseTableView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BaseTableView.h; sourceTree = ""; }; + 04FC95D62EB1EA16007BD342 /* BaseTableView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BaseTableView.m; sourceTree = ""; }; + 04FC95DB2EB202A3007BD342 /* KBGuideVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBGuideVC.h; sourceTree = ""; }; + 04FC95DC2EB202A3007BD342 /* KBGuideVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBGuideVC.m; sourceTree = ""; }; + 04FC95E32EB220B5007BD342 /* UIColor+Extension.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIColor+Extension.h"; sourceTree = ""; }; + 04FC95E42EB220B5007BD342 /* UIColor+Extension.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIColor+Extension.m"; sourceTree = ""; }; + 04FC95E62EB23B67007BD342 /* KBNetworkManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBNetworkManager.h; sourceTree = ""; }; + 04FC95E72EB23B67007BD342 /* KBNetworkManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBNetworkManager.m; sourceTree = ""; }; + 04FC95EF2EB339A7007BD342 /* LoginViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LoginViewController.h; sourceTree = ""; }; + 04FC95F02EB339A7007BD342 /* LoginViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LoginViewController.m; sourceTree = ""; }; + 04FC95F22EB339C1007BD342 /* AppleSignInManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppleSignInManager.h; sourceTree = ""; }; + 04FC95F32EB339C1007BD342 /* AppleSignInManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppleSignInManager.m; sourceTree = ""; }; + 04FC95F52EB33B52007BD342 /* keyBoard.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = keyBoard.entitlements; sourceTree = ""; }; + 04FC96112EB34E00007BD342 /* KBLoginSheetViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBLoginSheetViewController.h; sourceTree = ""; }; + 04FC96122EB34E00007BD342 /* KBLoginSheetViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBLoginSheetViewController.m; sourceTree = ""; }; + 04FC96FE2EB30A00007BD342 /* KBGuideTopCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBGuideTopCell.h; sourceTree = ""; }; + 04FC96FF2EB30A00007BD342 /* KBGuideTopCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBGuideTopCell.m; sourceTree = ""; }; + 04FC97012EB30A00007BD342 /* KBGuideKFCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBGuideKFCell.h; sourceTree = ""; }; + 04FC97022EB30A00007BD342 /* KBGuideKFCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBGuideKFCell.m; sourceTree = ""; }; + 04FC97042EB30A00007BD342 /* KBGuideUserCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBGuideUserCell.h; sourceTree = ""; }; + 04FC97052EB30A00007BD342 /* KBGuideUserCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBGuideUserCell.m; sourceTree = ""; }; + 04FC97072EB31B14007BD342 /* KBHUD.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBHUD.h; sourceTree = ""; }; + 04FC97082EB31B14007BD342 /* KBHUD.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBHUD.m; sourceTree = ""; }; + 04FC970A2EB334F8007BD342 /* UIImageView+KBWebImage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIImageView+KBWebImage.h"; sourceTree = ""; }; + 04FC970B2EB334F8007BD342 /* UIImageView+KBWebImage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIImageView+KBWebImage.m"; sourceTree = ""; }; + 04FC970C2EB334F8007BD342 /* KBWebImageManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBWebImageManager.h; sourceTree = ""; }; + 04FC970D2EB334F8007BD342 /* KBWebImageManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBWebImageManager.m; sourceTree = ""; }; + 04FC98012EB36AAB007BD342 /* KBConfig.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBConfig.h; sourceTree = ""; }; 2C1092FB2B452F95B15D4263 /* Pods_CustomKeyboard.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_CustomKeyboard.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 51FE7C4C42C2255B3C1C4128 /* Pods-keyBoard.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-keyBoard.release.xcconfig"; path = "Target Support Files/Pods-keyBoard/Pods-keyBoard.release.xcconfig"; sourceTree = ""; }; 727EC7532EAF848B00B36487 /* keyBoard.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = keyBoard.app; sourceTree = BUILT_PRODUCTS_DIR; }; 967065BB5230E43F293B3AF9 /* Pods_keyBoard.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_keyBoard.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + A1B2C3D22EB0A0A100000001 /* KBFunctionTagCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBFunctionTagCell.h; sourceTree = ""; }; + A1B2C3D32EB0A0A100000001 /* KBFunctionTagCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBFunctionTagCell.m; sourceTree = ""; }; + A1B2C3E02EB0C0A100000001 /* KBNetworkManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBNetworkManager.h; sourceTree = ""; }; + A1B2C3E12EB0C0A100000001 /* KBNetworkManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBNetworkManager.m; sourceTree = ""; }; + A1B2C3F12EB35A9900000001 /* KBFullAccessGuideView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBFullAccessGuideView.h; sourceTree = ""; }; + A1B2C3F22EB35A9900000001 /* KBFullAccessGuideView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBFullAccessGuideView.m; sourceTree = ""; }; + A1B2C4002EB4A0A100000001 /* KBAuthManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBAuthManager.h; sourceTree = ""; }; + A1B2C4002EB4A0A100000002 /* KBAuthManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBAuthManager.m; sourceTree = ""; }; + A1B2C4222EB4B7A100000001 /* KBKeyboardPermissionManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBKeyboardPermissionManager.m; sourceTree = ""; }; + 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 = ""; }; 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 = ""; }; @@ -133,9 +209,28 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 04A9FE122EB4D0D20020DB6D /* Manager */ = { + isa = PBXGroup; + children = ( + 04A9FE102EB4D0D20020DB6D /* KBFullAccessManager.h */, + 04A9FE112EB4D0D20020DB6D /* KBFullAccessManager.m */, + ); + path = Manager; + sourceTree = ""; + }; + 04A9FE1F2EB893F10020DB6D /* Localization */ = { + isa = PBXGroup; + children = ( + 04A9FE1E2EB893F10020DB6D /* Localizable.strings */, + ); + path = Localization; + sourceTree = ""; + }; 04C6EAB92EAF86530089C901 /* keyBoard */ = { isa = PBXGroup; children = ( + 04FC95F52EB33B52007BD342 /* keyBoard.entitlements */, + 04FC95BF2EB1E3B1007BD342 /* Class */, 04C6EAE32EAF942E0089C901 /* VC */, 04C6EAAC2EAF86530089C901 /* AppDelegate.h */, 04C6EAAD2EAF86530089C901 /* AppDelegate.m */, @@ -154,11 +249,13 @@ 04C6EAD72EAF870B0089C901 /* CustomKeyboard */ = { isa = PBXGroup; children = ( + 04A9FE122EB4D0D20020DB6D /* Manager */, + 04FC95662EB0546C007BD342 /* Model */, 04C6EADA2EAF8C7B0089C901 /* View */, + A1B2C3E52EB0C0A100000001 /* Network */, 04C6EAD42EAF870B0089C901 /* Info.plist */, 04C6EAD52EAF870B0089C901 /* KeyboardViewController.h */, 04C6EAD62EAF870B0089C901 /* KeyboardViewController.m */, - 04FC95572EAFAF51007BD342 /* Masonry */, 04C6EADE2EAF8D680089C901 /* PrefixHeader.pch */, ); path = CustomKeyboard; @@ -169,6 +266,24 @@ children = ( 04C6EADB2EAF8CEB0089C901 /* KBToolBar.h */, 04C6EADC2EAF8CEB0089C901 /* KBToolBar.m */, + 04FC95682EB05497007BD342 /* KBKeyButton.h */, + 04FC95692EB05497007BD342 /* KBKeyButton.m */, + 04FC956B2EB054B7007BD342 /* KBKeyboardView.h */, + 04FC956C2EB054B7007BD342 /* KBKeyboardView.m */, + 04FC95772EB09BC8007BD342 /* KBKeyBoardMainView.h */, + 04FC95782EB09BC8007BD342 /* KBKeyBoardMainView.m */, + 04FC956E2EB09516007BD342 /* KBFunctionView.h */, + 04FC956F2EB09516007BD342 /* KBFunctionView.m */, + 04FC95712EB09570007BD342 /* KBFunctionBarView.h */, + 04FC95722EB09570007BD342 /* KBFunctionBarView.m */, + 04FC95742EB095DE007BD342 /* KBFunctionPasteView.h */, + 04FC95752EB095DE007BD342 /* KBFunctionPasteView.m */, + A1B2C3D22EB0A0A100000001 /* KBFunctionTagCell.h */, + A1B2C3D32EB0A0A100000001 /* KBFunctionTagCell.m */, + A1B2C3F12EB35A9900000001 /* KBFullAccessGuideView.h */, + A1B2C3F22EB35A9900000001 /* KBFullAccessGuideView.m */, + 04FC95B02EB0B2CC007BD342 /* KBSettingView.h */, + 04FC95B12EB0B2CC007BD342 /* KBSettingView.m */, ); path = View; sourceTree = ""; @@ -182,46 +297,291 @@ path = VC; sourceTree = ""; }; - 04FC95552EAFAF51007BD342 /* Masonry */ = { + 04FC95662EB0546C007BD342 /* Model */ = { isa = PBXGroup; children = ( - 04FC953C2EAFAF51007BD342 /* MASCompositeConstraint.h */, - 04FC953D2EAFAF51007BD342 /* NSLayoutConstraint+MASDebugAdditions.m */, - 04FC953E2EAFAF51007BD342 /* MASConstraint+Private.h */, - 04FC953F2EAFAF51007BD342 /* MASLayoutConstraint.h */, - 04FC95402EAFAF51007BD342 /* NSArray+MASShorthandAdditions.h */, - 04FC95412EAFAF51007BD342 /* MASConstraintMaker.h */, - 04FC95422EAFAF51007BD342 /* View+MASAdditions.h */, - 04FC95432EAFAF51007BD342 /* NSArray+MASAdditions.h */, - 04FC95442EAFAF51007BD342 /* MASUtilities.h */, - 04FC95452EAFAF51007BD342 /* MASViewAttribute.h */, - 04FC95462EAFAF51007BD342 /* ViewController+MASAdditions.m */, - 04FC95472EAFAF51007BD342 /* MASViewConstraint.h */, - 04FC95482EAFAF51007BD342 /* MASConstraint.h */, - 04FC95492EAFAF51007BD342 /* NSLayoutConstraint+MASDebugAdditions.h */, - 04FC954A2EAFAF51007BD342 /* MASCompositeConstraint.m */, - 04FC954B2EAFAF51007BD342 /* MASConstraintMaker.m */, - 04FC954C2EAFAF51007BD342 /* MASLayoutConstraint.m */, - 04FC954D2EAFAF51007BD342 /* NSArray+MASAdditions.m */, - 04FC954E2EAFAF51007BD342 /* View+MASAdditions.m */, - 04FC954F2EAFAF51007BD342 /* View+MASShorthandAdditions.h */, - 04FC95502EAFAF51007BD342 /* Masonry.h */, - 04FC95512EAFAF51007BD342 /* MASConstraint.m */, - 04FC95522EAFAF51007BD342 /* ViewController+MASAdditions.h */, - 04FC95532EAFAF51007BD342 /* MASViewConstraint.m */, - 04FC95542EAFAF51007BD342 /* MASViewAttribute.m */, + 04FC95642EB0546C007BD342 /* KBKey.h */, + 04FC95652EB0546C007BD342 /* KBKey.m */, ); - path = Masonry; + path = Model; sourceTree = ""; }; - 04FC95572EAFAF51007BD342 /* Masonry */ = { + 04FC95B32EB1E3B1007BD342 /* M */ = { isa = PBXGroup; children = ( - 04FC953B2EAFAF51007BD342 /* LICENSE */, - 04FC95552EAFAF51007BD342 /* Masonry */, - 04FC95562EAFAF51007BD342 /* README.md */, ); - path = Masonry; + path = M; + sourceTree = ""; + }; + 04FC95B42EB1E3B1007BD342 /* V */ = { + isa = PBXGroup; + children = ( + ); + path = V; + sourceTree = ""; + }; + 04FC95B52EB1E3B1007BD342 /* VC */ = { + isa = PBXGroup; + children = ( + 04FC95CD2EB1E7A1007BD342 /* HomeVC.h */, + 04FC95CE2EB1E7A1007BD342 /* HomeVC.m */, + A1B2D7002EB8C00100000001 /* KBLangTestVC.h */, + A1B2D7012EB8C00100000001 /* KBLangTestVC.m */, + ); + path = VC; + sourceTree = ""; + }; + 04FC95B62EB1E3B1007BD342 /* Home */ = { + isa = PBXGroup; + children = ( + 04FC95B32EB1E3B1007BD342 /* M */, + 04FC95B42EB1E3B1007BD342 /* V */, + 04FC95B52EB1E3B1007BD342 /* VC */, + ); + path = Home; + sourceTree = ""; + }; + 04FC95B72EB1E3B1007BD342 /* M */ = { + isa = PBXGroup; + children = ( + ); + path = M; + sourceTree = ""; + }; + 04FC95B82EB1E3B1007BD342 /* V */ = { + isa = PBXGroup; + children = ( + ); + path = V; + sourceTree = ""; + }; + 04FC95B92EB1E3B1007BD342 /* VC */ = { + isa = PBXGroup; + children = ( + ); + path = VC; + sourceTree = ""; + }; + 04FC95BA2EB1E3B1007BD342 /* Main */ = { + isa = PBXGroup; + children = ( + 04FC95B72EB1E3B1007BD342 /* M */, + 04FC95B82EB1E3B1007BD342 /* V */, + 04FC95B92EB1E3B1007BD342 /* VC */, + ); + path = Main; + sourceTree = ""; + }; + 04FC95BB2EB1E3B1007BD342 /* M */ = { + isa = PBXGroup; + children = ( + ); + path = M; + sourceTree = ""; + }; + 04FC95BC2EB1E3B1007BD342 /* V */ = { + isa = PBXGroup; + children = ( + ); + path = V; + sourceTree = ""; + }; + 04FC95BD2EB1E3B1007BD342 /* VC */ = { + isa = PBXGroup; + children = ( + 04FC95D02EB1E7AE007BD342 /* MyVC.h */, + 04FC95D12EB1E7AE007BD342 /* MyVC.m */, + ); + path = VC; + sourceTree = ""; + }; + 04FC95BE2EB1E3B1007BD342 /* Me */ = { + isa = PBXGroup; + children = ( + 04FC95BB2EB1E3B1007BD342 /* M */, + 04FC95BC2EB1E3B1007BD342 /* V */, + 04FC95BD2EB1E3B1007BD342 /* VC */, + ); + path = Me; + sourceTree = ""; + }; + 04FC95BF2EB1E3B1007BD342 /* Class */ = { + isa = PBXGroup; + children = ( + 04FC95EE2EB3399D007BD342 /* Manager */, + 04FC95ED2EB33611007BD342 /* Login */, + 04FC95E82EB23B67007BD342 /* Network */, + 04FC95E22EB2208F007BD342 /* Categories */, + 04FC95E12EB20AD1007BD342 /* Guard */, + 04FC95C62EB1E4AB007BD342 /* Base */, + 04FC95BA2EB1E3B1007BD342 /* Main */, + 04FC95B62EB1E3B1007BD342 /* Home */, + 04FC95BE2EB1E3B1007BD342 /* Me */, + ); + path = Class; + sourceTree = ""; + }; + 04FC95C32EB1E4AB007BD342 /* M */ = { + isa = PBXGroup; + children = ( + ); + path = M; + sourceTree = ""; + }; + 04FC95C42EB1E4AB007BD342 /* V */ = { + isa = PBXGroup; + children = ( + 04FC95D32EB1EA16007BD342 /* BaseCell.h */, + 04FC95D42EB1EA16007BD342 /* BaseCell.m */, + 04FC95D52EB1EA16007BD342 /* BaseTableView.h */, + 04FC95D62EB1EA16007BD342 /* BaseTableView.m */, + ); + path = V; + sourceTree = ""; + }; + 04FC95C52EB1E4AB007BD342 /* VC */ = { + isa = PBXGroup; + children = ( + 04FC95C72EB1E4C9007BD342 /* BaseNavigationController.h */, + 04FC95C82EB1E4C9007BD342 /* BaseNavigationController.m */, + 04FC95CA2EB1E780007BD342 /* BaseTabBarController.h */, + 04FC95CB2EB1E780007BD342 /* BaseTabBarController.m */, + ); + path = VC; + sourceTree = ""; + }; + 04FC95C62EB1E4AB007BD342 /* Base */ = { + isa = PBXGroup; + children = ( + 04FC95C32EB1E4AB007BD342 /* M */, + 04FC95C42EB1E4AB007BD342 /* V */, + 04FC95C52EB1E4AB007BD342 /* VC */, + ); + path = Base; + sourceTree = ""; + }; + 04FC95DE2EB20AD1007BD342 /* M */ = { + isa = PBXGroup; + children = ( + ); + path = M; + sourceTree = ""; + }; + 04FC95DF2EB20AD1007BD342 /* V */ = { + isa = PBXGroup; + children = ( + 04FC96FE2EB30A00007BD342 /* KBGuideTopCell.h */, + 04FC96FF2EB30A00007BD342 /* KBGuideTopCell.m */, + 04FC97012EB30A00007BD342 /* KBGuideKFCell.h */, + 04FC97022EB30A00007BD342 /* KBGuideKFCell.m */, + 04FC97042EB30A00007BD342 /* KBGuideUserCell.h */, + 04FC97052EB30A00007BD342 /* KBGuideUserCell.m */, + ); + path = V; + sourceTree = ""; + }; + 04FC95E02EB20AD1007BD342 /* VC */ = { + isa = PBXGroup; + children = ( + 04FC95DB2EB202A3007BD342 /* KBGuideVC.h */, + 04FC95DC2EB202A3007BD342 /* KBGuideVC.m */, + ); + path = VC; + sourceTree = ""; + }; + 04FC95E12EB20AD1007BD342 /* Guard */ = { + isa = PBXGroup; + children = ( + 04FC95DE2EB20AD1007BD342 /* M */, + 04FC95DF2EB20AD1007BD342 /* V */, + 04FC95E02EB20AD1007BD342 /* VC */, + ); + path = Guard; + sourceTree = ""; + }; + 04FC95E22EB2208F007BD342 /* Categories */ = { + isa = PBXGroup; + children = ( + 04FC95E32EB220B5007BD342 /* UIColor+Extension.h */, + 04FC95E42EB220B5007BD342 /* UIColor+Extension.m */, + 04FC970A2EB334F8007BD342 /* UIImageView+KBWebImage.h */, + 04FC970B2EB334F8007BD342 /* UIImageView+KBWebImage.m */, + 04FC970C2EB334F8007BD342 /* KBWebImageManager.h */, + 04FC970D2EB334F8007BD342 /* KBWebImageManager.m */, + 04FC97072EB31B14007BD342 /* KBHUD.h */, + 04FC97082EB31B14007BD342 /* KBHUD.m */, + 04A9FE142EB873C80020DB6D /* UIViewController+Extension.h */, + 04A9FE152EB873C80020DB6D /* UIViewController+Extension.m */, + ); + path = Categories; + sourceTree = ""; + }; + 04FC95E82EB23B67007BD342 /* Network */ = { + isa = PBXGroup; + children = ( + 04FC95E62EB23B67007BD342 /* KBNetworkManager.h */, + 04FC95E72EB23B67007BD342 /* KBNetworkManager.m */, + ); + path = Network; + sourceTree = ""; + }; + 04FC95EA2EB33611007BD342 /* M */ = { + isa = PBXGroup; + children = ( + ); + path = M; + sourceTree = ""; + }; + 04FC95EB2EB33611007BD342 /* V */ = { + isa = PBXGroup; + children = ( + ); + path = V; + sourceTree = ""; + }; + 04FC95EC2EB33611007BD342 /* VC */ = { + isa = PBXGroup; + children = ( + 04FC95EF2EB339A7007BD342 /* LoginViewController.h */, + 04FC95F02EB339A7007BD342 /* LoginViewController.m */, + 04FC96112EB34E00007BD342 /* KBLoginSheetViewController.h */, + 04FC96122EB34E00007BD342 /* KBLoginSheetViewController.m */, + ); + path = VC; + sourceTree = ""; + }; + 04FC95ED2EB33611007BD342 /* Login */ = { + isa = PBXGroup; + children = ( + 04FC95EA2EB33611007BD342 /* M */, + 04FC95EB2EB33611007BD342 /* V */, + 04FC95EC2EB33611007BD342 /* VC */, + ); + path = Login; + sourceTree = ""; + }; + 04FC95EE2EB3399D007BD342 /* Manager */ = { + isa = PBXGroup; + children = ( + 04FC95F22EB339C1007BD342 /* AppleSignInManager.h */, + 04FC95F32EB339C1007BD342 /* AppleSignInManager.m */, + ); + path = Manager; + sourceTree = ""; + }; + 04FC98002EB36AAB007BD342 /* Shared */ = { + isa = PBXGroup; + children = ( + 04A9FE1F2EB893F10020DB6D /* Localization */, + 04FC98012EB36AAB007BD342 /* KBConfig.h */, + A1B2C4002EB4A0A100000001 /* KBAuthManager.h */, + A1B2C4002EB4A0A100000002 /* KBAuthManager.m */, + A1B2C4232EB4B7A100000001 /* KBKeyboardPermissionManager.h */, + A1B2C4222EB4B7A100000001 /* KBKeyboardPermissionManager.m */, + 04A9FE182EB892460020DB6D /* KBLocalizationManager.h */, + 04A9FE192EB892460020DB6D /* KBLocalizationManager.m */, + ); + path = Shared; sourceTree = ""; }; 2C53A0856097DCFBE7B55649 /* Pods */ = { @@ -249,6 +609,7 @@ children = ( 04C6EAB92EAF86530089C901 /* keyBoard */, 04C6EAD72EAF870B0089C901 /* CustomKeyboard */, + 04FC98002EB36AAB007BD342 /* Shared */, 727EC7542EAF848B00B36487 /* Products */, 2C53A0856097DCFBE7B55649 /* Pods */, 6E26572F95DCFDA6A6644133 /* Frameworks */, @@ -264,6 +625,15 @@ name = Products; sourceTree = ""; }; + A1B2C3E52EB0C0A100000001 /* Network */ = { + isa = PBXGroup; + children = ( + A1B2C3E02EB0C0A100000001 /* KBNetworkManager.h */, + A1B2C3E12EB0C0A100000001 /* KBNetworkManager.m */, + ); + path = Network; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -330,6 +700,7 @@ knownRegions = ( en, Base, + "zh-Hans", ); mainGroup = 727EC74A2EAF848B00B36487; minimizedProjectReferenceProxies = 1; @@ -349,8 +720,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 04FC95622EAFAF51007BD342 /* LICENSE in Resources */, - 04FC95632EAFAF51007BD342 /* README.md in Resources */, + 04A9FE202EB893F10020DB6D /* Localizable.strings in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -359,6 +729,7 @@ buildActionMask = 2147483647; files = ( 04C6EABA2EAF86530089C901 /* Assets.xcassets in Resources */, + 04A9FE212EB893F10020DB6D /* Localizable.strings in Resources */, 04C6EABC2EAF86530089C901 /* LaunchScreen.storyboard in Resources */, 04C6EABD2EAF86530089C901 /* Main.storyboard in Resources */, ); @@ -439,18 +810,24 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 04A9FE0F2EB481100020DB6D /* KBHUD.m in Sources */, 04C6EADD2EAF8CEB0089C901 /* KBToolBar.m in Sources */, + 04FC95792EB09BC8007BD342 /* KBKeyBoardMainView.m in Sources */, + 04FC95732EB09570007BD342 /* KBFunctionBarView.m in Sources */, 04C6EAD82EAF870B0089C901 /* KeyboardViewController.m in Sources */, - 04FC95582EAFAF51007BD342 /* MASConstraintMaker.m in Sources */, - 04FC95592EAFAF51007BD342 /* MASViewConstraint.m in Sources */, - 04FC955A2EAFAF51007BD342 /* MASViewAttribute.m in Sources */, - 04FC955B2EAFAF51007BD342 /* NSArray+MASAdditions.m in Sources */, - 04FC955C2EAFAF51007BD342 /* View+MASAdditions.m in Sources */, - 04FC955D2EAFAF51007BD342 /* MASCompositeConstraint.m in Sources */, - 04FC955E2EAFAF51007BD342 /* MASConstraint.m in Sources */, - 04FC955F2EAFAF51007BD342 /* NSLayoutConstraint+MASDebugAdditions.m in Sources */, - 04FC95602EAFAF51007BD342 /* MASLayoutConstraint.m in Sources */, - 04FC95612EAFAF51007BD342 /* ViewController+MASAdditions.m in Sources */, + 04FC95762EB095DE007BD342 /* KBFunctionPasteView.m in Sources */, + A1B2C3D42EB0A0A100000001 /* KBFunctionTagCell.m in Sources */, + 04A9FE1A2EB892460020DB6D /* KBLocalizationManager.m in Sources */, + A1B2C3E22EB0C0A100000001 /* KBNetworkManager.m in Sources */, + 04FC956A2EB05497007BD342 /* KBKeyButton.m in Sources */, + 04FC95B22EB0B2CC007BD342 /* KBSettingView.m in Sources */, + 04FC95702EB09516007BD342 /* KBFunctionView.m in Sources */, + 04FC956D2EB054B7007BD342 /* KBKeyboardView.m in Sources */, + 04FC95672EB0546C007BD342 /* KBKey.m in Sources */, + A1B2C3F42EB35A9900000001 /* KBFullAccessGuideView.m in Sources */, + A1B2C4002EB4A0A100000003 /* KBAuthManager.m in Sources */, + 04A9FE132EB4D0D20020DB6D /* KBFullAccessManager.m in Sources */, + A1B2C4202EB4B7A100000001 /* KBKeyboardPermissionManager.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -458,10 +835,33 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 04FC95E92EB23B67007BD342 /* KBNetworkManager.m in Sources */, + 04FC95D22EB1E7AE007BD342 /* MyVC.m in Sources */, 043FBCD22EAF97630036AFE1 /* KBPermissionViewController.m in Sources */, + 04A9FE162EB873C80020DB6D /* UIViewController+Extension.m in Sources */, 04C6EABE2EAF86530089C901 /* AppDelegate.m in Sources */, + 04FC95F12EB339A7007BD342 /* LoginViewController.m in Sources */, + 04FC96142EB34E00007BD342 /* KBLoginSheetViewController.m in Sources */, + 04A9FE1B2EB892460020DB6D /* KBLocalizationManager.m in Sources */, + 04FC95D72EB1EA16007BD342 /* BaseTableView.m in Sources */, + 04FC95D82EB1EA16007BD342 /* BaseCell.m in Sources */, + 04FC95C92EB1E4C9007BD342 /* BaseNavigationController.m in Sources */, + 04FC95DD2EB202A3007BD342 /* KBGuideVC.m in Sources */, + 04FC95E52EB220B5007BD342 /* UIColor+Extension.m in Sources */, + 04FC97002EB30A00007BD342 /* KBGuideTopCell.m in Sources */, + 04FC97032EB30A00007BD342 /* KBGuideKFCell.m in Sources */, + 04FC97062EB30A00007BD342 /* KBGuideUserCell.m in Sources */, + 04FC97092EB31B14007BD342 /* KBHUD.m in Sources */, + 04FC970E2EB334F8007BD342 /* UIImageView+KBWebImage.m in Sources */, + 04FC970F2EB334F8007BD342 /* KBWebImageManager.m in Sources */, + 04FC95CF2EB1E7A1007BD342 /* HomeVC.m in Sources */, + A1B2D7022EB8C00100000001 /* KBLangTestVC.m in Sources */, 04C6EABF2EAF86530089C901 /* main.m in Sources */, + 04FC95CC2EB1E780007BD342 /* BaseTabBarController.m in Sources */, + 04FC95F42EB339C1007BD342 /* AppleSignInManager.m in Sources */, 04C6EAC12EAF86530089C901 /* ViewController.m in Sources */, + A1B2C4002EB4A0A100000004 /* KBAuthManager.m in Sources */, + A1B2C4212EB4B7A100000001 /* KBKeyboardPermissionManager.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -476,6 +876,15 @@ /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ + 04A9FE1E2EB893F10020DB6D /* Localizable.strings */ = { + isa = PBXVariantGroup; + children = ( + 04A9FE1C2EB893F10020DB6D /* en */, + 04A9FE1D2EB893F10020DB6D /* zh-Hans */, + ); + name = Localizable.strings; + sourceTree = ""; + }; 04C6EAB12EAF86530089C901 /* LaunchScreen.storyboard */ = { isa = PBXVariantGroup; children = ( @@ -499,11 +908,16 @@ isa = XCBuildConfiguration; baseConfigurationReference = B8CA018AB878499327504AAD /* Pods-CustomKeyboard.debug.xcconfig */; buildSettings = { + CODE_SIGN_ENTITLEMENTS = CustomKeyboard/CustomKeyboard.entitlements; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = CBD35U2N52; + DEVELOPMENT_TEAM = UFX79H8H66; ENABLE_USER_SCRIPT_SANDBOXING = NO; GCC_PREFIX_HEADER = CustomKeyboard/PrefixHeader.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "KB_KEYCHAIN_ACCESS_GROUP=@\\\"$(AppIdentifierPrefix)com.keyBoardst.shared\\\"", + ); GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = CustomKeyboard/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "我的输入法"; @@ -515,7 +929,7 @@ "@executable_path/../../Frameworks", ); MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.keyBoard.CustomKeyboard; + PRODUCT_BUNDLE_IDENTIFIER = com.loveKey.nyx.CustomKeyboard; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; @@ -527,11 +941,16 @@ isa = XCBuildConfiguration; baseConfigurationReference = B12EC429812407B9F0E67565 /* Pods-CustomKeyboard.release.xcconfig */; buildSettings = { + CODE_SIGN_ENTITLEMENTS = CustomKeyboard/CustomKeyboard.entitlements; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = CBD35U2N52; + DEVELOPMENT_TEAM = UFX79H8H66; ENABLE_USER_SCRIPT_SANDBOXING = NO; GCC_PREFIX_HEADER = CustomKeyboard/PrefixHeader.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "KB_KEYCHAIN_ACCESS_GROUP=@\\\"$(AppIdentifierPrefix)com.keyBoardst.shared\\\"", + ); GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = CustomKeyboard/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "我的输入法"; @@ -543,7 +962,7 @@ "@executable_path/../../Frameworks", ); MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.keyBoard.CustomKeyboard; + PRODUCT_BUNDLE_IDENTIFIER = com.loveKey.nyx.CustomKeyboard; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; @@ -557,13 +976,20 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = keyBoard/keyBoard.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = CBD35U2N52; + DEVELOPMENT_TEAM = UFX79H8H66; GCC_PREFIX_HEADER = keyBoard/KeyBoardPrefixHeader.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "KB_KEYCHAIN_ACCESS_GROUP=@\\\"$(AppIdentifierPrefix)com.keyBoardst.shared\\\"", + ); GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = keyBoard/Info.plist; - INFOPLIST_KEY_CFBundleDisplayName = "我的输入法"; + INFOPLIST_KEY_CFBundleDisplayName = "YOLO输入法"; + INFOPLIST_KEY_CFBundleURLTypes = "{\n CFBundleURLName = \"com.keyBoardst.keyboard\";\n CFBundleURLSchemes = (\n kbkeyboard\n );\n}"; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; INFOPLIST_KEY_UIMainStoryboardFile = Main; @@ -575,8 +1001,9 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.keyBoard; + PRODUCT_BUNDLE_IDENTIFIER = com.loveKey.nyx; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_EMIT_LOC_STRINGS = YES; TARGETED_DEVICE_FAMILY = "1,2"; @@ -589,13 +1016,20 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = keyBoard/keyBoard.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = CBD35U2N52; + DEVELOPMENT_TEAM = UFX79H8H66; GCC_PREFIX_HEADER = keyBoard/KeyBoardPrefixHeader.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "KB_KEYCHAIN_ACCESS_GROUP=@\\\"$(AppIdentifierPrefix)com.keyBoardst.shared\\\"", + ); GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = keyBoard/Info.plist; - INFOPLIST_KEY_CFBundleDisplayName = "我的输入法"; + INFOPLIST_KEY_CFBundleDisplayName = "YOLO输入法"; + INFOPLIST_KEY_CFBundleURLTypes = "{\n CFBundleURLName = \"com.keyBoardst.keyboard\";\n CFBundleURLSchemes = (\n kbkeyboard\n );\n}"; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; INFOPLIST_KEY_UIMainStoryboardFile = Main; @@ -607,8 +1041,9 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.keyBoard; + PRODUCT_BUNDLE_IDENTIFIER = com.loveKey.nyx; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_EMIT_LOC_STRINGS = YES; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/keyBoard.xcworkspace/xcuserdata/mac.xcuserdatad/IDEFindNavigatorScopes.plist b/keyBoard.xcworkspace/xcuserdata/mac.xcuserdatad/IDEFindNavigatorScopes.plist new file mode 100644 index 0000000..5dd5da8 --- /dev/null +++ b/keyBoard.xcworkspace/xcuserdata/mac.xcuserdatad/IDEFindNavigatorScopes.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/keyBoard/AppDelegate.m b/keyBoard/AppDelegate.m index 7bae424..6e94da7 100644 --- a/keyBoard/AppDelegate.m +++ b/keyBoard/AppDelegate.m @@ -6,21 +6,28 @@ // #import "AppDelegate.h" -#import "ViewController.h" #import "KBPermissionViewController.h" #import #import -static NSString * const kKBKeyboardExtensionBundleId = @"com.keyBoard.CustomKeyboard"; +#import "BaseTabBarController.h" +#import "LoginViewController.h" +#import "KBLoginSheetViewController.h" +#import "AppleSignInManager.h" +#import + +// 注意:用于判断系统已启用本输入法扩展的 bundle id 需与扩展 target 的 +// PRODUCT_BUNDLE_IDENTIFIER 完全一致。 +// 当前工程的 CustomKeyboard target 为 com.keyBoardst.CustomKeyboard +static NSString * const kKBKeyboardExtensionBundleId = @"com.keyBoardst.CustomKeyboard"; @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; - self.window.backgroundColor = [UIColor whiteColor]; - [self.window makeKeyAndVisible]; - ViewController *vc = [[ViewController alloc] init]; - self.window.rootViewController = vc; + + [self setupRootVC]; + // 主工程默认开启网络总开关(键盘扩展仍需用户允许完全访问后再行开启) + [KBNetworkManager shared].enabled = YES; /// 获取网络权限 [self getNetJudge]; /// Bugly @@ -28,42 +35,68 @@ static NSString * const kKBKeyboardExtensionBundleId = @"com.keyBoard.CustomKeyb /// 设置GroupID进行配置 // buglyConfig.applicationGroupIdentifier = @""; [Bugly startWithAppId:BuglyId config:buglyConfig]; - /// 判断获取键盘权限 - dispatch_async(dispatch_get_main_queue(), ^{ - [self kb_presentPermissionIfNeeded]; - }); + // 键盘权限引导改由 KBGuideVC 内部负责;此处不主动弹出。 return YES; } +- (void)applicationDidBecomeActive:(UIApplication *)application{} + + +- (void)setupRootVC{ + self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; + self.window.backgroundColor = [UIColor whiteColor]; + [self.window makeKeyAndVisible]; + BaseTabBarController *vc = [[BaseTabBarController alloc] init]; + self.window.rootViewController = vc; +} + #pragma mark - Permission presentation -- (UIViewController *)kb_topMostViewController -{ - UIViewController *root = self.window.rootViewController; - if (!root) return nil; - UIViewController *top = root; - while (top.presentedViewController) { - top = top.presentedViewController; + +#pragma mark - Deep Link + +// iOS 9+ +- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)options { + if (!url) return NO; + if ([[url.scheme lowercaseString] isEqualToString:@"kbkeyboard"]) { + NSString *urlHost = url.host ?: @""; + NSString *host = [urlHost lowercaseString]; + if ([host isEqualToString:@"login"]) { // kbkeyboard://login + [self kb_presentLoginSheetIfNeeded]; + return YES; + } else if ([host isEqualToString:@"settings"]) { // kbkeyboard://settings + [self kb_openAppSettings]; + return YES; + } + return NO; + } + return NO; +} + +- (void)kb_presentLoginSheetIfNeeded { + // 已登录则不提示 + BOOL loggedIn = ([AppleSignInManager shared].storedUserIdentifier.length > 0); + if (loggedIn) return; + UIViewController *top = [UIViewController kb_topMostViewController]; + if (!top) return; + [KBLoginSheetViewController presentIfNeededFrom:top]; +} + +- (void)kb_openAppSettings { + NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString]; + UIApplication *app = [UIApplication sharedApplication]; + if ([app canOpenURL:url]) { + if (@available(iOS 10.0, *)) { + [app openURL:url options:@{} completionHandler:nil]; + } else { + [app openURL:url]; + } } - return top; } - (void)kb_presentPermissionIfNeeded { - BOOL enabled = KBIsKeyboardEnabled(); - UIViewController *top = [self kb_topMostViewController]; - if (!top) return; - if ([top isKindOfClass:[KBPermissionViewController class]]) { - if (enabled) { - [top dismissViewControllerAnimated:YES completion:nil]; - } - return; - } - if (!enabled) { - KBPermissionViewController *guide = [KBPermissionViewController new]; - guide.modalPresentationStyle = UIModalPresentationFullScreen; - [top presentViewController:guide animated:YES completion:nil]; - } + // 该逻辑已迁移到 KBGuideVC,保留占位以兼容旧调用,但不再执行任何操作 } diff --git a/keyBoard/Assets.xcassets/back_black_icon.imageset/Contents.json b/keyBoard/Assets.xcassets/back_black_icon.imageset/Contents.json new file mode 100644 index 0000000..79099b2 --- /dev/null +++ b/keyBoard/Assets.xcassets/back_black_icon.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "back@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "back@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/back_black_icon.imageset/back@2x.png b/keyBoard/Assets.xcassets/back_black_icon.imageset/back@2x.png new file mode 100644 index 0000000..a41e24c Binary files /dev/null and b/keyBoard/Assets.xcassets/back_black_icon.imageset/back@2x.png differ diff --git a/keyBoard/Assets.xcassets/back_black_icon.imageset/back@3x.png b/keyBoard/Assets.xcassets/back_black_icon.imageset/back@3x.png new file mode 100644 index 0000000..0e61428 Binary files /dev/null and b/keyBoard/Assets.xcassets/back_black_icon.imageset/back@3x.png differ diff --git a/keyBoard/Class/Base/V/BaseCell.h b/keyBoard/Class/Base/V/BaseCell.h new file mode 100644 index 0000000..868d274 --- /dev/null +++ b/keyBoard/Class/Base/V/BaseCell.h @@ -0,0 +1,23 @@ +// +// BaseCell.h +// keyBoard +// +// Common base cell with default selection style and hook for setup. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface BaseCell : UITableViewCell + +/// Convenience reuse identifier based on class name ++ (NSString *)reuseId; + +/// Override point to add subviews and constraints +- (void)setupUI; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/keyBoard/Class/Base/V/BaseCell.m b/keyBoard/Class/Base/V/BaseCell.m new file mode 100644 index 0000000..f13ec2e --- /dev/null +++ b/keyBoard/Class/Base/V/BaseCell.m @@ -0,0 +1,32 @@ +// +// BaseCell.m +// keyBoard +// + +#import "BaseCell.h" + +@implementation BaseCell + ++ (NSString *)reuseId { + return NSStringFromClass(self); +} + +- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { + if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { + self.selectionStyle = UITableViewCellSelectionStyleNone; + [self setupUI]; + } + return self; +} + +- (void)prepareForReuse { + [super prepareForReuse]; + // Reset state if needed by subclasses +} + +- (void)setupUI { + // Subclasses override to build UI +} + +@end + diff --git a/keyBoard/Class/Base/V/BaseTableView.h b/keyBoard/Class/Base/V/BaseTableView.h new file mode 100644 index 0000000..9395838 --- /dev/null +++ b/keyBoard/Class/Base/V/BaseTableView.h @@ -0,0 +1,45 @@ +// +// BaseTableView.h +// keyBoard +// +// 通用表格基类: +// - 统一一些默认配置(背景色、分割线、键盘收起等) +// - 可选接入 DZNEmptyDataSet(空数据占位视图),默认开启,按需关闭 +// - 通过 __has_include 判断三方库是否存在;即使工程未集成该库也能正常编译 +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +typedef void(^KBEmptyAction)(void); + +@interface BaseTableView : UITableView + + +#pragma mark - 空数据占位(DZNEmptyDataSet,可开关) +/// 是否启用空数据占位(默认 YES)。若工程未集成 DZNEmptyDataSet,此开关不生效但不会影响编译。 +@property (nonatomic, assign) BOOL useEmptyDataSet; +/// 标题(默认:"暂无数据") +@property (nonatomic, copy, nullable) NSString *emptyTitleText; +/// 描述(可选) +@property (nonatomic, copy, nullable) NSString *emptyDescriptionText; +/// 占位图(可选) +@property (nonatomic, strong, nullable) UIImage *emptyImage; +/// 按钮标题(可选) +@property (nonatomic, copy, nullable) NSString *emptyButtonTitle; +/// 垂直偏移(默认 0) +@property (nonatomic, assign) CGFloat emptyVerticalOffset; +/// 空视图是否允许滚动(默认 YES) +@property (nonatomic, assign) BOOL emptyShouldAllowScroll; +/// 点击整体视图回调(可选) +@property (nonatomic, copy, nullable) KBEmptyAction emptyDidTapView; +/// 点击按钮回调(可选) +@property (nonatomic, copy, nullable) KBEmptyAction emptyDidTapButton; + +/// 触发刷新空数据视图(若集成了 DZNEmptyDataSet 则调用其 reloadEmptyDataSet) +- (void)kb_reloadEmptyDataSet; + +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Base/V/BaseTableView.m b/keyBoard/Class/Base/V/BaseTableView.m new file mode 100644 index 0000000..0d743e3 --- /dev/null +++ b/keyBoard/Class/Base/V/BaseTableView.m @@ -0,0 +1,130 @@ +// +// BaseTableView.m +// keyBoard +// + +#import "BaseTableView.h" + +// 可选引入:若未集成 DZNEmptyDataSet,此处不会编译进来 +#if __has_include() +#import +#define KB_HAS_DZN 1 +#else +#define KB_HAS_DZN 0 +#endif + +@interface BaseTableView () +#if KB_HAS_DZN + +#endif +@end + +@implementation BaseTableView + +- (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style { + if (self = [super initWithFrame:frame style:style]) { + [self commonInit]; + } + return self; +} + + + +- (void)commonInit { + // iOS 15+ 头部默认留白,统一归零(老系统无此属性,不会影响) + self.sectionHeaderTopPadding = 0; + self.backgroundColor = [UIColor whiteColor]; + self.separatorStyle = UITableViewCellSeparatorStyleSingleLine; + self.estimatedRowHeight = 0; + self.estimatedSectionHeaderHeight = 0; + self.estimatedSectionFooterHeight = 0; + self.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag; + + // 空数据占位默认配置(保持“活”的:可开可关) + _useEmptyDataSet = YES; // 默认开启 + _emptyShouldAllowScroll = YES; // 默认允许滚动 + _emptyVerticalOffset = 0; // 默认不偏移 + _emptyTitleText = @"暂无数据"; // 默认标题 + +#if KB_HAS_DZN + self.emptyDataSetSource = self; + self.emptyDataSetDelegate = self; +#endif +} + +#pragma mark - Public + +- (void)kb_reloadEmptyDataSet { +#if KB_HAS_DZN + [self reloadEmptyDataSet]; +#endif +} + +- (void)setUseEmptyDataSet:(BOOL)useEmptyDataSet { + _useEmptyDataSet = useEmptyDataSet; +#if KB_HAS_DZN + // 切换时,动态挂/卸源委托 + self.emptyDataSetSource = useEmptyDataSet ? (id)self : nil; + self.emptyDataSetDelegate = useEmptyDataSet ? (id)self : nil; + [self reloadEmptyDataSet]; +#endif +} + +#pragma mark - DZNEmptyDataSet (仅当库存在时编译) +#if KB_HAS_DZN + +// 是否展示空视图 +- (BOOL)emptyDataSetShouldDisplay:(UIScrollView *)scrollView { + return self.useEmptyDataSet; +} + +// 标题 +- (NSAttributedString *)titleForEmptyDataSet:(UIScrollView *)scrollView { + NSString *title = self.emptyTitleText ?: @""; + NSDictionary *attrs = @{ NSFontAttributeName : [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold], + NSForegroundColorAttributeName : [UIColor colorWithWhite:0.5 alpha:1.0] }; + return [[NSAttributedString alloc] initWithString:title attributes:attrs]; +} + +// 描述 +- (NSAttributedString *)descriptionForEmptyDataSet:(UIScrollView *)scrollView { + if (self.emptyDescriptionText.length == 0) return nil; + NSDictionary *attrs = @{ NSFontAttributeName : [UIFont systemFontOfSize:14], + NSForegroundColorAttributeName : [UIColor colorWithWhite:0.6 alpha:1.0] }; + return [[NSAttributedString alloc] initWithString:self.emptyDescriptionText attributes:attrs]; +} + +// 图片 +- (UIImage *)imageForEmptyDataSet:(UIScrollView *)scrollView { + return self.emptyImage; +} + +// 按钮标题 +- (NSAttributedString *)buttonTitleForEmptyDataSet:(UIScrollView *)scrollView forState:(UIControlState)state { + if (self.emptyButtonTitle.length == 0) return nil; + UIColor *color = (state == UIControlStateHighlighted) ? [UIColor darkTextColor] : [UIColor colorWithRed:0.22 green:0.49 blue:0.96 alpha:1.0]; + NSDictionary *attrs = @{ NSFontAttributeName : [UIFont systemFontOfSize:15 weight:UIFontWeightSemibold], + NSForegroundColorAttributeName : color }; + return [[NSAttributedString alloc] initWithString:self.emptyButtonTitle attributes:attrs]; +} + +// 垂直位置偏移 +- (CGFloat)verticalOffsetForEmptyDataSet:(UIScrollView *)scrollView { + return self.emptyVerticalOffset; +} + +// 行为 +- (BOOL)emptyDataSetShouldAllowScroll:(UIScrollView *)scrollView { return self.emptyShouldAllowScroll; } +- (BOOL)emptyDataSetShouldAllowTouch:(UIScrollView *)scrollView { return YES; } + +- (void)emptyDataSet:(UIScrollView *)scrollView didTapView:(UIView *)view { + if (self.emptyDidTapView) self.emptyDidTapView(); +} + +- (void)emptyDataSet:(UIScrollView *)scrollView didTapButton:(UIButton *)button { + if (self.emptyDidTapButton) self.emptyDidTapButton(); +} + +#endif + +@end diff --git a/keyBoard/Class/Base/VC/BaseNavigationController.h b/keyBoard/Class/Base/VC/BaseNavigationController.h new file mode 100644 index 0000000..dbebd0b --- /dev/null +++ b/keyBoard/Class/Base/VC/BaseNavigationController.h @@ -0,0 +1,16 @@ +// +// BaseNavigationController.h +// keyBoard +// +// Created by Mac on 2025/10/29. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface BaseNavigationController : UINavigationController + +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Base/VC/BaseNavigationController.m b/keyBoard/Class/Base/VC/BaseNavigationController.m new file mode 100644 index 0000000..7e12afe --- /dev/null +++ b/keyBoard/Class/Base/VC/BaseNavigationController.m @@ -0,0 +1,44 @@ +// +// BaseNavigationController.m +// keyBoard +// +// Created by Mac on 2025/10/29. +// + +#import "BaseNavigationController.h" + +@interface BaseNavigationController () + +@end + +@implementation BaseNavigationController + +- (void)viewDidLoad { + [super viewDidLoad]; + // 统一返回箭头样式与颜色 + UIImage *backImg = [UIImage imageNamed:@"back_black_icon"]; + if (backImg) { + self.navigationBar.backIndicatorImage = backImg; + self.navigationBar.backIndicatorTransitionMaskImage = backImg; + } + self.navigationBar.tintColor = [UIColor blackColor]; // 箭头/按钮的着色 + + if (@available(iOS 14.0, *)) { + self.navigationBar.topItem.backButtonDisplayMode = UINavigationItemBackButtonDisplayModeMinimal; + } +} + +- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated{ + if (self.viewControllers.count > 0) { + viewController.hidesBottomBarWhenPushed = true; + UIViewController *prev = self.topViewController; + if (@available(iOS 14.0, *)) { + prev.navigationItem.backButtonDisplayMode = UINavigationItemBackButtonDisplayModeMinimal; + } else { + prev.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil]; + } + } + [super pushViewController:viewController animated:animated]; +} + +@end diff --git a/keyBoard/Class/Base/VC/BaseTabBarController.h b/keyBoard/Class/Base/VC/BaseTabBarController.h new file mode 100644 index 0000000..b2a25ef --- /dev/null +++ b/keyBoard/Class/Base/VC/BaseTabBarController.h @@ -0,0 +1,16 @@ +// +// BaseTabBarController.h +// keyBoard +// +// Created by Mac on 2025/10/29. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface BaseTabBarController : UITabBarController + +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Base/VC/BaseTabBarController.m b/keyBoard/Class/Base/VC/BaseTabBarController.m new file mode 100644 index 0000000..68bd70b --- /dev/null +++ b/keyBoard/Class/Base/VC/BaseTabBarController.m @@ -0,0 +1,47 @@ +// +// BaseTabBarController.m +// keyBoard +// +// Created by Mac on 2025/10/29. +// + +#import "BaseTabBarController.h" +#import "HomeVC.h" +#import "MyVC.h" +#import "BaseNavigationController.h" +#import "KBAuthManager.h" +@interface BaseTabBarController () + +@end + +@implementation BaseTabBarController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Setup two tabs: Home & My, each embedded in BaseNavigationController + HomeVC *home = [[HomeVC alloc] init]; + home.title = @"首页"; + BaseNavigationController *navHome = [[BaseNavigationController alloc] initWithRootViewController:home]; + navHome.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"首页" image:nil selectedImage:nil]; + + MyVC *my = [[MyVC alloc] init]; + my.title = @"我的"; + BaseNavigationController *navMy = [[BaseNavigationController alloc] initWithRootViewController:my]; + navMy.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"我的" image:nil selectedImage:nil]; + + self.viewControllers = @[navHome, navMy]; + + [[KBAuthManager shared] saveAccessToken:@"TEST" refreshToken:nil expiryDate:[NSDate dateWithTimeIntervalSinceNow:3600] userIdentifier:nil]; +} + +/* +#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/KBHUD.h b/keyBoard/Class/Categories/KBHUD.h new file mode 100644 index 0000000..06a65d2 --- /dev/null +++ b/keyBoard/Class/Categories/KBHUD.h @@ -0,0 +1,72 @@ +// +// KBHUD.h +// keyBoard +// +// 基于 MBProgressHUD 的轻量封装,提供类似 SVProgressHUD 的类方法调用方式。 +// 特性: +// - 默认加到 KeyWindow 上 +// - 支持遮罩模式(不拦截/透明拦截/半透明黑遮罩) +// - 默认不支持点击背景关闭;可为“本次显示/当前 HUD”开启点击关闭 +// - 文案/加载/进度/自动消失 +// + +#import +@class UIView; // forward declare to avoid importing UIKit in header + +typedef NS_ENUM(NSUInteger, KBHUDMaskType) { + /// 不加遮罩,事件可透传到后面的视图(与 SVProgressHUDMaskTypeNone 类似) + KBHUDMaskTypeNone = 0, + /// 透明遮罩,拦截触摸但不变暗(与 SVProgressHUDMaskTypeClear 类似) + KBHUDMaskTypeClear, + /// 半透明黑色遮罩(与 SVProgressHUDMaskTypeBlack 类似) + KBHUDMaskTypeBlack, +}; + +NS_ASSUME_NONNULL_BEGIN + +@interface KBHUD : NSObject + +#pragma mark - 显示 +/// 纯菊花 ++ (void)show; +/// 菊花 + 文案 ++ (void)showWithStatus:(nullable NSString *)status; +/// 菊花 + 文案(可配置:是否允许点击背景关闭) ++ (void)showWithStatus:(nullable NSString *)status allowTapToDismiss:(BOOL)allow; +/// 圆形进度 0~1 + 文案 ++ (void)showProgress:(float)progress status:(nullable NSString *)status; +/// 圆形进度 0~1 + 文案(可配置:是否允许点击背景关闭) ++ (void)showProgress:(float)progress status:(nullable NSString *)status allowTapToDismiss:(BOOL)allow; +/// 文案提示(自动隐藏) ++ (void)showInfo:(NSString *)status; +/// 成功提示(自动隐藏) ++ (void)showSuccess:(NSString *)status; +/// 失败提示(自动隐藏) ++ (void)showError:(NSString *)status; + +#pragma mark - 隐藏 +/// 立即隐藏 ++ (void)dismiss; +/// 延时隐藏 ++ (void)dismissWithDelay:(NSTimeInterval)delay; + +#pragma mark - 配置(全局) +/// 设置默认遮罩类型,默认 KBHUDMaskTypeClear ++ (void)setDefaultMaskType:(KBHUDMaskType)maskType; +/// 为“当前正在展示的 HUD”设置点击背景是否关闭;若当前没有 HUD 则忽略 ++ (void)setTapToDismissEnabled:(BOOL)enabled; +/// 仅本次显示:菊花(无文案)可配置是否允许点击背景关闭 ++ (void)showAllowTapToDismiss:(BOOL)allow; +/// 设置自动隐藏的时长(success/error/info),默认 1.2s ++ (void)setAutoDismissInterval:(NSTimeInterval)interval; + +/// 设置缺省承载视图(App Extension 环境下必须设置,例如在键盘扩展里传入 self.view) +/// 注意:内部弱引用,不会形成循环引用。 +/// 若不设置,在非 Extension 的 App 内默认加到 KeyWindow;在 Extension 内将不会显示。 +/// 可在 viewDidLoad 或 viewDidAppear 调用一次即可。 +/// @param view 作为 HUD 的承载父视图 + + (void)setContainerView:(nullable UIView *)view; + +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Categories/KBHUD.m b/keyBoard/Class/Categories/KBHUD.m new file mode 100644 index 0000000..2d1f399 --- /dev/null +++ b/keyBoard/Class/Categories/KBHUD.m @@ -0,0 +1,200 @@ +// +// KBHUD.m +// keyBoard +// + +#import "KBHUD.h" +#import +#import + +#ifndef KBSCREEN +#define KBSCREEN [UIScreen mainScreen].bounds.size +#endif + +@implementation KBHUD + +static __weak MBProgressHUD *sHUD = nil; +static KBHUDMaskType sMaskType = KBHUDMaskTypeClear; // 全局默认遮罩 +static BOOL sDefaultTapToDismiss = NO; // 全局默认:不允许点击关闭 +static NSTimeInterval sAutoDismiss = 1.2; +static __weak UIView *sContainerView = nil; // 缺省承载视图(扩展里必须设置) + +#pragma mark - Private Helpers + ++ (void)onMain:(dispatch_block_t)blk { + if (NSThread.isMainThread) { blk(); } else { dispatch_async(dispatch_get_main_queue(), blk); } +} + ++ (MBProgressHUD *)ensureHUDWithMask:(KBHUDMaskType)mask tap:(BOOL)tap { + // 先尝试使用外部指定的容器视图(扩展环境推荐) + UIView *hostView = sContainerView; +#ifndef KB_APP_EXTENSION + // App 内退回到 KeyWindow + if (!hostView) { + // KB_KeyWindow 在 App 目标的 PrefixHeader 中定义;在扩展内不依赖它 + UIWindow *win = nil; + // 避免强依赖某个前缀:这里以运行时方式访问 UIApplication 以规避编译期的 App Extension 限制 + Class uiAppClass = NSClassFromString(@"UIApplication"); + if (uiAppClass && [uiAppClass respondsToSelector:@selector(sharedApplication)]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + id app = [uiAppClass performSelector:@selector(sharedApplication)]; + if ([app respondsToSelector:@selector(keyWindow)]) { + win = [app keyWindow]; + } + if (!win && [app respondsToSelector:@selector(windows)]) { + NSArray *wins = [app windows]; + win = wins.firstObject; + } +#pragma clang diagnostic pop + } + hostView = win; + } +#endif + + if (!hostView) { return nil; } + + MBProgressHUD *hud = sHUD; + if (!hud) { + hud = [MBProgressHUD showHUDAddedTo:hostView animated:YES]; + sHUD = hud; + // 外观:深色圆角,白色文字,模仿 SVProgressHUD 默认 + hud.removeFromSuperViewOnHide = YES; + hud.bezelView.style = MBProgressHUDBackgroundStyleSolidColor; + hud.bezelView.layer.cornerRadius = 12.0; + hud.bezelView.color = [UIColor colorWithWhite:0 alpha:0.8]; + hud.contentColor = UIColor.whiteColor; + hud.margin = 16; + hud.label.numberOfLines = 0; + hud.detailsLabel.numberOfLines = 0; + } + // 遮罩与交互(按本次 show 的入参应用) + [self applyMaskType:mask hud:hud]; + [self applyTapToDismiss:tap hud:hud]; + return hud; +} + ++ (void)applyMaskType:(KBHUDMaskType)type hud:(MBProgressHUD *)hud { + switch (type) { + case KBHUDMaskTypeNone: { + hud.userInteractionEnabled = NO; // 不拦截触摸 + hud.backgroundView.style = MBProgressHUDBackgroundStyleSolidColor; + hud.backgroundView.color = UIColor.clearColor; + } break; + case KBHUDMaskTypeClear: { + hud.userInteractionEnabled = YES; // 拦截触摸但不变暗 + hud.backgroundView.style = MBProgressHUDBackgroundStyleSolidColor; + hud.backgroundView.color = [UIColor colorWithWhite:0 alpha:0.01]; + } break; + case KBHUDMaskTypeBlack: { + hud.userInteractionEnabled = YES; // 变暗并拦截 + hud.backgroundView.style = MBProgressHUDBackgroundStyleSolidColor; + hud.backgroundView.color = [UIColor colorWithWhite:0 alpha:0.35]; + } break; + } +} + ++ (void)applyTapToDismiss:(BOOL)enabled hud:(MBProgressHUD *)hud { + UIView *bg = hud.backgroundView; + // 清理旧手势 + for (UIGestureRecognizer *g in bg.gestureRecognizers.copy) { + if ([g isKindOfClass:UITapGestureRecognizer.class] && g.view == bg) { + [bg removeGestureRecognizer:g]; + } + } + if (enabled) { + UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(_kb_handleTap)]; + [bg addGestureRecognizer:tap]; + // 确保可拦截 + hud.userInteractionEnabled = YES; + if (hud.backgroundView.color == UIColor.clearColor) { + hud.backgroundView.color = [UIColor colorWithWhite:0 alpha:0.01]; + } + } +} + ++ (void)_kb_handleTap { + [self dismiss]; +} + ++ (void)_showText:(NSString *)text icon:(nullable UIImage *)icon { + [self onMain:^{ + MBProgressHUD *hud = [self ensureHUDWithMask:sMaskType tap:sDefaultTapToDismiss]; + if (!hud) { return; } + hud.mode = icon ? MBProgressHUDModeCustomView : MBProgressHUDModeText; + hud.label.text = text ?: @""; + hud.detailsLabel.text = nil; + if (icon) { + UIImageView *iv = [[UIImageView alloc] initWithImage:icon]; + hud.customView = iv; + } else { + hud.customView = nil; + } + [hud hideAnimated:YES afterDelay:sAutoDismiss]; + }]; +} + +#pragma mark - Public API + ++ (void)show { [self showWithStatus:nil]; } + ++ (void)showWithStatus:(NSString *)status { [self showWithStatus:status allowTapToDismiss:NO]; } + ++ (void)showWithStatus:(NSString *)status allowTapToDismiss:(BOOL)allow { + [self onMain:^{ + MBProgressHUD *hud = [self ensureHUDWithMask:sMaskType tap:allow]; + if (!hud) { return; } + hud.mode = MBProgressHUDModeIndeterminate; + hud.label.text = status ?: @""; + }]; +} + ++ (void)showProgress:(float)progress status:(NSString *)status { + [self showProgress:progress status:status allowTapToDismiss:NO]; +} + ++ (void)showProgress:(float)progress status:(NSString *)status allowTapToDismiss:(BOOL)allow { + [self onMain:^{ + MBProgressHUD *hud = [self ensureHUDWithMask:sMaskType tap:allow]; + if (!hud) { return; } + hud.mode = MBProgressHUDModeDeterminate; + hud.progress = progress; + hud.label.text = status ?: @""; + }]; +} + ++ (void)showInfo:(NSString *)status { + [self _showText:status icon:nil]; +} + ++ (void)showSuccess:(NSString *)status { + // 简单起见,使用文字模式;如需图标,可替换为自定义勾勾图片 + [self _showText:status ?: @"成功" icon:nil]; +} + ++ (void)showError:(NSString *)status { [self _showText:status ?: @"失败" icon:nil]; } + ++ (void)dismiss { [self onMain:^{ [sHUD hideAnimated:YES]; }]; } + ++ (void)dismissWithDelay:(NSTimeInterval)delay { [self onMain:^{ [sHUD hideAnimated:YES afterDelay:delay]; }]; } + +#pragma mark - Config + ++ (void)setDefaultMaskType:(KBHUDMaskType)maskType { sMaskType = maskType; } ++ (void)setTapToDismissEnabled:(BOOL)enabled { + // 仅针对当前可见 HUD 生效,不修改默认值,满足“B 允许点击,A 默认不允许”的诉求 + [self onMain:^{ + if (sHUD) { [self applyTapToDismiss:enabled hud:sHUD]; } + }]; +} ++ (void)setAutoDismissInterval:(NSTimeInterval)interval { sAutoDismiss = MAX(0.2, interval); } + ++ (void)showAllowTapToDismiss:(BOOL)allow { + [self showWithStatus:nil allowTapToDismiss:allow]; +} + ++ (void)setContainerView:(UIView *)view { + sContainerView = view; +} + +@end diff --git a/keyBoard/Class/Categories/KBWebImageManager.h b/keyBoard/Class/Categories/KBWebImageManager.h new file mode 100644 index 0000000..ce81b7e --- /dev/null +++ b/keyBoard/Class/Categories/KBWebImageManager.h @@ -0,0 +1,31 @@ +// +// KBWebImageManager.h +// keyBoard +// +// SDWebImage 的二次封装:全局配置、预取、缓存管理 +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface KBWebImageManager : NSObject + +/// 预取一组图片 ++ (void)prefetchURLs:(NSArray *)urlList + progress:(void(^_Nullable)(NSUInteger finished, NSUInteger total))progress + completed:(void(^_Nullable)(NSUInteger finished, NSUInteger skipped))completed; + +/// 异步计算磁盘缓存大小(字节) ++ (void)calculateDiskSize:(void(^)(NSUInteger bytes))completion; + +/// 清理内存+磁盘缓存 ++ (void)clearAllCache:(void(^_Nullable)(void))completion; + +/// 设置全局 HTTP Header(如鉴权 Token) ++ (void)setHTTPHeaderValue:(nullable NSString *)value forKey:(NSString *)field; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/keyBoard/Class/Categories/KBWebImageManager.m b/keyBoard/Class/Categories/KBWebImageManager.m new file mode 100644 index 0000000..4d40ff3 --- /dev/null +++ b/keyBoard/Class/Categories/KBWebImageManager.m @@ -0,0 +1,51 @@ +// +// KBWebImageManager.m +// keyBoard +// + +#import "KBWebImageManager.h" +#import + +static inline NSURL *_KBURL(id url) { + if (!url) return nil; + if ([url isKindOfClass:NSURL.class]) return url; + if ([url isKindOfClass:NSString.class]) return [NSURL URLWithString:(NSString *)url]; + return nil; +} + +@implementation KBWebImageManager + ++ (void)prefetchURLs:(NSArray *)urlList + progress:(void(^)(NSUInteger finished, NSUInteger total))progress + completed:(void(^)(NSUInteger finished, NSUInteger skipped))completed { + NSMutableArray *urls = [NSMutableArray arrayWithCapacity:urlList.count]; + for (id u in urlList) { NSURL *nu = _KBURL(u); if (nu) [urls addObject:nu]; } + [[SDWebImagePrefetcher sharedImagePrefetcher] prefetchURLs:urls progress:^(NSUInteger noOfFinishedUrls, NSUInteger noOfTotalUrls) { + if (progress) progress(noOfFinishedUrls, noOfTotalUrls); + } completed:^(NSUInteger finishedCount, NSUInteger skippedCount) { + if (completed) completed(finishedCount, skippedCount); + }]; +} + ++ (void)calculateDiskSize:(void(^)(NSUInteger bytes))completion { + [[SDImageCache sharedImageCache] calculateSizeWithCompletionBlock:^(NSUInteger fileCount, NSUInteger totalSize) { + if (completion) completion(totalSize); + }]; +} + ++ (void)clearAllCache:(void(^)(void))completion { + SDImageCache *cache = SDImageCache.sharedImageCache; + [cache clearMemory]; + [cache clearDiskOnCompletion:^{ if (completion) completion(); }]; +} + ++ (void)setHTTPHeaderValue:(NSString *)value forKey:(NSString *)field { + if (value.length == 0) { + [[SDWebImageDownloader sharedDownloader] setValue:nil forHTTPHeaderField:field]; + } else { + [[SDWebImageDownloader sharedDownloader] setValue:value forHTTPHeaderField:field]; + } +} + +@end + diff --git a/keyBoard/Class/Categories/UIColor+Extension.h b/keyBoard/Class/Categories/UIColor+Extension.h new file mode 100644 index 0000000..2584919 --- /dev/null +++ b/keyBoard/Class/Categories/UIColor+Extension.h @@ -0,0 +1,16 @@ +// +// UIColor+Extension.h +// keyBoard +// +// Created by Mac on 2025/10/29. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface UIColor (Extension) ++ (UIColor *)colorWithHex:(int)hexValue; +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Categories/UIColor+Extension.m b/keyBoard/Class/Categories/UIColor+Extension.m new file mode 100644 index 0000000..c7349da --- /dev/null +++ b/keyBoard/Class/Categories/UIColor+Extension.m @@ -0,0 +1,23 @@ +// +// UIColor+Extension.m +// keyBoard +// +// Created by Mac on 2025/10/29. +// + +#import "UIColor+Extension.h" + +@implementation UIColor (Extension) ++ (UIColor *)colorWithHex:(int)hexValue alpha:(CGFloat)alpha +{ + return [UIColor colorWithRed:((float)((hexValue & 0xFF0000) >> 16))/255.0 + green:((float)((hexValue & 0xFF00) >> 8))/255.0 + blue:((float)(hexValue & 0xFF))/255.0 + alpha:alpha]; +} + ++ (UIColor *)colorWithHex:(int)hexValue +{ + return [UIColor colorWithHex:hexValue alpha:1.0]; +} +@end diff --git a/keyBoard/Class/Categories/UIImageView+KBWebImage.h b/keyBoard/Class/Categories/UIImageView+KBWebImage.h new file mode 100644 index 0000000..c014bdf --- /dev/null +++ b/keyBoard/Class/Categories/UIImageView+KBWebImage.h @@ -0,0 +1,49 @@ +// +// UIImageView+KBWebImage.h +// keyBoard +// +// 在 SDWebImage 基础上的便捷封装: +// - 统一默认 options(失败重试、后台续传、降采样等) +// - 支持按视图大小缩略解码,减少内存占用 +// - 常用形状:普通、圆角、头像圆形 +// - 支持占位图、渐隐动画、取消下载 +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface UIImageView (KBWebImage) + +/// 简单加载(默认 options,自动渐隐) +- (void)kb_setImageURL:(nullable id)url placeholder:(nullable UIImage *)placeholder; + +/// 自定义 options +- (void)kb_setImageURL:(nullable id)url + placeholder:(nullable UIImage *)placeholder + options:(NSUInteger)options; + +/// 按视图大小缩略解码(推荐:内存友好)。若视图尚未布局,可传入 `targetSize` 期望像素尺寸(点×scale)。 +- (void)kb_setImageURL:(nullable id)url + placeholder:(nullable UIImage *)placeholder + thumbnailToFit:(BOOL)thumbnailToFit + targetSize:(CGSize)targetPixelSize; + +/// 圆角图(在解码阶段裁圆角,避免离屏开销) +- (void)kb_setImageURL:(nullable id)url + placeholder:(nullable UIImage *)placeholder + cornerRadius:(CGFloat)radius + corners:(UIRectCorner)corners + borderWidth:(CGFloat)borderWidth + borderColor:(nullable UIColor *)borderColor; + +/// 头像:自动按最短边裁成圆形(若视图尚未布局,会使用当前 bounds 估算) +- (void)kb_setAvatarURL:(nullable id)url placeholder:(nullable UIImage *)placeholder; + +/// 取消当前图的下载 +- (void)kb_cancelImageLoad; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/keyBoard/Class/Categories/UIImageView+KBWebImage.m b/keyBoard/Class/Categories/UIImageView+KBWebImage.m new file mode 100644 index 0000000..7b3a98e --- /dev/null +++ b/keyBoard/Class/Categories/UIImageView+KBWebImage.m @@ -0,0 +1,142 @@ +// +// UIImageView+KBWebImage.m +// keyBoard +// + +#import "UIImageView+KBWebImage.h" +#import + +// 默认下载配置:失败重试、后台续传、降采样、大图优先级 +static inline SDWebImageOptions KBWebImageDefaultOptions(void) { + return SDWebImageRetryFailed | + SDWebImageContinueInBackground | + SDWebImageHighPriority | + SDWebImageScaleDownLargeImages | + SDWebImageProgressiveLoad; // 渐进式 +} + +static inline NSURL *_KBURL(id url) { + if (!url) return nil; + if ([url isKindOfClass:NSURL.class]) return url; + if ([url isKindOfClass:NSString.class]) return [NSURL URLWithString:(NSString *)url]; + return nil; +} + +@implementation UIImageView (KBWebImage) + +- (void)kb_setImageURL:(id)url placeholder:(UIImage *)placeholder { + [self kb_setImageURL:url placeholder:placeholder options:KBWebImageDefaultOptions()]; +} + +- (void)kb_setImageURL:(id)url placeholder:(UIImage *)placeholder options:(NSUInteger)options { + NSURL *u = _KBURL(url); + // 默认渐隐动画 + __weak typeof(self) weakSelf = self; + [self sd_setImageWithURL:u + placeholderImage:placeholder + options:options + progress:nil + completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) { + if (!error && image && cacheType == SDImageCacheTypeNone) { + // 网络新图,做一次淡入动画 + weakSelf.alpha = 0.0; + [UIView animateWithDuration:0.25 animations:^{ weakSelf.alpha = 1.0; }]; + } + }]; +} + +- (void)kb_setImageURL:(id)url + placeholder:(UIImage *)placeholder + thumbnailToFit:(BOOL)thumbnailToFit + targetSize:(CGSize)targetPixelSize { + NSURL *u = _KBURL(url); + SDWebImageOptions options = KBWebImageDefaultOptions(); + NSMutableDictionary *context = [NSMutableDictionary dictionary]; + + if (thumbnailToFit) { + CGFloat scale = UIScreen.mainScreen.scale; + CGSize size = self.bounds.size; + if (CGSizeEqualToSize(size, CGSizeZero) && !CGSizeEqualToSize(targetPixelSize, CGSizeZero)) { + size = CGSizeMake(targetPixelSize.width/scale, targetPixelSize.height/scale); + } + if (!CGSizeEqualToSize(size, CGSizeZero)) { + CGSize pixelSize = CGSizeMake(size.width * scale, size.height * scale); + context[SDWebImageContextImageThumbnailPixelSize] = @(pixelSize); + } + } + + __weak typeof(self) weakSelf = self; + [self sd_setImageWithURL:u + placeholderImage:placeholder + options:options + context:context + progress:nil + completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) { + if (!error && image && cacheType == SDImageCacheTypeNone) { + weakSelf.alpha = 0.0; + [UIView animateWithDuration:0.25 animations:^{ weakSelf.alpha = 1.0; }]; + } + }]; +} + +- (void)kb_setImageURL:(id)url + placeholder:(UIImage *)placeholder + cornerRadius:(CGFloat)radius + corners:(UIRectCorner)corners + borderWidth:(CGFloat)borderWidth + borderColor:(UIColor *)borderColor { + NSURL *u = _KBURL(url); + SDWebImageOptions options = KBWebImageDefaultOptions(); + + // 组合圆角 + 缩略(按视图大小) + CGFloat scale = UIScreen.mainScreen.scale; + CGSize size = self.bounds.size; + NSMutableArray> *trans = [NSMutableArray array]; + if (!CGSizeEqualToSize(size, CGSizeZero)) { + // 先按像素缩到视图大小,避免在解码后再裁切浪费内存 + CGSize pixel = CGSizeMake(size.width * scale, size.height * scale); + [trans addObject:[SDImageResizingTransformer transformerWithSize:pixel scaleMode:SDImageScaleModeAspectFill]]; + } + [trans addObject:[SDImageRoundCornerTransformer transformerWithRadius:radius + corners:(SDRectCorner)corners + borderWidth:borderWidth + borderColor:borderColor]]; + SDImagePipelineTransformer *pipeline = [SDImagePipelineTransformer transformerWithTransformers:trans]; + + NSDictionary *context = @{ SDWebImageContextImageTransformer : pipeline }; + + __weak typeof(self) weakSelf = self; + [self sd_setImageWithURL:u + placeholderImage:placeholder + options:options + context:context + progress:nil + completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) { + if (!error && image && cacheType == SDImageCacheTypeNone) { + weakSelf.alpha = 0.0; + [UIView animateWithDuration:0.25 animations:^{ weakSelf.alpha = 1.0; }]; + } + }]; +} + +- (void)kb_setAvatarURL:(id)url placeholder:(UIImage *)placeholder { + // 圆形:以视图最短边的一半为半径 + CGSize sz = self.bounds.size; + CGFloat r = MIN(sz.width, sz.height) * 0.5; + if (r <= 0) { + // 若尚未布局,使用占位图尺寸估算 + r = MIN(placeholder.size.width, placeholder.size.height) * 0.5; + } + [self kb_setImageURL:url + placeholder:placeholder + cornerRadius:r + corners:UIRectCornerAllCorners + borderWidth:0 + borderColor:nil]; +} + +- (void)kb_cancelImageLoad { + [self sd_cancelCurrentImageLoad]; +} + +@end diff --git a/keyBoard/Class/Categories/UIViewController+Extension.h b/keyBoard/Class/Categories/UIViewController+Extension.h new file mode 100644 index 0000000..ab29df4 --- /dev/null +++ b/keyBoard/Class/Categories/UIViewController+Extension.h @@ -0,0 +1,18 @@ +// +// UIViewController+Extension.h +// keyBoard +// +// Created by Mac on 2025/11/3. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface UIViewController (Extension) +/// Returns the top-most presented view controller from the app's active window. +/// This mirrors the prior logic in AppDelegate (walks presentedViewController chain). ++ (nullable UIViewController *)kb_topMostViewController; +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Categories/UIViewController+Extension.m b/keyBoard/Class/Categories/UIViewController+Extension.m new file mode 100644 index 0000000..de0def3 --- /dev/null +++ b/keyBoard/Class/Categories/UIViewController+Extension.m @@ -0,0 +1,46 @@ +// +// UIViewController+Extension.m +// keyBoard +// +// Created by Mac on 2025/11/3. +// + +#import "UIViewController+Extension.h" + +@implementation UIViewController (Extension) + +/// Find the app's active window in a scene-friendly way (iOS 13+ safe) +static inline __kindof UIWindow *KBActiveWindow(void) { + UIWindow *window = [UIApplication sharedApplication].keyWindow; + if (window) return window; + // Fallbacks when keyWindow is nil (e.g. iOS 13+ with scenes) + if (@available(iOS 13.0, *)) { + for (UIScene *scene in [UIApplication sharedApplication].connectedScenes) { + if (scene.activationState != UISceneActivationStateForegroundActive) { continue; } + if (![scene isKindOfClass:[UIWindowScene class]]) { continue; } + UIWindowScene *ws = (UIWindowScene *)scene; + for (UIWindow *w in ws.windows) { + if (w.isKeyWindow) { return w; } + } + if (ws.windows.firstObject) { return ws.windows.firstObject; } + } + } + // iOS 12 and earlier fallback + for (UIWindow *w in [UIApplication sharedApplication].windows) { + if (w.isKeyWindow) { return w; } + } + return [UIApplication sharedApplication].windows.firstObject; +} + ++ (UIViewController *)kb_topMostViewController { + UIWindow *window = KBActiveWindow(); + UIViewController *root = window.rootViewController; + if (!root) return nil; + UIViewController *top = root; + while (top.presentedViewController) { + top = top.presentedViewController; + } + return top; +} + +@end diff --git a/keyBoard/Class/Guard/V/KBGuideKFCell.h b/keyBoard/Class/Guard/V/KBGuideKFCell.h new file mode 100644 index 0000000..5871658 --- /dev/null +++ b/keyBoard/Class/Guard/V/KBGuideKFCell.h @@ -0,0 +1,20 @@ +// +// KBGuideKFCell.h +// keyBoard +// +// 客服回复气泡 cell(左侧头像 + 白色圆角气泡) +// + +#import "BaseCell.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface KBGuideKFCell : BaseCell + +/// 设置文案 +- (void)configText:(NSString *)text; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/keyBoard/Class/Guard/V/KBGuideKFCell.m b/keyBoard/Class/Guard/V/KBGuideKFCell.m new file mode 100644 index 0000000..14a9ac2 --- /dev/null +++ b/keyBoard/Class/Guard/V/KBGuideKFCell.m @@ -0,0 +1,77 @@ +// +// KBGuideKFCell.m +// keyBoard +// + +#import "KBGuideKFCell.h" + +@interface KBGuideKFCell () +@property (nonatomic, strong) UIView *avatarView; // 左侧头像 +@property (nonatomic, strong) UIView *bubbleView; // 气泡 +@property (nonatomic, strong) UILabel *contentLabel; // 文案 +@end + +@implementation KBGuideKFCell + +- (void)setupUI { + self.contentView.backgroundColor = [UIColor colorWithWhite:0.96 alpha:1.0]; + + [self.contentView addSubview:self.avatarView]; + [self.avatarView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.contentView).offset(16); + make.top.equalTo(self.contentView).offset(10); + make.width.height.mas_equalTo(36); + }]; + + [self.contentView addSubview:self.bubbleView]; + [self.bubbleView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.avatarView.mas_right).offset(8); + make.top.equalTo(self.contentView).offset(8); + make.right.lessThanOrEqualTo(self.contentView).offset(-80); + make.bottom.equalTo(self.contentView).offset(-8); + }]; + + [self.bubbleView addSubview:self.contentLabel]; + [self.contentLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.bubbleView).insets(UIEdgeInsetsMake(10, 12, 10, 12)); + }]; +} + +- (void)configText:(NSString *)text { + self.contentLabel.text = text; +} + +#pragma mark - Lazy + +- (UIView *)avatarView { + if (!_avatarView) { + _avatarView = [UIView new]; + _avatarView.backgroundColor = [UIColor colorWithRed:0.23 green:0.47 blue:0.96 alpha:1.0]; + _avatarView.layer.cornerRadius = 18; + _avatarView.layer.masksToBounds = YES; + } + return _avatarView; +} + +- (UIView *)bubbleView { + if (!_bubbleView) { + _bubbleView = [UIView new]; + _bubbleView.backgroundColor = [UIColor whiteColor]; + _bubbleView.layer.cornerRadius = 18; + _bubbleView.layer.masksToBounds = YES; + } + return _bubbleView; +} + +- (UILabel *)contentLabel { + if (!_contentLabel) { + _contentLabel = [UILabel new]; + _contentLabel.numberOfLines = 0; + _contentLabel.font = [UIFont systemFontOfSize:15]; + _contentLabel.textColor = [UIColor colorWithWhite:0.15 alpha:1.0]; + } + return _contentLabel; +} + +@end + diff --git a/keyBoard/Class/Guard/V/KBGuideTopCell.h b/keyBoard/Class/Guard/V/KBGuideTopCell.h new file mode 100644 index 0000000..2cccbbb --- /dev/null +++ b/keyBoard/Class/Guard/V/KBGuideTopCell.h @@ -0,0 +1,17 @@ +// +// KBGuideTopCell.h +// keyBoard +// +// 顶部固定引导 cell(左侧头像 + 卡片文案) +// + +#import "BaseCell.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface KBGuideTopCell : BaseCell + +@end + +NS_ASSUME_NONNULL_END + diff --git a/keyBoard/Class/Guard/V/KBGuideTopCell.m b/keyBoard/Class/Guard/V/KBGuideTopCell.m new file mode 100644 index 0000000..e839946 --- /dev/null +++ b/keyBoard/Class/Guard/V/KBGuideTopCell.m @@ -0,0 +1,156 @@ +// +// KBGuideTopCell.m +// keyBoard +// + +#import "KBGuideTopCell.h" + +@interface KBGuideTopCell () + +// 左侧头像(占位色块代替图片) +@property (nonatomic, strong) UIView *avatarView; +// 白色卡片容器 +@property (nonatomic, strong) UIView *cardView; +// 卡片标题/正文 +@property (nonatomic, strong) UILabel *titleLabel; +@property (nonatomic, strong) UILabel *descLabel; +@property (nonatomic, strong) UIView *line1; +@property (nonatomic, strong) UILabel *q1Label; +@property (nonatomic, strong) UIView *line2; +@property (nonatomic, strong) UILabel *q2Label; + +@end + +@implementation KBGuideTopCell + +- (void)setupUI { + self.contentView.backgroundColor = [UIColor colorWithWhite:0.96 alpha:1.0]; + + // 头像 + [self.contentView addSubview:self.avatarView]; + [self.avatarView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.contentView).offset(16); + make.top.equalTo(self.contentView).offset(12); + make.width.height.mas_equalTo(36); + }]; + + // 卡片 + [self.contentView addSubview:self.cardView]; + [self.cardView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.avatarView.mas_right).offset(8); + make.right.lessThanOrEqualTo(self.contentView).offset(-32); + make.top.equalTo(self.contentView).offset(8); + make.bottom.equalTo(self.contentView).offset(-8); + }]; + + [self.cardView addSubview:self.titleLabel]; + [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.left.equalTo(self.cardView).offset(12); + make.right.equalTo(self.cardView).offset(-12); + }]; + + [self.cardView addSubview:self.descLabel]; + [self.descLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.titleLabel.mas_bottom).offset(6); + make.left.right.equalTo(self.titleLabel); + }]; + + // 分隔、两条示例问题 + [self.cardView addSubview:self.line1]; + [self.cardView addSubview:self.q1Label]; + [self.cardView addSubview:self.line2]; + [self.cardView addSubview:self.q2Label]; + + [self.line1 mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.descLabel.mas_bottom).offset(10); + make.left.right.equalTo(self.cardView); + make.height.mas_equalTo(KB_ONE_PIXEL); + }]; + + [self.q1Label mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.line1.mas_bottom).offset(10); + make.left.right.equalTo(self.titleLabel); + }]; + + [self.line2 mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.q1Label.mas_bottom).offset(10); + make.left.right.equalTo(self.cardView); + make.height.mas_equalTo(KB_ONE_PIXEL); + }]; + + [self.q2Label mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.line2.mas_bottom).offset(10); + make.left.right.equalTo(self.titleLabel); + make.bottom.equalTo(self.cardView).offset(-14); + }]; +} + +#pragma mark - Lazy + +- (UIView *)avatarView { + if (!_avatarView) { + _avatarView = [UIView new]; + _avatarView.backgroundColor = [UIColor colorWithRed:0.23 green:0.47 blue:0.96 alpha:1.0]; + _avatarView.layer.cornerRadius = 18; + _avatarView.layer.masksToBounds = YES; + } + return _avatarView; +} + +- (UIView *)cardView { + if (!_cardView) { + _cardView = [UIView new]; + _cardView.backgroundColor = [UIColor whiteColor]; + _cardView.layer.cornerRadius = 18; + _cardView.layer.masksToBounds = YES; + } + return _cardView; +} + +- (UILabel *)titleLabel { + if (!_titleLabel) { + _titleLabel = [UILabel new]; + _titleLabel.numberOfLines = 0; + _titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold]; + _titleLabel.textColor = [UIColor colorWithWhite:0.2 alpha:1.0]; + _titleLabel.text = @"👋 欢迎使用『Lovekey 键盘』"; + } + return _titleLabel; +} + +- (UILabel *)descLabel { + if (!_descLabel) { + _descLabel = [UILabel new]; + _descLabel.numberOfLines = 0; + _descLabel.font = [UIFont systemFontOfSize:14]; + _descLabel.textColor = [UIColor colorWithWhite:0.2 alpha:1.0]; + _descLabel.text = @"点击任一对话去粘贴,选择任意回复方式去试用吧~"; + } + return _descLabel; +} + +- (UIView *)line1 { if (!_line1) { _line1 = [UIView new]; _line1.backgroundColor = [UIColor colorWithWhite:0.92 alpha:1.0]; } return _line1; } +- (UIView *)line2 { if (!_line2) { _line2 = [UIView new]; _line2.backgroundColor = [UIColor colorWithWhite:0.92 alpha:1.0]; } return _line2; } + +- (UILabel *)q1Label { + if (!_q1Label) { + _q1Label = [UILabel new]; + _q1Label.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold]; + _q1Label.textColor = [UIColor blackColor]; + _q1Label.text = @"在干嘛?"; + } + return _q1Label; +} + +- (UILabel *)q2Label { + if (!_q2Label) { + _q2Label = [UILabel new]; + _q2Label.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold]; + _q2Label.textColor = [UIColor blackColor]; + _q2Label.text = @"我去洗澡了"; + } + return _q2Label; +} + +@end + diff --git a/keyBoard/Class/Guard/V/KBGuideUserCell.h b/keyBoard/Class/Guard/V/KBGuideUserCell.h new file mode 100644 index 0000000..e4837c4 --- /dev/null +++ b/keyBoard/Class/Guard/V/KBGuideUserCell.h @@ -0,0 +1,19 @@ +// +// KBGuideUserCell.h +// keyBoard +// +// 我方发送气泡 cell(右侧紫色气泡) +// + +#import "BaseCell.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface KBGuideUserCell : BaseCell + +- (void)configText:(NSString *)text; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/keyBoard/Class/Guard/V/KBGuideUserCell.m b/keyBoard/Class/Guard/V/KBGuideUserCell.m new file mode 100644 index 0000000..88dd15c --- /dev/null +++ b/keyBoard/Class/Guard/V/KBGuideUserCell.m @@ -0,0 +1,60 @@ +// +// KBGuideUserCell.m +// keyBoard +// + +#import "KBGuideUserCell.h" + +@interface KBGuideUserCell () +@property (nonatomic, strong) UIView *bubbleView; // 右侧紫色气泡 +@property (nonatomic, strong) UILabel *contentLabel; +@end + +@implementation KBGuideUserCell + +- (void)setupUI { + self.contentView.backgroundColor = [UIColor colorWithWhite:0.96 alpha:1.0]; + + [self.contentView addSubview:self.bubbleView]; + [self.bubbleView mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.equalTo(self.contentView).offset(-16); + make.top.equalTo(self.contentView).offset(8); + make.left.greaterThanOrEqualTo(self.contentView).offset(80); + make.bottom.equalTo(self.contentView).offset(-8); + }]; + + [self.bubbleView addSubview:self.contentLabel]; + [self.contentLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.bubbleView).insets(UIEdgeInsetsMake(8, 10, 8, 10)); + }]; +} + +- (void)configText:(NSString *)text { + self.contentLabel.text = text; +} + +#pragma mark - Lazy + +- (UIView *)bubbleView { + if (!_bubbleView) { + _bubbleView = [UIView new]; + _bubbleView.backgroundColor = [UIColor colorWithRed:0.42 green:0.45 blue:0.98 alpha:1.0]; + _bubbleView.layer.cornerRadius = 12; + _bubbleView.layer.masksToBounds = YES; + } + return _bubbleView; +} + +- (UILabel *)contentLabel { + if (!_contentLabel) { + _contentLabel = [UILabel new]; + _contentLabel.numberOfLines = 0; + _contentLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold]; + _contentLabel.textColor = [UIColor whiteColor]; + _contentLabel.textAlignment = NSTextAlignmentCenter; + } + return _contentLabel; +} + +@end + diff --git a/keyBoard/Class/Guard/VC/KBGuideVC.h b/keyBoard/Class/Guard/VC/KBGuideVC.h new file mode 100644 index 0000000..38950da --- /dev/null +++ b/keyBoard/Class/Guard/VC/KBGuideVC.h @@ -0,0 +1,16 @@ +// +// KBGuideVC.h +// keyBoard +// +// Created by Mac on 2025/10/29. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface KBGuideVC : UIViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Guard/VC/KBGuideVC.m b/keyBoard/Class/Guard/VC/KBGuideVC.m new file mode 100644 index 0000000..32f4b4b --- /dev/null +++ b/keyBoard/Class/Guard/VC/KBGuideVC.m @@ -0,0 +1,302 @@ +// +// KBGuideVC.m +// keyBoard +// +// Created by Mac on 2025/10/29. +// + +#import "KBGuideVC.h" +#import "KBGuideTopCell.h" +#import "KBGuideKFCell.h" +#import "KBGuideUserCell.h" +#import "KBPermissionViewController.h" +#import "KBKeyboardPermissionManager.h" + +typedef NS_ENUM(NSInteger, KBGuideItemType) { + KBGuideItemTypeTop = 0, // 顶部固定卡片 + KBGuideItemTypeUser, // 我方消息 + KBGuideItemTypeKF // 客服回复 +}; + +@interface KBGuideVC () + +@property (nonatomic, strong) BaseTableView *tableView; // 列表(继承 BaseTableView) +@property (nonatomic, strong) UIView *inputBar; // 底部输入容器 +@property (nonatomic, strong) UITextField *textField; // 输入框 +@property (nonatomic, strong) MASConstraint *inputBarBottom;// 输入栏底部约束 +@property (nonatomic, strong) UITapGestureRecognizer *bgTap;// 点击空白收起键盘 + +@property (nonatomic, strong) NSMutableArray *items; // 数据源 [{type, text}] +/// 权限引导页作为子控制器(用于“同时隐藏”) +@property (nonatomic, strong, nullable) KBPermissionViewController *permVC; + +@end + +@implementation KBGuideVC + +- (void)viewDidLoad { + [super viewDidLoad]; + self.view.backgroundColor = [UIColor colorWithWhite:0.96 alpha:1.0]; + self.title = @"使用引导"; + + [self.view addSubview:self.tableView]; + [self.view addSubview:self.inputBar]; + + [self.inputBar addSubview:self.textField]; + + [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.left.right.equalTo(self.view); + make.bottom.equalTo(self.view); + }]; + + [self.inputBar mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.equalTo(self.view); + make.height.mas_equalTo(52); + // 底部跟随键盘变化 + if (@available(iOS 11.0, *)) { + self.inputBarBottom = make.bottom.equalTo(self.view.mas_safeAreaLayoutGuideBottom); + } else { + self.inputBarBottom = make.bottom.equalTo(self.view); + } + }]; + + [self.textField mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.inputBar).offset(12); + make.right.equalTo(self.inputBar).offset(-12); + make.centerY.equalTo(self.inputBar); + make.height.mas_equalTo(36); + }]; + + // 初始只有固定 Top + [self.items addObject:@{ @"type": @(KBGuideItemTypeTop), @"text": @"" }]; + [self.tableView reloadData]; + + // 键盘监听 + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(kb_keyboardWillChange:) name:UIKeyboardWillChangeFrameNotification object:nil]; + + // 点击空白收起键盘(不干扰 cell 的点击/滚动) + self.bgTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(kb_didTapBackground)]; + self.bgTap.cancelsTouchesInView = NO; + self.bgTap.delegate = self; + [self.tableView addGestureRecognizer:self.bgTap]; + + // 监听应用回到前台/变为活跃:用于从设置返回时再次校验权限 + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(kb_checkKeyboardPermission) name:UIApplicationDidBecomeActiveNotification object:nil]; + + // 提前创建并铺满权限引导页(默认隐藏),避免后续显示时出现布局进场感 + [self kb_preparePermissionOverlayIfNeeded]; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + // 每次进入页面都校验一次(包括从其它页面返回) + [self kb_checkKeyboardPermission]; +} + +/// 校验键盘权限: +/// - 未启用或已启用但拒绝完全访问 => 弹出引导页 +/// - 已满足条件且正在展示引导页 => 关闭引导页 +- (void)kb_checkKeyboardPermission { + KBKeyboardPermissionManager *mgr = [KBKeyboardPermissionManager shared]; + BOOL enabled = [mgr isKeyboardEnabled]; + KBFARecord fa = [mgr lastKnownFullAccess]; + BOOL needGuide = (!enabled) || (enabled && fa == KBFARecordDenied); + + [self kb_preparePermissionOverlayIfNeeded]; + BOOL show = needGuide; +// [UIView performWithoutAnimation:^{ + self.permVC.view.hidden = !show; +// }]; +} + +/// 提前创建权限引导页覆盖层(仅一次) +- (void)kb_preparePermissionOverlayIfNeeded { + if (self.permVC) return; + KBPermissionViewController *guide = [KBPermissionViewController new]; +// guide.modalPresentationStyle = UIModalPresentationFullScreen; // 仅用于内部布局,不会真正 present + KBWeakSelf; + guide.backHandler = ^{ [weakSelf.navigationController popViewControllerAnimated:YES]; }; + self.permVC = guide; + guide.backButton.hidden = true; + [self addChildViewController:guide]; + [self.view addSubview:guide.view]; +// [guide.view mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.equalTo(self.view); }]; + [guide didMoveToParentViewController:self]; + guide.view.hidden = YES; // 初始隐藏 +} + +- (void)kb_didTapBackground { + // 结束编辑,隐藏键盘 + [self.view endEditing:YES]; +} + + +#pragma mark - Actions + +// 发送:回车发送一条消息,随后插入固定的客服回复 +- (BOOL)textFieldShouldReturn:(UITextField *)textField { + NSString *text = [textField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + if (text.length == 0) { return NO; } + + // 1. 插入我方消息 + [self.items addObject:@{ @"type": @(KBGuideItemTypeUser), @"text": text ?: @"" }]; + // 2. 紧跟一条固定客服消息 + NSString *reply = @"🎉 如您遇到其他问题,可点击在线客服帮您解决~"; + [self.items addObject:@{ @"type": @(KBGuideItemTypeKF), @"text": reply }]; + + // 刷新并滚动到底部 + [self.tableView reloadData]; + [self scrollToBottomAnimated:YES]; + + textField.text = @""; + return YES; +} + +- (void)kb_keyboardWillChange:(NSNotification *)note { + NSDictionary *info = note.userInfo; + NSTimeInterval duration = [info[UIKeyboardAnimationDurationUserInfoKey] doubleValue]; + UIViewAnimationOptions curve = ([info[UIKeyboardAnimationCurveUserInfoKey] integerValue] << 16); + + CGRect endFrame = [info[UIKeyboardFrameEndUserInfoKey] CGRectValue]; + CGFloat screenH = UIScreen.mainScreen.bounds.size.height; + CGFloat kbHeight = MAX(0, screenH - endFrame.origin.y); + + CGFloat safeBtm = 0; + if (@available(iOS 11.0, *)) { safeBtm = self.view.safeAreaInsets.bottom; } + + // 输入栏距离底部 = -max(kbHeight - 安全区, 0) + CGFloat offset = -MAX(kbHeight - safeBtm, 0); + self.inputBarBottom.offset = offset; + + [UIView animateWithDuration:duration delay:0 options:curve animations:^{ + UIEdgeInsets inset = self.tableView.contentInset; + inset.bottom = 52 + MAX(kbHeight - safeBtm, 0); + self.tableView.contentInset = inset; +// self.tableView.scrollIndicatorInsets = inset; + } completion:^(BOOL finished) { + [self scrollToBottomAnimated:YES]; + }]; +} + +- (void)scrollToBottomAnimated:(BOOL)animated { + if (self.items.count == 0) return; + NSInteger last = self.items.count - 1; + NSIndexPath *ip = [NSIndexPath indexPathForRow:last inSection:0]; + if (last >= 0) { + [self.tableView scrollToRowAtIndexPath:ip atScrollPosition:UITableViewScrollPositionBottom animated:animated]; + } +} + +#pragma mark - UITableView + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return self.items.count; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + NSDictionary *it = self.items[indexPath.row]; + KBGuideItemType type = [it[@"type"] integerValue]; + NSString *text = it[@"text"] ?: @""; + + if (type == KBGuideItemTypeTop) { + KBGuideTopCell *cell = [tableView dequeueReusableCellWithIdentifier:[KBGuideTopCell reuseId]]; + if (!cell) cell = [[KBGuideTopCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:[KBGuideTopCell reuseId]]; + return cell; + } else if (type == KBGuideItemTypeUser) { + KBGuideUserCell *cell = [tableView dequeueReusableCellWithIdentifier:[KBGuideUserCell reuseId]]; + if (!cell) cell = [[KBGuideUserCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:[KBGuideUserCell reuseId]]; + [cell configText:text]; + return cell; + } else { + KBGuideKFCell *cell = [tableView dequeueReusableCellWithIdentifier:[KBGuideKFCell reuseId]]; + if (!cell) cell = [[KBGuideKFCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:[KBGuideKFCell reuseId]]; + [cell configText:text]; + return cell; + } +} + +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { + return UITableViewAutomaticDimension; +} + +- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath { + return 100; +} + +#pragma mark - Lazy + +- (BaseTableView *)tableView { + if (!_tableView) { + _tableView = [[BaseTableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain]; + _tableView.delegate = self; + _tableView.dataSource = self; + _tableView.separatorStyle = UITableViewCellSeparatorStyleNone; // 无分割线 + _tableView.backgroundColor = [UIColor colorWithWhite:0.96 alpha:1.0]; + _tableView.rowHeight = UITableViewAutomaticDimension; + _tableView.estimatedRowHeight = 120; // 开启自适应高度 + _tableView.contentInset = UIEdgeInsetsMake(0, 0, 52 + KB_SafeAreaBottom(), 0); + _tableView.scrollIndicatorInsets = _tableView.contentInset; + } + return _tableView; +} + +- (UIView *)inputBar { + if (!_inputBar) { + _inputBar = [UIView new]; + _inputBar.backgroundColor = [UIColor colorWithWhite:0.96 alpha:1.0]; + UIView *bg = [UIView new]; + bg.backgroundColor = [UIColor whiteColor]; + bg.layer.cornerRadius = 10; bg.layer.masksToBounds = YES; + [_inputBar addSubview:bg]; + [bg mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(_inputBar).offset(12); + make.right.equalTo(_inputBar).offset(-12); + make.top.equalTo(_inputBar).offset(8); + make.bottom.equalTo(_inputBar).offset(-8); + }]; + } + return _inputBar; +} + +- (UITextField *)textField { + if (!_textField) { + _textField = [UITextField new]; + _textField.delegate = self; + _textField.returnKeyType = UIReturnKeySend; // 回车发送 + _textField.font = [UIFont systemFontOfSize:15]; + _textField.placeholder = @"在键盘粘贴对话后,选择回复方式"; + _textField.backgroundColor = [UIColor whiteColor]; + _textField.layer.cornerRadius = 10; _textField.layer.masksToBounds = YES; + UIView *pad = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 36)]; + _textField.leftView = pad; _textField.leftViewMode = UITextFieldViewModeAlways; + } + return _textField; +} + +- (NSMutableArray *)items { + if (!_items) { _items = @[].mutableCopy; } + return _items; +} + +#pragma mark - UIGestureRecognizerDelegate + +// 避免点到输入栏触发收起 +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { + if (gestureRecognizer == self.bgTap) { + if ([touch.view isDescendantOfView:self.inputBar]) { + return NO; + } + } + return YES; +} + +// 与其它手势同时识别,避免影响表格滚动/选择 +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { + return YES; +} + +@end diff --git a/keyBoard/Class/Home/VC/HomeVC.h b/keyBoard/Class/Home/VC/HomeVC.h new file mode 100644 index 0000000..23d76f4 --- /dev/null +++ b/keyBoard/Class/Home/VC/HomeVC.h @@ -0,0 +1,16 @@ +// +// HomeVC.h +// keyBoard +// +// Created by Mac on 2025/10/29. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface HomeVC : UIViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Home/VC/HomeVC.m b/keyBoard/Class/Home/VC/HomeVC.m new file mode 100644 index 0000000..346f4b4 --- /dev/null +++ b/keyBoard/Class/Home/VC/HomeVC.m @@ -0,0 +1,101 @@ +// +// HomeVC.m +// keyBoard +// +// Created by Mac on 2025/10/29. +// + +#import "HomeVC.h" +#import "KBGuideVC.h" +#import "KBLangTestVC.h" + +@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]; + + 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]; + } +} + +/* +#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/VC/KBLangTestVC.h b/keyBoard/Class/Home/VC/KBLangTestVC.h new file mode 100644 index 0000000..810ee13 --- /dev/null +++ b/keyBoard/Class/Home/VC/KBLangTestVC.h @@ -0,0 +1,14 @@ +// +// KBLangTestVC.h +// 多语言测试页:点击按钮在中英文之间切换,并刷新文案。 +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface KBLangTestVC : UIViewController +@end + +NS_ASSUME_NONNULL_END + diff --git a/keyBoard/Class/Home/VC/KBLangTestVC.m b/keyBoard/Class/Home/VC/KBLangTestVC.m new file mode 100644 index 0000000..0c212c1 --- /dev/null +++ b/keyBoard/Class/Home/VC/KBLangTestVC.m @@ -0,0 +1,60 @@ +// +// KBLangTestVC.m +// + +#import "KBLangTestVC.h" + +@interface KBLangTestVC () +@property (nonatomic, strong) UILabel *label; +@property (nonatomic, strong) UIButton *toggleBtn; +@end + +@implementation KBLangTestVC + +- (void)viewDidLoad { + [super viewDidLoad]; + self.view.backgroundColor = UIColor.whiteColor; + [self buildUI]; + [self refreshTexts]; + + // 监听语言变更,实时刷新 + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refreshTexts) name:KBLocalizationDidChangeNotification object:nil]; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (void)buildUI { + CGFloat w = UIScreen.mainScreen.bounds.size.width; + + self.label = [[UILabel alloc] initWithFrame:CGRectMake(24, 120, w - 48, 60)]; + self.label.textAlignment = NSTextAlignmentCenter; + self.label.numberOfLines = 0; + [self.view addSubview:self.label]; + + self.toggleBtn = [UIButton buttonWithType:UIButtonTypeSystem]; + self.toggleBtn.frame = CGRectMake(40, CGRectGetMaxY(self.label.frame) + 24, w - 80, 48); + self.toggleBtn.layer.cornerRadius = 8; + self.toggleBtn.backgroundColor = [UIColor colorWithRed:0.22 green:0.49 blue:0.96 alpha:1]; + [self.toggleBtn setTitleColor:UIColor.whiteColor forState:UIControlStateNormal]; + [self.toggleBtn addTarget:self action:@selector(onToggle) forControlEvents:UIControlEventTouchUpInside]; + [self.view addSubview:self.toggleBtn]; +} + +- (void)refreshTexts { + self.title = KBLocalized(@"lang_test_title"); + NSString *code = [KBLocalizationManager shared].currentLanguageCode ?: @""; + NSString *fmt = KBLocalized(@"current_lang"); + self.label.text = [NSString stringWithFormat:fmt.length ? fmt : @"当前:%@", code]; + [self.toggleBtn setTitle:KBLocalized(@"lang_toggle") forState:UIControlStateNormal]; +} + +- (void)onToggle { + KBLocalizationManager *mgr = [KBLocalizationManager shared]; + NSString *next = [mgr.currentLanguageCode.lowercaseString hasPrefix:@"zh"] ? @"en" : @"zh-Hans"; + [mgr setCurrentLanguageCode:next persist:YES]; +} + +@end + diff --git a/keyBoard/Class/Login/VC/KBLoginSheetViewController.h b/keyBoard/Class/Login/VC/KBLoginSheetViewController.h new file mode 100644 index 0000000..2f65a49 --- /dev/null +++ b/keyBoard/Class/Login/VC/KBLoginSheetViewController.h @@ -0,0 +1,21 @@ +// +// KBLoginSheetViewController.h +// keyBoard +// +// A lightweight bottom-sheet style login prompt. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface KBLoginSheetViewController : UIViewController + +@property (nonatomic, copy, nullable) void (^onLoginSuccess)(void); + ++ (void)presentIfNeededFrom:(UIViewController *)presenting; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/keyBoard/Class/Login/VC/KBLoginSheetViewController.m b/keyBoard/Class/Login/VC/KBLoginSheetViewController.m new file mode 100644 index 0000000..04b6629 --- /dev/null +++ b/keyBoard/Class/Login/VC/KBLoginSheetViewController.m @@ -0,0 +1,147 @@ +// +// KBLoginSheetViewController.m +// keyBoard +// +// Bottom sheet asking user to login with Apple ID. Tapping Continue shows LoginViewController. +// + +#import "KBLoginSheetViewController.h" +#import "LoginViewController.h" +#import + +@interface KBLoginSheetViewController () +@property (nonatomic, strong) UIControl *backdrop; +@property (nonatomic, strong) UIView *sheet; +@property (nonatomic, strong) UIButton *checkButton; +@property (nonatomic, strong) UILabel *descLabel; +@property (nonatomic, strong) UIButton *continueButton; +@end + +@implementation KBLoginSheetViewController + ++ (void)presentIfNeededFrom:(UIViewController *)presenting { + if (!presenting) return; + // 避免重复弹多个 + if ([presenting.presentedViewController isKindOfClass:[self class]]) return; + KBLoginSheetViewController *vc = [KBLoginSheetViewController new]; + vc.modalPresentationStyle = UIModalPresentationOverFullScreen; + [presenting presentViewController:vc animated:NO completion:nil]; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + self.view.backgroundColor = [UIColor clearColor]; + [self buildUI]; +} + +- (void)buildUI { + self.backdrop = [[UIControl alloc] init]; + self.backdrop.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.15]; + [self.backdrop addTarget:self action:@selector(dismissSelf) forControlEvents:UIControlEventTouchUpInside]; + [self.view addSubview:self.backdrop]; + [self.backdrop mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.view); + }]; + + self.sheet = [[UIView alloc] init]; + self.sheet.backgroundColor = [UIColor whiteColor]; + self.sheet.layer.cornerRadius = 12.0; + self.sheet.layer.masksToBounds = YES; + [self.view addSubview:self.sheet]; + [self.sheet mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.equalTo(self.view); + make.bottom.equalTo(self.view.mas_safeAreaLayoutGuideBottom); + make.height.mas_equalTo(160); + }]; + + self.checkButton = [UIButton buttonWithType:UIButtonTypeSystem]; + self.checkButton.layer.cornerRadius = 16; + self.checkButton.layer.borderWidth = 2; + self.checkButton.layer.borderColor = [UIColor colorWithWhite:0.8 alpha:1.0].CGColor; + self.checkButton.backgroundColor = [UIColor whiteColor]; + [self.checkButton setTitle:@"" forState:UIControlStateNormal]; + [self.checkButton addTarget:self action:@selector(toggleCheck) forControlEvents:UIControlEventTouchUpInside]; + + self.descLabel = [UILabel new]; + self.descLabel.text = @"allow log in with apple id?"; + self.descLabel.textColor = [UIColor blackColor]; + self.descLabel.font = [UIFont systemFontOfSize:16]; + + [self.sheet addSubview:self.checkButton]; + [self.sheet addSubview:self.descLabel]; + [self.checkButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.sheet).offset(28); + make.top.equalTo(self.sheet).offset(18); + make.width.height.mas_equalTo(32); + }]; + [self.descLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.checkButton.mas_right).offset(12); + make.centerY.equalTo(self.checkButton.mas_centerY); + make.right.lessThanOrEqualTo(self.sheet).offset(-20); + }]; + + self.continueButton = [UIButton buttonWithType:UIButtonTypeSystem]; + self.continueButton.backgroundColor = [UIColor whiteColor]; + self.continueButton.layer.cornerRadius = 10; + self.continueButton.layer.borderWidth = 1.0; + self.continueButton.layer.borderColor = [UIColor colorWithWhite:0.8 alpha:1.0].CGColor; + [self.continueButton setTitle:@"Continue" forState:UIControlStateNormal]; + [self.continueButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; + self.continueButton.titleLabel.font = [UIFont boldSystemFontOfSize:20]; + [self.continueButton addTarget:self action:@selector(onContinue) forControlEvents:UIControlEventTouchUpInside]; + [self.sheet addSubview:self.continueButton]; + [self.continueButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.sheet).offset(28); + make.right.equalTo(self.sheet).offset(-28); + make.height.mas_equalTo(48); + make.top.equalTo(self.checkButton.mas_bottom).offset(18); + }]; +} + +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + // 初始位置在屏幕下方,做一个上滑动画 + CGRect frame = self.sheet.frame; + self.sheet.transform = CGAffineTransformMakeTranslation(0, frame.size.height + 40); + self.backdrop.alpha = 0; + [UIView animateWithDuration:0.22 animations:^{ + self.sheet.transform = CGAffineTransformIdentity; + self.backdrop.alpha = 1; + }]; +} + +- (void)dismissSelf { + [UIView animateWithDuration:0.18 animations:^{ + self.sheet.transform = CGAffineTransformMakeTranslation(0, self.sheet.bounds.size.height + 40); + self.backdrop.alpha = 0; + } completion:^(BOOL finished) { + [self dismissViewControllerAnimated:NO completion:nil]; + }]; +} + +- (void)toggleCheck { + self.checkButton.selected = !self.checkButton.selected; + if (self.checkButton.selected) { + self.checkButton.backgroundColor = [UIColor colorWithRed:0.22 green:0.49 blue:0.96 alpha:1.0]; + self.checkButton.layer.borderColor = self.checkButton.backgroundColor.CGColor; + } else { + self.checkButton.backgroundColor = [UIColor whiteColor]; + self.checkButton.layer.borderColor = [UIColor colorWithWhite:0.8 alpha:1.0].CGColor; + } +} + +- (void)onContinue { + LoginViewController *login = [LoginViewController new]; + __weak typeof(self) weakSelf = self; + login.onLoginSuccess = ^(NSDictionary * _Nonnull userInfo) { + __strong typeof(weakSelf) self = weakSelf; if (!self) return; + [self dismissViewControllerAnimated:YES completion:^{ + if (self.onLoginSuccess) self.onLoginSuccess(); + [self dismissSelf]; + }]; + }; + login.modalPresentationStyle = UIModalPresentationPageSheet; + [self presentViewController:login animated:YES completion:nil]; +} + +@end diff --git a/keyBoard/Class/Login/VC/LoginViewController.h b/keyBoard/Class/Login/VC/LoginViewController.h new file mode 100644 index 0000000..3c00c1f --- /dev/null +++ b/keyBoard/Class/Login/VC/LoginViewController.h @@ -0,0 +1,18 @@ +// LoginViewController.h +// 仅包含“Apple 登录”的登录页 + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface LoginViewController : UIViewController + +/// Apple 登录成功回调。包含 userIdentifier;首次授权可能包含 email/fullName。 +@property (nonatomic, copy, nullable) void (^onLoginSuccess)(NSDictionary *userInfo); + +/// 登录失败或取消时回调(返回错误)。 +@property (nonatomic, copy, nullable) void (^onLoginFailure)(NSError *error); + +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Login/VC/LoginViewController.m b/keyBoard/Class/Login/VC/LoginViewController.m new file mode 100644 index 0000000..7d4fc9a --- /dev/null +++ b/keyBoard/Class/Login/VC/LoginViewController.m @@ -0,0 +1,161 @@ +// LoginViewController.m + +#import "LoginViewController.h" +#import "AppleSignInManager.h" +#import +#import +#import "KBAuthManager.h" + +@interface LoginViewController () +// 容器视图(用于居中摆放内容) +@property (nonatomic, strong) UIView *contentView; +// 标题标签(懒加载) +@property (nonatomic, strong) UILabel *titleLabel; +// Apple 登录按钮容器(懒加载) +@property (nonatomic, strong) UIView *appleContainer; +// Apple 登录按钮(懒加载) +@property (nonatomic, strong) ASAuthorizationAppleIDButton *appleButton API_AVAILABLE(ios(13.0)); +// iOS13 以下的占位按钮(懒加载) +@property (nonatomic, strong) UIButton *compatHintButton; +@end + +@implementation LoginViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + if (@available(iOS 13.0, *)) { + self.view.backgroundColor = [UIColor systemBackgroundColor]; + } else { + self.view.backgroundColor = [UIColor whiteColor]; + } + [self setupUI]; // 仅做布局,控件懒加载 +} + +- (void)setupUI { + // 添加并约束 contentView + [self.view addSubview:self.contentView]; + [self.contentView mas_makeConstraints:^(MASConstraintMaker *make) { + make.center.equalTo(self.view); + make.left.equalTo(self.view).offset(24); + make.right.equalTo(self.view).offset(-24); + }]; + + // 添加并约束 titleLabel + [self.contentView addSubview:self.titleLabel]; + [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.left.right.equalTo(self.contentView); + }]; + + // 添加并约束 appleContainer + [self.contentView addSubview:self.appleContainer]; + [self.appleContainer mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.titleLabel.mas_bottom).offset(24); + make.left.right.equalTo(self.contentView); + make.height.mas_equalTo(50); + make.bottom.equalTo(self.contentView); + }]; +} + +// 懒加载:容器视图 +- (UIView *)contentView { + if (!_contentView) { + _contentView = [UIView new]; + } + return _contentView; +} + +// 懒加载:标题 +- (UILabel *)titleLabel { + if (!_titleLabel) { + _titleLabel = [UILabel new]; + _titleLabel.text = @"登录"; + _titleLabel.font = [UIFont boldSystemFontOfSize:24]; + _titleLabel.textAlignment = NSTextAlignmentCenter; + } + return _titleLabel; +} + +// 懒加载:Apple 按钮容器(内部放按钮或占位提示) +- (UIView *)appleContainer { + if (!_appleContainer) { + _appleContainer = [UIView new]; + if (@available(iOS 13.0, *)) { + [_appleContainer addSubview:self.appleButton]; + [self.appleButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(_appleContainer); + }]; + } else { + [_appleContainer addSubview:self.compatHintButton]; + [self.compatHintButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(_appleContainer); + }]; + } + } + return _appleContainer; +} + +// 懒加载:Apple 登录按钮(iOS13+) +- (ASAuthorizationAppleIDButton *)appleButton API_AVAILABLE(ios(13.0)) { + if (!_appleButton) { + _appleButton = [ASAuthorizationAppleIDButton new]; + [_appleButton addTarget:self action:@selector(handleAppleIDButtonPress) forControlEvents:UIControlEventTouchUpInside]; + } + return _appleButton; +} + +// 懒加载:iOS13 以下占位提示 +- (UIButton *)compatHintButton { + if (!_compatHintButton) { + _compatHintButton = [UIButton buttonWithType:UIButtonTypeSystem]; + [_compatHintButton setTitle:@"需要 iOS13+ 才能使用 Apple 登录" forState:UIControlStateNormal]; + _compatHintButton.enabled = NO; + } + return _compatHintButton; +} + +- (void)handleAppleIDButtonPress API_AVAILABLE(ios(13.0)) { + __weak typeof(self) weakSelf = self; + [[AppleSignInManager shared] signInFromViewController:self completion:^(ASAuthorizationAppleIDCredential * _Nullable credential, NSError * _Nullable error) { + __strong typeof(weakSelf) selfStrong = weakSelf; + if (error) { + if (selfStrong.onLoginFailure) selfStrong.onLoginFailure(error); + return; + } + if (!credential) return; + + NSString *userID = credential.user ?: @""; + NSString *email = credential.email ?: @""; // 仅在首次授权时返回 + NSPersonNameComponents *name = credential.fullName; // 同上,仅首次返回 + NSString *givenName = name.givenName ?: @""; + NSString *familyName = name.familyName ?: @""; + + NSMutableDictionary *info = [@{ @"userIdentifier": userID } mutableCopy]; + if (email.length) info[@"email"] = email; + if (givenName.length || familyName.length) { + info[@"givenName"] = givenName; + info[@"familyName"] = familyName; + } + + // 如需服务端校验,附带 identityToken / authorizationCode + NSData *tokenData = credential.identityToken; + if (tokenData) { + NSString *token = [[NSString alloc] initWithData:tokenData encoding:NSUTF8StringEncoding] ?: @""; + if (token.length) info[@"identityToken"] = token; + } + NSData *codeData = credential.authorizationCode; + if (codeData) { + NSString *code = [[NSString alloc] initWithData:codeData encoding:NSUTF8StringEncoding] ?: @""; + if (code.length) info[@"authorizationCode"] = code; + } + + // 将示例中的 identityToken 暂存为访问令牌(实际项目应调用服务端换取业务 token) + NSString *accessToken = info[@"identityToken"]; + NSString *uid = info[@"userIdentifier"]; // 不变 + if (accessToken.length > 0) { + [[KBAuthManager shared] saveAccessToken:accessToken refreshToken:nil expiryDate:nil userIdentifier:uid]; + } + if (selfStrong.onLoginSuccess) selfStrong.onLoginSuccess(info); + }]; +} + +@end diff --git a/keyBoard/Class/Manager/AppleSignInManager.h b/keyBoard/Class/Manager/AppleSignInManager.h new file mode 100644 index 0000000..05dc7c6 --- /dev/null +++ b/keyBoard/Class/Manager/AppleSignInManager.h @@ -0,0 +1,40 @@ +// AppleSignInManager.h +// 封装“用 Apple 登录”逻辑 + +#import +#import +@class UIViewController; + +NS_ASSUME_NONNULL_BEGIN + +/// Apple 登录回调结果 +typedef void (^KBAppleSignInCompletion)(ASAuthorizationAppleIDCredential * _Nullable credential, NSError * _Nullable error); + +/// AppleSignInManager 集中管理 Apple 登录流程与代理回调 +@interface AppleSignInManager : NSObject + +/// 单例便捷访问 ++ (instancetype)shared; + +/// 发起 Apple 登录 +/// - 参数说明: +/// - presenting: 用于呈现授权界面的控制器 +/// - completion: 主线程回调,返回凭证或错误 +- (void)signInFromViewController:(UIViewController *)presenting completion:(KBAppleSignInCompletion)completion; + +/// 根据已存储的 userIdentifier 检查凭证状态 +/// 返回:ASAuthorizationAppleIDProviderCredentialAuthorized/Revoked/NotFound +- (void)checkCredentialStateWithCompletion:(void(^)(ASAuthorizationAppleIDProviderCredentialState state))completion; + +/// 使用给定 userIdentifier 检查凭证状态(推荐:从服务端返回的 userIdentifier) +- (void)checkCredentialStateForUserID:(NSString *)userID completion:(void(^)(ASAuthorizationAppleIDProviderCredentialState state))completion; + +/// 最近一次成功登录的 userIdentifier(已持久化) +@property (nonatomic, readonly, nullable) NSString *storedUserIdentifier; + +/// 本地登出:清除已存储的 userIdentifier(不会向苹果撤销授权) +- (void)signOut; + +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Manager/AppleSignInManager.m b/keyBoard/Class/Manager/AppleSignInManager.m new file mode 100644 index 0000000..3306926 --- /dev/null +++ b/keyBoard/Class/Manager/AppleSignInManager.m @@ -0,0 +1,159 @@ +// AppleSignInManager.m +// 封装“用 Apple 登录”的实现与存储 + +#import "AppleSignInManager.h" +#import +#import + +static NSString * const kKBAppleUserIdentifierKey = @"com.company.keyboard.apple.user"; // 钥匙串键名 + +@interface AppleSignInManager () +@property (nonatomic, weak) UIViewController *presentingVC; +@property (nonatomic, copy) KBAppleSignInCompletion completion; +@end + +@implementation AppleSignInManager + ++ (instancetype)shared { + static AppleSignInManager *instance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ instance = [AppleSignInManager new]; }); + return instance; +} + +- (NSString *)storedUserIdentifier { + return [self.class keychainLoad:kKBAppleUserIdentifierKey]; +} + +- (void)signInFromViewController:(UIViewController *)presenting completion:(KBAppleSignInCompletion)completion { + if (@available(iOS 13.0, *)) { + self.presentingVC = presenting; + self.completion = completion; + + ASAuthorizationAppleIDProvider *provider = [ASAuthorizationAppleIDProvider new]; + ASAuthorizationAppleIDRequest *request = provider.createRequest; + request.requestedScopes = @[ASAuthorizationScopeFullName, ASAuthorizationScopeEmail]; + + ASAuthorizationController *controller = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[request]]; + controller.delegate = self; + controller.presentationContextProvider = self; + [controller performRequests]; + } else { + if (completion) { + NSError *err = [NSError errorWithDomain:@"AppleSignIn" code:-1 userInfo:@{NSLocalizedDescriptionKey: @"Apple 登录需要 iOS 13 及以上版本"}]; + completion(nil, err); + } + } +} + +- (void)checkCredentialStateWithCompletion:(void(^)(ASAuthorizationAppleIDProviderCredentialState state))completion { + if (!completion) return; + if (@available(iOS 13.0, *)) { + NSString *userID = self.storedUserIdentifier; + if (!userID) { + completion(ASAuthorizationAppleIDProviderCredentialNotFound); + return; + } + ASAuthorizationAppleIDProvider *provider = [ASAuthorizationAppleIDProvider new]; + [provider getCredentialStateForUserID:userID completion:^(ASAuthorizationAppleIDProviderCredentialState credentialState, NSError * _Nullable error) { + dispatch_async(dispatch_get_main_queue(), ^{ completion(credentialState); }); + }]; + } else { + completion(ASAuthorizationAppleIDProviderCredentialNotFound); + } +} + +// 使用指定的 userIdentifier 检查凭证状态(无需本地存储) +- (void)checkCredentialStateForUserID:(NSString *)userID completion:(void(^)(ASAuthorizationAppleIDProviderCredentialState state))completion { + if (!completion) return; + if (@available(iOS 13.0, *)) { + if (userID.length == 0) { + completion(ASAuthorizationAppleIDProviderCredentialNotFound); + return; + } + ASAuthorizationAppleIDProvider *provider = [ASAuthorizationAppleIDProvider new]; + [provider getCredentialStateForUserID:userID completion:^(ASAuthorizationAppleIDProviderCredentialState credentialState, NSError * _Nullable error) { + dispatch_async(dispatch_get_main_queue(), ^{ completion(credentialState); }); + }]; + } else { + completion(ASAuthorizationAppleIDProviderCredentialNotFound); + } +} + +#pragma mark - 授权回调 (ASAuthorizationControllerDelegate) + +- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorization API_AVAILABLE(ios(13.0)) { + if (@available(iOS 13.0, *)) { + ASAuthorizationAppleIDCredential *credential = authorization.credential; + // 为了让键盘扩展/主 App 能识别“是否已登录”,在本地持久化 userIdentifier 到钥匙串。 + // 仅保存一个标记(不包含敏感信息),业务登录态仍以服务端为准。 + NSString *userID = credential.user ?: @""; + if (userID.length > 0) { + [self.class keychainSave:kKBAppleUserIdentifierKey value:userID]; + } + if (self.completion) { + self.completion(credential, nil); + } + } + self.completion = nil; + self.presentingVC = nil; +} + +- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithError:(NSError *)error API_AVAILABLE(ios(13.0)) { + if (self.completion) { + self.completion(nil, error); + } + self.completion = nil; + self.presentingVC = nil; +} + +#pragma mark - 授权界面展示锚点 (ASAuthorizationControllerPresentationContextProviding) + +- (ASPresentationAnchor)presentationAnchorForAuthorizationController:(ASAuthorizationController *)controller API_AVAILABLE(ios(13.0)) { + return self.presentingVC.view.window ?: UIApplication.sharedApplication.keyWindow; +} + +#pragma mark - Keychain 工具 + +// 本地登出:删除已存储的 userIdentifier,使 App 重新要求登录 +- (void)signOut { + NSDictionary *query = @{(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword, + (__bridge id)kSecAttrService: kKBAppleUserIdentifierKey, + (__bridge id)kSecAttrAccount: kKBAppleUserIdentifierKey}; + SecItemDelete((__bridge CFDictionaryRef)query); +} + ++ (BOOL)keychainSave:(NSString *)key value:(NSString *)value { + if (!key) return NO; + NSData *data = [value dataUsingEncoding:NSUTF8StringEncoding]; + + NSDictionary *query = @{(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword, + (__bridge id)kSecAttrService: key, + (__bridge id)kSecAttrAccount: key}; + + SecItemDelete((__bridge CFDictionaryRef)query); + + NSMutableDictionary *attributes = [query mutableCopy]; + attributes[(__bridge id)kSecValueData] = data ?: [NSData data]; + + OSStatus status = SecItemAdd((__bridge CFDictionaryRef)attributes, NULL); + return (status == errSecSuccess); +} + ++ (NSString *)keychainLoad:(NSString *)key { + if (!key) return nil; + NSDictionary *query = @{(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword, + (__bridge id)kSecAttrService: key, + (__bridge id)kSecAttrAccount: key, + (__bridge id)kSecReturnData: @YES, + (__bridge id)kSecMatchLimit: (__bridge id)kSecMatchLimitOne}; + + CFTypeRef dataRef = NULL; + OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &dataRef); + if (status != errSecSuccess || !dataRef) return nil; + + NSData *data = (__bridge_transfer NSData *)dataRef; + return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; +} + +@end diff --git a/keyBoard/Class/Me/VC/MyVC.h b/keyBoard/Class/Me/VC/MyVC.h new file mode 100644 index 0000000..a552cbe --- /dev/null +++ b/keyBoard/Class/Me/VC/MyVC.h @@ -0,0 +1,16 @@ +// +// MyVC.h +// keyBoard +// +// Created by Mac on 2025/10/29. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface MyVC : UIViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Me/VC/MyVC.m b/keyBoard/Class/Me/VC/MyVC.m new file mode 100644 index 0000000..b98e244 --- /dev/null +++ b/keyBoard/Class/Me/VC/MyVC.m @@ -0,0 +1,43 @@ +// +// MyVC.m +// keyBoard +// +// Created by Mac on 2025/10/29. +// + +#import "MyVC.h" + +@interface MyVC () + +@end + +@implementation MyVC + +- (void)viewDidLoad { + [super viewDidLoad]; + self.view.backgroundColor = [UIColor whiteColor]; + UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero]; + label.text = @"My"; + label.textColor = [UIColor darkTextColor]; + label.font = [UIFont systemFontOfSize:20 weight:UIFontWeightSemibold]; + [label sizeToFit]; + label.center = self.view.center; + label.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin; + [self.view addSubview:label]; +} + +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ + [KBHUD show]; +} + +/* +#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/Network/KBNetworkManager.h b/keyBoard/Class/Network/KBNetworkManager.h new file mode 100644 index 0000000..c0dfc9e --- /dev/null +++ b/keyBoard/Class/Network/KBNetworkManager.h @@ -0,0 +1,57 @@ +// +// KBNetworkManager.h +// CustomKeyboard +// +// 轻量网络层封装(扩展安全)。支持 GET/POST(JSON)。 +// 注意:键盘扩展需要"允许完全访问"后才可联网, +// 建议由宿主控制器在确认后调用 `setEnabled:YES` 再发起请求。 +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +extern NSErrorDomain const KBNetworkErrorDomain; +typedef NS_ERROR_ENUM(KBNetworkErrorDomain, KBNetworkError) { + KBNetworkErrorDisabled = 1, // 未启用网络(例如未开启完全访问) + KBNetworkErrorInvalidURL = 2, + KBNetworkErrorInvalidResponse = 3, + KBNetworkErrorDecodeFailed = 4, +}; + +/// 简单的 JSON 回调:json 为 NSDictionary/NSArray 或者在非 JSON 情况下返回 NSData +typedef void(^KBNetworkCompletion)(id _Nullable jsonOrData, NSURLResponse * _Nullable response, NSError * _Nullable error); + +@interface KBNetworkManager : NSObject + +/// 单例 ++ (instancetype)shared; + +/// 是否允许网络(默认为 NO,宿主在合适时机置 YES) +@property (atomic, assign, getter=isEnabled) BOOL enabled; + +/// 可选的基础域名,例如 https://api.example.com +@property (nonatomic, strong, nullable) NSURL *baseURL; + +/// 全局默认请求头(每次请求会与局部 headers 合并,局部优先) +@property (nonatomic, copy) NSDictionary *defaultHeaders; + +/// 超时时间(默认 10s) +@property (nonatomic, assign) NSTimeInterval timeout; + +/// GET 请求,parameters 会拼到 URL 上 +- (nullable NSURLSessionDataTask *)GET:(NSString *)path + parameters:(nullable NSDictionary *)parameters + headers:(nullable NSDictionary *)headers + completion:(KBNetworkCompletion)completion; + +/// POST JSON 请求,jsonBody 会以 application/json 发送 +- (nullable NSURLSessionDataTask *)POST:(NSString *)path + jsonBody:(nullable id)jsonBody + headers:(nullable NSDictionary *)headers + completion:(KBNetworkCompletion)completion; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/keyBoard/Class/Network/KBNetworkManager.m b/keyBoard/Class/Network/KBNetworkManager.m new file mode 100644 index 0000000..824109b --- /dev/null +++ b/keyBoard/Class/Network/KBNetworkManager.m @@ -0,0 +1,169 @@ +// +// KBNetworkManager.m +// CustomKeyboard +// + +#import "KBNetworkManager.h" +#import "AFNetworking.h" +#import "KBAuthManager.h" + +NSErrorDomain const KBNetworkErrorDomain = @"com.company.keyboard.network"; + +@interface KBNetworkManager () +@property (nonatomic, strong) AFHTTPSessionManager *manager; // AFN 管理器(ephemeral 配置) +// 私有错误派发 +- (void)fail:(KBNetworkError)code completion:(KBNetworkCompletion)completion; +@end + +@implementation KBNetworkManager + ++ (instancetype)shared { + static KBNetworkManager *m; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ m = [KBNetworkManager new]; }); + return m; +} + +- (instancetype)init { + if (self = [super init]) { + _enabled = NO; // 键盘扩展默认无网络能力,需外部显式开启 + _timeout = 10.0; + _defaultHeaders = @{ @"Accept": @"application/json" }; + // 设置基础域名,路径可相对该地址拼接 + _baseURL = [NSURL URLWithString:KB_BASE_URL]; + } + return self; +} + +#pragma mark - Public + +- (NSURLSessionDataTask *)GET:(NSString *)path + parameters:(NSDictionary *)parameters + headers:(NSDictionary *)headers + completion:(KBNetworkCompletion)completion { + if (![self ensureEnabled:completion]) return nil; + NSString *urlString = [self buildURLStringWithPath:path]; + if (!urlString) { [self fail:KBNetworkErrorInvalidURL completion:completion]; return nil; } + // 使用 AFHTTPRequestSerializer 生成带参数与头的请求 + AFHTTPRequestSerializer *serializer = [AFHTTPRequestSerializer serializer]; + serializer.timeoutInterval = self.timeout; + NSMutableURLRequest *req = [serializer requestWithMethod:@"GET" + URLString:urlString + parameters:parameters + error:NULL]; + [self applyHeaders:headers toMutableRequest:req contentType:nil]; + return [self startAFTaskWithRequest:req completion:completion]; +} + +- (NSURLSessionDataTask *)POST:(NSString *)path + jsonBody:(id)jsonBody + headers:(NSDictionary *)headers + completion:(KBNetworkCompletion)completion { + if (![self ensureEnabled:completion]) return nil; + NSString *urlString = [self buildURLStringWithPath:path]; + if (!urlString) { [self fail:KBNetworkErrorInvalidURL completion:completion]; return nil; } + // 用 JSON 序列化器生成 JSON Body 的请求 + AFJSONRequestSerializer *serializer = [AFJSONRequestSerializer serializer]; + serializer.timeoutInterval = self.timeout; + NSError *error = nil; + NSMutableURLRequest *req = [serializer requestWithMethod:@"POST" + URLString:urlString + parameters:jsonBody + error:&error]; + if (error) { if (completion) completion(nil, nil, error); return nil; } + [self applyHeaders:headers toMutableRequest:req contentType:nil]; + return [self startAFTaskWithRequest:req completion:completion]; +} + +#pragma mark - Core + +- (BOOL)ensureEnabled:(KBNetworkCompletion)completion { + if (!self.isEnabled) { + NSError *e = [NSError errorWithDomain:KBNetworkErrorDomain code:KBNetworkErrorDisabled userInfo:@{NSLocalizedDescriptionKey: @"网络未启用(可能未开启完全访问)"}]; + if (completion) completion(nil, nil, e); + return NO; + } + return YES; +} + +- (NSString *)buildURLStringWithPath:(NSString *)path { + if (path.length == 0) return nil; + if ([path hasPrefix:@"http://"] || [path hasPrefix:@"https://"]) { + return path; + } + if (self.baseURL) { + return [NSURL URLWithString:path relativeToURL:self.baseURL].absoluteURL.absoluteString; + } + return path; // 当无 baseURL 且 path 不是完整 URL 时,让 AFN 处理(可能失败) +} + +- (void)applyHeaders:(NSDictionary *)headers toMutableRequest:(NSMutableURLRequest *)req contentType:(NSString *)contentType { + // 合并默认头与局部头,并注入授权头(若可用)。局部覆盖优先。 + NSMutableDictionary *all = [self.defaultHeaders mutableCopy] ?: [NSMutableDictionary new]; + NSDictionary *auth = [[KBAuthManager shared] authorizationHeader]; + [auth enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *obj, BOOL *stop) { all[key] = obj; }]; + if (contentType) all[@"Content-Type"] = contentType; + [headers enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *obj, BOOL *stop) { all[key] = obj; }]; + [all enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *obj, BOOL *stop) { [req setValue:obj forHTTPHeaderField:key]; }]; +} + +- (NSURLSessionDataTask *)startAFTaskWithRequest:(NSURLRequest *)req completion:(KBNetworkCompletion)completion { + // 响应先用原始数据返回,再按 Content-Type 解析 JSON(与原实现一致) + self.manager.responseSerializer = [AFHTTPResponseSerializer serializer]; + NSURLSessionDataTask *task = [self.manager dataTaskWithRequest:req uploadProgress:nil downloadProgress:nil completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) { + if (error) { if (completion) completion(nil, response, error); return; } + NSData *data = (NSData *)responseObject; + if (![data isKindOfClass:[NSData class]]) { + if (completion) completion(nil, response, [NSError errorWithDomain:KBNetworkErrorDomain code:KBNetworkErrorInvalidResponse userInfo:@{NSLocalizedDescriptionKey:@"无数据"}]); + return; + } + NSString *ct = nil; + if ([response isKindOfClass:[NSHTTPURLResponse class]]) { + ct = ((NSHTTPURLResponse *)response).allHeaderFields[@"Content-Type"]; + } + BOOL looksJSON = (ct && [ct.lowercaseString containsString:@"application/json"]); + if (looksJSON) { + NSError *jsonErr = nil; + id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonErr]; + if (jsonErr) { if (completion) completion(nil, response, [NSError errorWithDomain:KBNetworkErrorDomain code:KBNetworkErrorDecodeFailed userInfo:@{NSLocalizedDescriptionKey:@"JSON解析失败"}]); return; } + if (completion) completion(json, response, nil); + } else { + if (completion) completion(data, response, nil); + } + }]; + [task resume]; + return task; +} + +#pragma mark - AFHTTPSessionManager + +- (AFHTTPSessionManager *)manager { + if (!_manager) { + NSURLSessionConfiguration *cfg = [NSURLSessionConfiguration ephemeralSessionConfiguration]; + cfg.requestCachePolicy = NSURLRequestReloadIgnoringLocalCacheData; + cfg.timeoutIntervalForRequest = self.timeout; + cfg.timeoutIntervalForResource = MAX(self.timeout, 30.0); + if (@available(iOS 11.0, *)) { cfg.waitsForConnectivity = YES; } + _manager = [[AFHTTPSessionManager alloc] initWithBaseURL:nil sessionConfiguration:cfg]; + // 默认不使用 JSON 解析器,保持原生数据,再按需解析 + _manager.responseSerializer = [AFHTTPResponseSerializer serializer]; + } + return _manager; +} + +#pragma mark - Private helpers + +- (void)fail:(KBNetworkError)code completion:(KBNetworkCompletion)completion { + NSString *msg = @"网络错误"; + switch (code) { + case KBNetworkErrorDisabled: msg = @"网络未启用(可能未开启完全访问)"; break; + case KBNetworkErrorInvalidURL: msg = @"无效的URL"; break; + case KBNetworkErrorInvalidResponse: msg = @"无效的响应"; break; + case KBNetworkErrorDecodeFailed: msg = @"解析失败"; break; + default: break; + } + NSError *e = [NSError errorWithDomain:KBNetworkErrorDomain + code:code + userInfo:@{NSLocalizedDescriptionKey: msg}]; + if (completion) completion(nil, nil, e); +} + +@end diff --git a/keyBoard/Class/Shared/KBAuthManager.h b/keyBoard/Class/Shared/KBAuthManager.h new file mode 100644 index 0000000..b43bf2b --- /dev/null +++ b/keyBoard/Class/Shared/KBAuthManager.h @@ -0,0 +1,56 @@ +// +// KBAuthManager.h +// 主 App 与键盘扩展共享使用 +// +// 通过 Keychain Sharing 统一管理用户登录态(access/refresh token)。 +// 线程安全;在保存/清空时同时发送进程内通知与 Darwin 跨进程通知, +// 以便键盘扩展正运行在其他 App 时也能及时感知变更。 +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// Darwin 跨进程通知名称:当令牌更新或清除时发送,用于提示 App/扩展刷新缓存。 +extern NSString * const kKBDarwinAuthChanged; + +/// 进程内通知(NSNotificationCenter):令牌更新或清除时发送。 +extern NSNotificationName const KBAuthChangedNotification; + +/// 简单的会话容器;可按需扩展字段。 +@interface KBAuthSession : NSObject +@property (nonatomic, copy, nullable) NSString *accessToken; +@property (nonatomic, copy, nullable) NSString *refreshToken; +@property (nonatomic, strong, nullable) NSDate *expiryDate; // 可选:过期时间 +@property (nonatomic, copy, nullable) NSString *userIdentifier; // 可选:如“用 Apple 登录”的 userIdentifier +@end + +/// 基于“共享钥匙串”的鉴权管理器(使用 Keychain Sharing 访问组)。 +@interface KBAuthManager : NSObject + ++ (instancetype)shared; + +/// 当前会话(内存缓存),在加载/保存/清除后更新。 +@property (atomic, strong, readonly, nullable) KBAuthSession *current; + +/// 是否已登录:存在 accessToken 且未明显过期(未设置过期时间则只要有 token 即视为已登录)。 +- (BOOL)isLoggedIn; + +/// 从钥匙串加载到内存;通常首次访问时会自动加载。 +- (void)reloadFromKeychain; + +/// 保存令牌到“共享钥匙串”并通知观察者。 +- (BOOL)saveAccessToken:(NSString *)accessToken + refreshToken:(nullable NSString *)refreshToken + expiryDate:(nullable NSDate *)expiryDate + userIdentifier:(nullable NSString *)userIdentifier; + +/// 从钥匙串与内存中清除令牌,并通知观察者。 +- (void)signOut; + +/// 便捷方法:若存在有效令牌,返回 `Authorization` 请求头;否则返回空字典。 +- (NSDictionary *)authorizationHeader; + +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Shared/KBAuthManager.m b/keyBoard/Class/Shared/KBAuthManager.m new file mode 100644 index 0000000..dca7319 --- /dev/null +++ b/keyBoard/Class/Shared/KBAuthManager.m @@ -0,0 +1,211 @@ +// +// KBAuthManager.m +// +// 关键点: +// - 使用固定的 service/account 将 KBAuthSession 序列化后保存到钥匙串; +// - 通过 kSecAttrAccessGroup 指定 Keychain Sharing 访问组,实现 App 与扩展共享; +// - 保存/清除时发送 Darwin 跨进程通知,便于对端刷新缓存; +// + +#import "KBAuthManager.h" +#import +#import "KBConfig.h" // 需要共享钥匙串访问组常量,见 KBConfig.h 中的说明 + +NSString * const kKBDarwinAuthChanged = @"com.keyBoardst.auth.changed"; +NSNotificationName const KBAuthChangedNotification = @"KBAuthChangedNotification"; + +static NSString * const kKBKCService = @"com.keyBoardst.auth"; // 钥匙串 service 名 +static NSString * const kKBKCAccount = @"session"; // 钥匙串 account 键 + +// 用于 Keychain Sharing 的访问组;必须与两个 target 的 entitlements 配置一致。 +// 示例(Capabilities 中勾选 Keychain Sharing 后的值): +// $(AppIdentifierPrefix)com.keyBoardst.shared +// 运行时会被展开为:TN6HHV45BB.com.keyBoardst.shared +#ifndef KB_KEYCHAIN_ACCESS_GROUP +#define KB_KEYCHAIN_ACCESS_GROUP @"TN6HHV45BB.com.keyBoardst.shared" +#endif + +// 过期宽限:若过期时间距离当前 <= 该阈值,则视为已过期。 +static const NSTimeInterval kKBExpiryGrace = 5.0; // 秒 + +@implementation KBAuthSession + ++ (BOOL)supportsSecureCoding { return YES; } + +- (void)encodeWithCoder:(NSCoder *)coder { + [coder encodeObject:self.accessToken forKey:@"accessToken"]; + [coder encodeObject:self.refreshToken forKey:@"refreshToken"]; + [coder encodeObject:self.expiryDate forKey:@"expiryDate"]; + [coder encodeObject:self.userIdentifier forKey:@"userIdentifier"]; +} + +- (instancetype)initWithCoder:(NSCoder *)coder { + if (self = [super init]) { + _accessToken = [coder decodeObjectOfClass:NSString.class forKey:@"accessToken"]; + _refreshToken = [coder decodeObjectOfClass:NSString.class forKey:@"refreshToken"]; + _expiryDate = [coder decodeObjectOfClass:NSDate.class forKey:@"expiryDate"]; + _userIdentifier = [coder decodeObjectOfClass:NSString.class forKey:@"userIdentifier"]; + } + return self; +} + +@end + +@interface KBAuthManager () +@property (atomic, strong, readwrite, nullable) KBAuthSession *current; +@end + +@implementation KBAuthManager + ++ (instancetype)shared { + static KBAuthManager *m; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ m = [KBAuthManager new]; }); + return m; +} + +#if DEBUG +static inline void KBLog(NSString *fmt, ...) { + va_list args; va_start(args, fmt); + NSString *msg = [[NSString alloc] initWithFormat:fmt arguments:args]; + va_end(args); + NSLog(@"[KBAuth] %@", msg); +} +#endif + +- (instancetype)init { + if (self = [super init]) { + [self reloadFromKeychain]; + // 监听 Darwin 跨进程通知(App 与扩展之间) + CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), + (__bridge const void *)(self), + KBAuthDarwinCallback, + (__bridge CFStringRef)kKBDarwinAuthChanged, + NULL, + CFNotificationSuspensionBehaviorDeliverImmediately); + } + return self; +} + +static void KBAuthDarwinCallback(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { + KBAuthManager *self = (__bridge KBAuthManager *)observer; + [self reloadFromKeychain]; +} + +- (void)dealloc { + CFNotificationCenterRemoveObserver(CFNotificationCenterGetDarwinNotifyCenter(), (__bridge const void *)(self), (__bridge CFStringRef)kKBDarwinAuthChanged, NULL); +} + +- (BOOL)isLoggedIn { + KBAuthSession *s = self.current; + if (s.accessToken.length == 0) return NO; + if (!s.expiryDate) return YES; // 未设置过期时间时,只要有 token 即视为已登录 + return ([s.expiryDate timeIntervalSinceNow] > kKBExpiryGrace); +} + +#pragma mark - Public + +- (void)reloadFromKeychain { + NSData *data = [self keychainRead]; + KBAuthSession *session = nil; + if (data.length > 0) { + @try { + session = [NSKeyedUnarchiver unarchivedObjectOfClass:KBAuthSession.class fromData:data error:NULL]; + } @catch (__unused NSException *e) { session = nil; } + } + self.current = session; + [[NSNotificationCenter defaultCenter] postNotificationName:KBAuthChangedNotification object:nil]; // 进程内通知 +} + +- (BOOL)saveAccessToken:(NSString *)accessToken + refreshToken:(NSString *)refreshToken + expiryDate:(NSDate *)expiryDate + userIdentifier:(NSString *)userIdentifier { + KBAuthSession *s = [KBAuthSession new]; + s.accessToken = accessToken ?: @""; + s.refreshToken = refreshToken; + s.expiryDate = expiryDate; + s.userIdentifier = userIdentifier; + + NSError *err = nil; + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:s requiringSecureCoding:YES error:&err]; + if (err || data.length == 0) return NO; + + BOOL ok = [self keychainWrite:data]; + if (ok) { + self.current = s; + // 进程内通知 + [[NSNotificationCenter defaultCenter] postNotificationName:KBAuthChangedNotification object:nil]; + // 跨进程通知(App <-> 扩展) + CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), (__bridge CFStringRef)kKBDarwinAuthChanged, NULL, NULL, true); + } + return ok; +} + +- (void)signOut { + [self keychainDelete]; + self.current = nil; + [[NSNotificationCenter defaultCenter] postNotificationName:KBAuthChangedNotification object:nil]; + CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), (__bridge CFStringRef)kKBDarwinAuthChanged, NULL, NULL, true); +} + +- (NSDictionary *)authorizationHeader { + NSString *t = self.current.accessToken; + if (t.length == 0) return @{}; // 未登录返回空头部 + return @{ @"Authorization": [@"Bearer " stringByAppendingString:t] }; +} + +#pragma mark - Keychain (shared) + +- (NSMutableDictionary *)baseKCQuery { + NSMutableDictionary *q = [@{ (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword, + (__bridge id)kSecAttrService: kKBKCService, + (__bridge id)kSecAttrAccount: kKBKCAccount } mutableCopy]; + // 指定共享访问组(App 与扩展共用同一组) + q[(__bridge id)kSecAttrAccessGroup] = KB_KEYCHAIN_ACCESS_GROUP; + return q; +} + +- (BOOL)keychainWrite:(NSData *)data { + if (!data) return NO; + NSMutableDictionary *query = [self baseKCQuery]; + SecItemDelete((__bridge CFDictionaryRef)query); + + // 设置属性 + query[(__bridge id)kSecValueData] = data; + // 访问控制:设备首次解锁后可读,不随备份迁移 + query[(__bridge id)kSecAttrAccessible] = (__bridge id)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly; + + OSStatus status = SecItemAdd((__bridge CFDictionaryRef)query, NULL); +#if DEBUG + if (status != errSecSuccess) { + KBLog(@"SecItemAdd failed status=%ld group=%@", (long)status, KB_KEYCHAIN_ACCESS_GROUP); + } else { + KBLog(@"SecItemAdd ok group=%@", KB_KEYCHAIN_ACCESS_GROUP); + } +#endif + return (status == errSecSuccess); +} + +- (NSData *)keychainRead { + NSMutableDictionary *query = [self baseKCQuery]; + query[(__bridge id)kSecReturnData] = @YES; + query[(__bridge id)kSecMatchLimit] = (__bridge id)kSecMatchLimitOne; + + CFTypeRef dataRef = NULL; + OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &dataRef); +#if DEBUG + if (status != errSecSuccess) { + KBLog(@"SecItemCopyMatching status=%ld group=%@ (item not found or no entitlement)", (long)status, KB_KEYCHAIN_ACCESS_GROUP); + } else { + KBLog(@"SecItemCopyMatching ok group=%@", KB_KEYCHAIN_ACCESS_GROUP); + } +#endif + if (status != errSecSuccess || !dataRef) return nil; + return (__bridge_transfer NSData *)dataRef; +} + +- (void)keychainDelete { + NSDictionary *query = [self baseKCQuery]; + SecItemDelete((__bridge CFDictionaryRef)query); +} + +@end diff --git a/keyBoard/Class/Shared/KBConfig.h b/keyBoard/Class/Shared/KBConfig.h new file mode 100644 index 0000000..5813a63 --- /dev/null +++ b/keyBoard/Class/Shared/KBConfig.h @@ -0,0 +1,33 @@ +// +// KBConfig.h +// 主 App 与键盘扩展共用的配置/宏。 +// +// 在此处修改后,会通过 PCH 被两个 target 同步引用。 +// + +#ifndef KBConfig_h +#define KBConfig_h + +// 基础baseUrl +#ifndef KB_BASE_URL +#define KB_BASE_URL @"https://m1.apifoxmock.com/m1/5438099-5113192-default/" +#endif + +// Universal Links 通用链接 +#ifndef KB_UL_BASE +#define KB_UL_BASE @"https://your.domain/ul" +#endif + +#define KB_UL_LOGIN KB_UL_BASE @"/login" +#define KB_UL_SETTINGS KB_UL_BASE @"/settings" + +#endif /* KBConfig_h */ + +// --- 认证/共享钥匙串 配置 --- +// 若已在 Capabilities 中启用 Keychain Sharing,并添加访问组: +// $(AppIdentifierPrefix)com.keyBoardst.shared +// 运行时会展开为:TN6HHV45BB.com.keyBoardst.shared +// KBAuthManager 通过下面的宏定位访问组;如需修改,可在 Build Settings 或前缀头中覆盖该宏。 +#ifndef KB_KEYCHAIN_ACCESS_GROUP +#define KB_KEYCHAIN_ACCESS_GROUP @"TN6HHV45BB.com.keyBoardst.shared" +#endif diff --git a/keyBoard/Info.plist b/keyBoard/Info.plist index 6a6654d..6ab2b09 100644 --- a/keyBoard/Info.plist +++ b/keyBoard/Info.plist @@ -2,6 +2,17 @@ + CFBundleURLTypes + + + CFBundleURLName + com.keyBoardst.keyboard + CFBundleURLSchemes + + kbkeyboard + + + NSAppTransportSecurity NSAllowsArbitraryLoads diff --git a/keyBoard/KeyBoardPrefixHeader.pch b/keyBoard/KeyBoardPrefixHeader.pch index 0842fc8..b8caeb7 100644 --- a/keyBoard/KeyBoardPrefixHeader.pch +++ b/keyBoard/KeyBoardPrefixHeader.pch @@ -15,7 +15,88 @@ /// 三方 #import +// 公共配置 +#import "KBConfig.h" +/// 系统 +#import +#import "KBHUD.h" +#import "KBNetworkManager.h" + + +/// 项目 +#import "UIViewController+Extension.h" +#import "BaseNavigationController.h" +#import "BaseTableView.h" +#import "BaseCell.h" +#import "KBLocalizationManager.h" // 全局多语言封装 + + +//-----------------------------------------------宏定义全局----------------------------------------------------------/ +// 通用链接(Universal Links)统一配置 +// 仅需修改这里的域名/前缀,工程内所有使用 UL 的地方都会同步。 +#define KB_UL_BASE @"https://your.domain/ul" // 替换为你的真实域名与前缀路径 +#define KB_UL_LOGIN KB_UL_BASE @"/login" +#define KB_UL_SETTINGS KB_UL_BASE @"/settings" + +/// UI 尺寸/设备宏 +// 屏幕尺寸 +#define KB_SCREEN_WIDTH ([UIScreen mainScreen].bounds.size.width) +#define KB_SCREEN_HEIGHT ([UIScreen mainScreen].bounds.size.height) +#define KB_ONE_PIXEL (1.0 / [UIScreen mainScreen].scale) + +// 基础高度 +#define KB_NAVBAR_BASE_HEIGHT 44.0 +#define KB_TABBAR_BASE_HEIGHT 49.0 + +// 当前 KeyWindow(iOS 13 场景化兼容) +static inline UIWindow *KB_KeyWindow(void) { + 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; +} + +// Safe Area +static inline UIEdgeInsets KB_SafeAreaInsets(void) { + if (@available(iOS 11.0, *)) { + UIWindow *w = KB_KeyWindow(); + return w ? w.safeAreaInsets : UIEdgeInsetsZero; + } + return UIEdgeInsetsZero; +} + +static inline CGFloat KB_SafeAreaTop(void) { return KB_SafeAreaInsets().top; } +static inline CGFloat KB_SafeAreaBottom(void) { return KB_SafeAreaInsets().bottom; } + +// 状态栏高度(iOS13+ 兼容) +static inline CGFloat KB_StatusBarHeight(void) { + if (@available(iOS 13.0, *)) { + UIWindow *w = KB_KeyWindow(); + UIStatusBarManager *m = w.windowScene.statusBarManager; + return m ? m.statusBarFrame.size.height : 0.0; + } else { + return UIApplication.sharedApplication.statusBarFrame.size.height; + } +} + +// 导航栏+状态栏总高度、TabBar 高度、是否异形屏 +#define KB_STATUSBAR_HEIGHT (KB_StatusBarHeight()) +#define KB_NAV_TOTAL_HEIGHT (KB_NAVBAR_BASE_HEIGHT + KB_StatusBarHeight()) +#define KB_TABBAR_HEIGHT (KB_TABBAR_BASE_HEIGHT + KB_SafeAreaBottom()) +#define KB_IS_IPHONEX_SERIES (KB_SafeAreaBottom() > 0.0) #endif /* KeyBoardPrefixHeader_pch */ diff --git a/keyBoard/Shared/KBAuthManager.h b/keyBoard/Shared/KBAuthManager.h new file mode 100644 index 0000000..b43bf2b --- /dev/null +++ b/keyBoard/Shared/KBAuthManager.h @@ -0,0 +1,56 @@ +// +// KBAuthManager.h +// 主 App 与键盘扩展共享使用 +// +// 通过 Keychain Sharing 统一管理用户登录态(access/refresh token)。 +// 线程安全;在保存/清空时同时发送进程内通知与 Darwin 跨进程通知, +// 以便键盘扩展正运行在其他 App 时也能及时感知变更。 +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// Darwin 跨进程通知名称:当令牌更新或清除时发送,用于提示 App/扩展刷新缓存。 +extern NSString * const kKBDarwinAuthChanged; + +/// 进程内通知(NSNotificationCenter):令牌更新或清除时发送。 +extern NSNotificationName const KBAuthChangedNotification; + +/// 简单的会话容器;可按需扩展字段。 +@interface KBAuthSession : NSObject +@property (nonatomic, copy, nullable) NSString *accessToken; +@property (nonatomic, copy, nullable) NSString *refreshToken; +@property (nonatomic, strong, nullable) NSDate *expiryDate; // 可选:过期时间 +@property (nonatomic, copy, nullable) NSString *userIdentifier; // 可选:如“用 Apple 登录”的 userIdentifier +@end + +/// 基于“共享钥匙串”的鉴权管理器(使用 Keychain Sharing 访问组)。 +@interface KBAuthManager : NSObject + ++ (instancetype)shared; + +/// 当前会话(内存缓存),在加载/保存/清除后更新。 +@property (atomic, strong, readonly, nullable) KBAuthSession *current; + +/// 是否已登录:存在 accessToken 且未明显过期(未设置过期时间则只要有 token 即视为已登录)。 +- (BOOL)isLoggedIn; + +/// 从钥匙串加载到内存;通常首次访问时会自动加载。 +- (void)reloadFromKeychain; + +/// 保存令牌到“共享钥匙串”并通知观察者。 +- (BOOL)saveAccessToken:(NSString *)accessToken + refreshToken:(nullable NSString *)refreshToken + expiryDate:(nullable NSDate *)expiryDate + userIdentifier:(nullable NSString *)userIdentifier; + +/// 从钥匙串与内存中清除令牌,并通知观察者。 +- (void)signOut; + +/// 便捷方法:若存在有效令牌,返回 `Authorization` 请求头;否则返回空字典。 +- (NSDictionary *)authorizationHeader; + +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Shared/KBAuthManager.m b/keyBoard/Shared/KBAuthManager.m new file mode 100644 index 0000000..dca7319 --- /dev/null +++ b/keyBoard/Shared/KBAuthManager.m @@ -0,0 +1,211 @@ +// +// KBAuthManager.m +// +// 关键点: +// - 使用固定的 service/account 将 KBAuthSession 序列化后保存到钥匙串; +// - 通过 kSecAttrAccessGroup 指定 Keychain Sharing 访问组,实现 App 与扩展共享; +// - 保存/清除时发送 Darwin 跨进程通知,便于对端刷新缓存; +// + +#import "KBAuthManager.h" +#import +#import "KBConfig.h" // 需要共享钥匙串访问组常量,见 KBConfig.h 中的说明 + +NSString * const kKBDarwinAuthChanged = @"com.keyBoardst.auth.changed"; +NSNotificationName const KBAuthChangedNotification = @"KBAuthChangedNotification"; + +static NSString * const kKBKCService = @"com.keyBoardst.auth"; // 钥匙串 service 名 +static NSString * const kKBKCAccount = @"session"; // 钥匙串 account 键 + +// 用于 Keychain Sharing 的访问组;必须与两个 target 的 entitlements 配置一致。 +// 示例(Capabilities 中勾选 Keychain Sharing 后的值): +// $(AppIdentifierPrefix)com.keyBoardst.shared +// 运行时会被展开为:TN6HHV45BB.com.keyBoardst.shared +#ifndef KB_KEYCHAIN_ACCESS_GROUP +#define KB_KEYCHAIN_ACCESS_GROUP @"TN6HHV45BB.com.keyBoardst.shared" +#endif + +// 过期宽限:若过期时间距离当前 <= 该阈值,则视为已过期。 +static const NSTimeInterval kKBExpiryGrace = 5.0; // 秒 + +@implementation KBAuthSession + ++ (BOOL)supportsSecureCoding { return YES; } + +- (void)encodeWithCoder:(NSCoder *)coder { + [coder encodeObject:self.accessToken forKey:@"accessToken"]; + [coder encodeObject:self.refreshToken forKey:@"refreshToken"]; + [coder encodeObject:self.expiryDate forKey:@"expiryDate"]; + [coder encodeObject:self.userIdentifier forKey:@"userIdentifier"]; +} + +- (instancetype)initWithCoder:(NSCoder *)coder { + if (self = [super init]) { + _accessToken = [coder decodeObjectOfClass:NSString.class forKey:@"accessToken"]; + _refreshToken = [coder decodeObjectOfClass:NSString.class forKey:@"refreshToken"]; + _expiryDate = [coder decodeObjectOfClass:NSDate.class forKey:@"expiryDate"]; + _userIdentifier = [coder decodeObjectOfClass:NSString.class forKey:@"userIdentifier"]; + } + return self; +} + +@end + +@interface KBAuthManager () +@property (atomic, strong, readwrite, nullable) KBAuthSession *current; +@end + +@implementation KBAuthManager + ++ (instancetype)shared { + static KBAuthManager *m; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ m = [KBAuthManager new]; }); + return m; +} + +#if DEBUG +static inline void KBLog(NSString *fmt, ...) { + va_list args; va_start(args, fmt); + NSString *msg = [[NSString alloc] initWithFormat:fmt arguments:args]; + va_end(args); + NSLog(@"[KBAuth] %@", msg); +} +#endif + +- (instancetype)init { + if (self = [super init]) { + [self reloadFromKeychain]; + // 监听 Darwin 跨进程通知(App 与扩展之间) + CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), + (__bridge const void *)(self), + KBAuthDarwinCallback, + (__bridge CFStringRef)kKBDarwinAuthChanged, + NULL, + CFNotificationSuspensionBehaviorDeliverImmediately); + } + return self; +} + +static void KBAuthDarwinCallback(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { + KBAuthManager *self = (__bridge KBAuthManager *)observer; + [self reloadFromKeychain]; +} + +- (void)dealloc { + CFNotificationCenterRemoveObserver(CFNotificationCenterGetDarwinNotifyCenter(), (__bridge const void *)(self), (__bridge CFStringRef)kKBDarwinAuthChanged, NULL); +} + +- (BOOL)isLoggedIn { + KBAuthSession *s = self.current; + if (s.accessToken.length == 0) return NO; + if (!s.expiryDate) return YES; // 未设置过期时间时,只要有 token 即视为已登录 + return ([s.expiryDate timeIntervalSinceNow] > kKBExpiryGrace); +} + +#pragma mark - Public + +- (void)reloadFromKeychain { + NSData *data = [self keychainRead]; + KBAuthSession *session = nil; + if (data.length > 0) { + @try { + session = [NSKeyedUnarchiver unarchivedObjectOfClass:KBAuthSession.class fromData:data error:NULL]; + } @catch (__unused NSException *e) { session = nil; } + } + self.current = session; + [[NSNotificationCenter defaultCenter] postNotificationName:KBAuthChangedNotification object:nil]; // 进程内通知 +} + +- (BOOL)saveAccessToken:(NSString *)accessToken + refreshToken:(NSString *)refreshToken + expiryDate:(NSDate *)expiryDate + userIdentifier:(NSString *)userIdentifier { + KBAuthSession *s = [KBAuthSession new]; + s.accessToken = accessToken ?: @""; + s.refreshToken = refreshToken; + s.expiryDate = expiryDate; + s.userIdentifier = userIdentifier; + + NSError *err = nil; + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:s requiringSecureCoding:YES error:&err]; + if (err || data.length == 0) return NO; + + BOOL ok = [self keychainWrite:data]; + if (ok) { + self.current = s; + // 进程内通知 + [[NSNotificationCenter defaultCenter] postNotificationName:KBAuthChangedNotification object:nil]; + // 跨进程通知(App <-> 扩展) + CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), (__bridge CFStringRef)kKBDarwinAuthChanged, NULL, NULL, true); + } + return ok; +} + +- (void)signOut { + [self keychainDelete]; + self.current = nil; + [[NSNotificationCenter defaultCenter] postNotificationName:KBAuthChangedNotification object:nil]; + CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), (__bridge CFStringRef)kKBDarwinAuthChanged, NULL, NULL, true); +} + +- (NSDictionary *)authorizationHeader { + NSString *t = self.current.accessToken; + if (t.length == 0) return @{}; // 未登录返回空头部 + return @{ @"Authorization": [@"Bearer " stringByAppendingString:t] }; +} + +#pragma mark - Keychain (shared) + +- (NSMutableDictionary *)baseKCQuery { + NSMutableDictionary *q = [@{ (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword, + (__bridge id)kSecAttrService: kKBKCService, + (__bridge id)kSecAttrAccount: kKBKCAccount } mutableCopy]; + // 指定共享访问组(App 与扩展共用同一组) + q[(__bridge id)kSecAttrAccessGroup] = KB_KEYCHAIN_ACCESS_GROUP; + return q; +} + +- (BOOL)keychainWrite:(NSData *)data { + if (!data) return NO; + NSMutableDictionary *query = [self baseKCQuery]; + SecItemDelete((__bridge CFDictionaryRef)query); + + // 设置属性 + query[(__bridge id)kSecValueData] = data; + // 访问控制:设备首次解锁后可读,不随备份迁移 + query[(__bridge id)kSecAttrAccessible] = (__bridge id)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly; + + OSStatus status = SecItemAdd((__bridge CFDictionaryRef)query, NULL); +#if DEBUG + if (status != errSecSuccess) { + KBLog(@"SecItemAdd failed status=%ld group=%@", (long)status, KB_KEYCHAIN_ACCESS_GROUP); + } else { + KBLog(@"SecItemAdd ok group=%@", KB_KEYCHAIN_ACCESS_GROUP); + } +#endif + return (status == errSecSuccess); +} + +- (NSData *)keychainRead { + NSMutableDictionary *query = [self baseKCQuery]; + query[(__bridge id)kSecReturnData] = @YES; + query[(__bridge id)kSecMatchLimit] = (__bridge id)kSecMatchLimitOne; + + CFTypeRef dataRef = NULL; + OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &dataRef); +#if DEBUG + if (status != errSecSuccess) { + KBLog(@"SecItemCopyMatching status=%ld group=%@ (item not found or no entitlement)", (long)status, KB_KEYCHAIN_ACCESS_GROUP); + } else { + KBLog(@"SecItemCopyMatching ok group=%@", KB_KEYCHAIN_ACCESS_GROUP); + } +#endif + if (status != errSecSuccess || !dataRef) return nil; + return (__bridge_transfer NSData *)dataRef; +} + +- (void)keychainDelete { + NSDictionary *query = [self baseKCQuery]; + SecItemDelete((__bridge CFDictionaryRef)query); +} + +@end diff --git a/keyBoard/Shared/KBConfig.h b/keyBoard/Shared/KBConfig.h new file mode 100644 index 0000000..5813a63 --- /dev/null +++ b/keyBoard/Shared/KBConfig.h @@ -0,0 +1,33 @@ +// +// KBConfig.h +// 主 App 与键盘扩展共用的配置/宏。 +// +// 在此处修改后,会通过 PCH 被两个 target 同步引用。 +// + +#ifndef KBConfig_h +#define KBConfig_h + +// 基础baseUrl +#ifndef KB_BASE_URL +#define KB_BASE_URL @"https://m1.apifoxmock.com/m1/5438099-5113192-default/" +#endif + +// Universal Links 通用链接 +#ifndef KB_UL_BASE +#define KB_UL_BASE @"https://your.domain/ul" +#endif + +#define KB_UL_LOGIN KB_UL_BASE @"/login" +#define KB_UL_SETTINGS KB_UL_BASE @"/settings" + +#endif /* KBConfig_h */ + +// --- 认证/共享钥匙串 配置 --- +// 若已在 Capabilities 中启用 Keychain Sharing,并添加访问组: +// $(AppIdentifierPrefix)com.keyBoardst.shared +// 运行时会展开为:TN6HHV45BB.com.keyBoardst.shared +// KBAuthManager 通过下面的宏定位访问组;如需修改,可在 Build Settings 或前缀头中覆盖该宏。 +#ifndef KB_KEYCHAIN_ACCESS_GROUP +#define KB_KEYCHAIN_ACCESS_GROUP @"TN6HHV45BB.com.keyBoardst.shared" +#endif diff --git a/keyBoard/VC/KBPermissionViewController.h b/keyBoard/VC/KBPermissionViewController.h index e2a77a1..90bced0 100644 --- a/keyBoard/VC/KBPermissionViewController.h +++ b/keyBoard/VC/KBPermissionViewController.h @@ -11,6 +11,11 @@ NS_ASSUME_NONNULL_BEGIN @interface KBPermissionViewController : UIViewController +/// 点击页面左上角“返回”时回调。用于让调用方(如 KBGuideVC)一起退出等自定义行为。 +/// 注意:避免与按钮 action `onBack` 重名,故命名为 backHandler。 +@property (nonatomic, copy, nullable) void (^backHandler)(void); +@property (nonatomic, strong) UIButton *backButton; // 左上角返回 + @end NS_ASSUME_NONNULL_END diff --git a/keyBoard/VC/KBPermissionViewController.m b/keyBoard/VC/KBPermissionViewController.m index 83692c8..6ba3ed3 100644 --- a/keyBoard/VC/KBPermissionViewController.m +++ b/keyBoard/VC/KBPermissionViewController.m @@ -6,10 +6,13 @@ // #import "KBPermissionViewController.h" -#import @interface KBPermissionViewController () - +@property (nonatomic, strong) UILabel *titleLabel; // 标题 +@property (nonatomic, strong) UILabel *tipsLabel; // 步骤提示 +@property (nonatomic, strong) UIView *cardView; // 中部卡片 +@property (nonatomic, strong) UIButton *openButton; // 去设置 +@property (nonatomic, strong) UILabel *helpLabel; // 底部帮助 @end @implementation KBPermissionViewController @@ -18,66 +21,83 @@ [super viewDidLoad]; self.view.backgroundColor = [UIColor colorWithWhite:0.96 alpha:1.0]; - UIButton *close = [UIButton buttonWithType:UIButtonTypeSystem]; - [close setTitle:@"X" forState:UIControlStateNormal]; - close.titleLabel.font = [UIFont systemFontOfSize:20 weight:UIFontWeightSemibold]; - close.tintColor = [UIColor darkTextColor]; - close.frame = CGRectMake(self.view.bounds.size.width - 44, 44, 28, 28); - close.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleBottomMargin; - [close addTarget:self action:@selector(dismissSelf) forControlEvents:UIControlEventTouchUpInside]; - [self.view addSubview:close]; + // 懒加载控件 + 添加到视图 + [self.view addSubview:self.backButton]; + [self.view addSubview:self.titleLabel]; + [self.view addSubview:self.tipsLabel]; + [self.view addSubview:self.cardView]; + [self.view addSubview:self.openButton]; + [self.view addSubview:self.helpLabel]; - UILabel *title = [[UILabel alloc] init]; - title.text = @"启用输入法"; - title.font = [UIFont systemFontOfSize:22 weight:UIFontWeightSemibold]; - title.textColor = [UIColor blackColor]; - title.textAlignment = NSTextAlignmentCenter; - title.frame = CGRectMake(24, 100, self.view.bounds.size.width - 48, 28); - title.autoresizingMask = UIViewAutoresizingFlexibleWidth; - [self.view addSubview:title]; + // Masonry 约束 + [self.backButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.view).offset(16); + make.top.equalTo(self.view.mas_safeAreaLayoutGuideTop).offset(8); + + make.width.mas_equalTo(60); + make.height.mas_equalTo(32); + }]; - UILabel *tips = [[UILabel alloc] init]; - tips.text = @"1 开启键盘 > 2 允许完全访问"; - tips.font = [UIFont systemFontOfSize:14]; - tips.textColor = [UIColor darkGrayColor]; - tips.textAlignment = NSTextAlignmentCenter; - tips.frame = CGRectMake(24, CGRectGetMaxY(title.frame) + 8, self.view.bounds.size.width - 48, 20); - tips.autoresizingMask = UIViewAutoresizingFlexibleWidth; - [self.view addSubview:tips]; + [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.view.mas_safeAreaLayoutGuideTop).offset(48); + + make.left.equalTo(self.view).offset(24); + make.right.equalTo(self.view).offset(-24); + make.height.mas_equalTo(28); + }]; - UIView *card = [[UIView alloc] initWithFrame:CGRectMake(32, CGRectGetMaxY(tips.frame) + 28, self.view.bounds.size.width - 64, 260)]; - card.backgroundColor = [UIColor whiteColor]; - card.layer.cornerRadius = 16; - card.layer.shadowColor = [UIColor colorWithWhite:0 alpha:0.1].CGColor; - card.layer.shadowOpacity = 1; - card.layer.shadowRadius = 12; - [self.view addSubview:card]; + [self.tipsLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.titleLabel.mas_bottom).offset(8); + make.left.equalTo(self.view).offset(24); + make.right.equalTo(self.view).offset(-24); + }]; - UIButton *open = [UIButton buttonWithType:UIButtonTypeSystem]; - [open setTitle:@"去设置中开启" forState:UIControlStateNormal]; - open.titleLabel.font = [UIFont systemFontOfSize:17 weight:UIFontWeightSemibold]; - [open setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - open.backgroundColor = [UIColor colorWithRed:0.22 green:0.49 blue:0.96 alpha:1.0]; - open.layer.cornerRadius = 8; - CGFloat btnW = self.view.bounds.size.width - 64; - open.frame = CGRectMake(32, CGRectGetMaxY(card.frame) + 32, btnW, 48); - open.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin; - [open addTarget:self action:@selector(openSettings) forControlEvents:UIControlEventTouchUpInside]; - [self.view addSubview:open]; + [self.cardView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.tipsLabel.mas_bottom).offset(28); + make.left.equalTo(self.view).offset(32); + make.right.equalTo(self.view).offset(-32); + make.height.mas_equalTo(260); + }]; - UILabel *help = [[UILabel alloc] init]; - help.text = @"没有找到键盘? 请前往 设置 > 通用 > 键盘 > 键盘 > 添加新键盘"; - help.font = [UIFont systemFontOfSize:12]; - help.textColor = [UIColor grayColor]; - help.textAlignment = NSTextAlignmentCenter; - help.numberOfLines = 2; - help.frame = CGRectMake(24, CGRectGetMaxY(open.frame) + 12, self.view.bounds.size.width - 48, 36); - help.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin; - [self.view addSubview:help]; + [self.openButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.cardView.mas_bottom).offset(32); + make.left.equalTo(self.view).offset(32); + make.right.equalTo(self.view).offset(-32); + make.height.mas_equalTo(48); + }]; + + [self.helpLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.openButton.mas_bottom).offset(12); + make.left.equalTo(self.view).offset(24); + make.right.equalTo(self.view).offset(-24); + }]; } -- (void)dismissSelf { - [self dismissViewControllerAnimated:YES completion:nil]; +#pragma mark - Actions + +- (void)onBack { + // 支持两种展示方式: + // 1) 作为子控制器嵌入(无 presentingViewController)→ 交由回调让父 VC 处理(通常 pop) + // 2) 作为模态弹出 → 按原策略先 pop 再 dismiss + UIViewController *presenter = self.presentingViewController; + if (!presenter) { + if (self.backHandler) self.backHandler(); + return; + } + + UINavigationController *nav = nil; + if ([presenter isKindOfClass:UINavigationController.class]) { + nav = (UINavigationController *)presenter; + } else if (presenter.navigationController) { + nav = presenter.navigationController; + } + + if (nav) { + [nav popViewControllerAnimated:NO]; + [nav dismissViewControllerAnimated:YES completion:^{ if (self.backHandler) self.backHandler(); }]; + } else { + [self dismissViewControllerAnimated:YES completion:^{ if (self.backHandler) self.backHandler(); }]; + } } - (void)openSettings { @@ -92,4 +112,76 @@ } } +#pragma mark - Lazy Subviews + +- (UIButton *)backButton { + if (!_backButton) { + _backButton = [UIButton buttonWithType:UIButtonTypeSystem]; + [_backButton setTitle:KBLocalized(@"common_back") forState:UIControlStateNormal]; + _backButton.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightMedium]; + [_backButton setTitleColor:[UIColor darkTextColor] forState:UIControlStateNormal]; + [_backButton addTarget:self action:@selector(onBack) forControlEvents:UIControlEventTouchUpInside]; + } + return _backButton; +} + +- (UILabel *)titleLabel { + if (!_titleLabel) { + _titleLabel = [UILabel new]; + _titleLabel.text = KBLocalized(@"perm_title_enable"); + _titleLabel.font = [UIFont systemFontOfSize:22 weight:UIFontWeightSemibold]; + _titleLabel.textColor = [UIColor blackColor]; + _titleLabel.textAlignment = NSTextAlignmentCenter; + } + return _titleLabel; +} + +- (UILabel *)tipsLabel { + if (!_tipsLabel) { + _tipsLabel = [UILabel new]; + _tipsLabel.text = KBLocalized(@"perm_steps"); + _tipsLabel.font = [UIFont systemFontOfSize:14]; + _tipsLabel.textColor = [UIColor darkGrayColor]; + _tipsLabel.textAlignment = NSTextAlignmentCenter; + } + return _tipsLabel; +} + +- (UIView *)cardView { + if (!_cardView) { + _cardView = [UIView new]; + _cardView.backgroundColor = [UIColor whiteColor]; + _cardView.layer.cornerRadius = 16; + _cardView.layer.shadowColor = [UIColor colorWithWhite:0 alpha:0.1].CGColor; + _cardView.layer.shadowOpacity = 1; + _cardView.layer.shadowRadius = 12; + } + return _cardView; +} + +- (UIButton *)openButton { + if (!_openButton) { + _openButton = [UIButton buttonWithType:UIButtonTypeSystem]; + [_openButton setTitle:KBLocalized(@"perm_open_settings") forState:UIControlStateNormal]; + _openButton.titleLabel.font = [UIFont systemFontOfSize:17 weight:UIFontWeightSemibold]; + [_openButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + _openButton.backgroundColor = [UIColor colorWithRed:0.22 green:0.49 blue:0.96 alpha:1.0]; + _openButton.layer.cornerRadius = 8; + [_openButton addTarget:self action:@selector(openSettings) forControlEvents:UIControlEventTouchUpInside]; + } + return _openButton; +} + +- (UILabel *)helpLabel { + if (!_helpLabel) { + _helpLabel = [UILabel new]; + _helpLabel.text = KBLocalized(@"perm_help"); + _helpLabel.font = [UIFont systemFontOfSize:12]; + _helpLabel.textColor = [UIColor grayColor]; + _helpLabel.textAlignment = NSTextAlignmentCenter; + _helpLabel.numberOfLines = 2; + } + return _helpLabel; +} + @end diff --git a/keyBoard/keyBoard.entitlements b/keyBoard/keyBoard.entitlements new file mode 100644 index 0000000..1cc6c2d --- /dev/null +++ b/keyBoard/keyBoard.entitlements @@ -0,0 +1,14 @@ + + + + + com.apple.developer.applesignin + + Default + + keychain-access-groups + + $(AppIdentifierPrefix)com.keyBoardst.shared + + +