├── .gitignore
├── LICENSE
├── LookinDemo
├── LookinCustomInfoDemo
│ ├── LookinCustomInfoDemo.xcodeproj
│ │ ├── project.pbxproj
│ │ ├── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata
│ │ │ │ └── IDEWorkspaceChecks.plist
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ └── LookinCustomInfoDemo.xcscheme
│ ├── LookinCustomInfoDemo.xcworkspace
│ │ └── contents.xcworkspacedata
│ ├── LookinCustomInfoDemo
│ │ ├── AppDelegate.swift
│ │ ├── Assets.xcassets
│ │ │ ├── AccentColor.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── AppIcon.appiconset
│ │ │ │ └── Contents.json
│ │ │ └── Contents.json
│ │ ├── Base.lproj
│ │ │ ├── LaunchScreen.storyboard
│ │ │ └── Main.storyboard
│ │ ├── Demo
│ │ │ ├── ObjectiveC
│ │ │ │ ├── CatView.h
│ │ │ │ ├── CatView.m
│ │ │ │ ├── DogLayer.h
│ │ │ │ ├── DogLayer.m
│ │ │ │ ├── SomeViewModel.h
│ │ │ │ ├── SomeViewModel.m
│ │ │ │ ├── UIView+Custom.h
│ │ │ │ └── UIView+Custom.m
│ │ │ └── Swift
│ │ │ │ ├── BirdView.swift
│ │ │ │ ├── CALayer+Custom.swift
│ │ │ │ ├── GoodViewModel.swift
│ │ │ │ └── HorseLayer.swift
│ │ ├── Info.plist
│ │ ├── LookinCustomInfoDemo-Bridging-Header.h
│ │ ├── SceneDelegate.swift
│ │ └── ViewController.swift
│ ├── Podfile
│ └── Podfile.lock
├── OC_Pod
│ ├── LookinDemoOC.xcodeproj
│ │ ├── project.pbxproj
│ │ ├── project.xcworkspace
│ │ │ └── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ └── LookinDemoOC.xcscheme
│ ├── LookinDemoOC.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ ├── LookinDemoOC
│ │ ├── AppDelegate.h
│ │ ├── AppDelegate.m
│ │ ├── Assets.xcassets
│ │ │ ├── AccentColor.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── AppIcon.appiconset
│ │ │ │ └── Contents.json
│ │ │ ├── Contents.json
│ │ │ └── Logo_128.imageset
│ │ │ │ ├── Contents.json
│ │ │ │ └── Logo_128.png
│ │ ├── Base.lproj
│ │ │ ├── LaunchScreen.storyboard
│ │ │ └── Main.storyboard
│ │ ├── CatView.h
│ │ ├── CatView.m
│ │ ├── Info.plist
│ │ ├── SceneDelegate.h
│ │ ├── SceneDelegate.m
│ │ ├── ViewController.h
│ │ ├── ViewController.m
│ │ └── main.m
│ ├── Podfile
│ └── Podfile.lock
├── Swift_SPM_Debug
│ ├── LookinDemoSwift.xcodeproj
│ │ ├── project.pbxproj
│ │ ├── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata
│ │ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ │ └── swiftpm
│ │ │ │ └── Package.resolved
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ └── LookinDemoSwift.xcscheme
│ └── LookinDemoSwift
│ │ ├── AppDelegate.swift
│ │ ├── Assets.xcassets
│ │ ├── AccentColor.colorset
│ │ │ └── Contents.json
│ │ ├── AppIcon.appiconset
│ │ │ └── Contents.json
│ │ └── Contents.json
│ │ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ │ ├── Info.plist
│ │ ├── SceneDelegate.swift
│ │ └── ViewController.swift
├── Swift_SPM_Release
│ ├── LookinDemoSwift.xcodeproj
│ │ ├── project.pbxproj
│ │ ├── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata
│ │ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ │ └── swiftpm
│ │ │ │ └── Package.resolved
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ └── LookinDemoSwift.xcscheme
│ └── LookinDemoSwift
│ │ ├── AppDelegate.swift
│ │ ├── Assets.xcassets
│ │ ├── AccentColor.colorset
│ │ │ └── Contents.json
│ │ ├── AppIcon.appiconset
│ │ │ └── Contents.json
│ │ └── Contents.json
│ │ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ │ ├── Info.plist
│ │ ├── SceneDelegate.swift
│ │ └── ViewController.swift
└── TestVisionOS
│ ├── Podfile
│ ├── Podfile.lock
│ ├── TestVisionOS.xcodeproj
│ ├── project.pbxproj
│ └── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
│ ├── TestVisionOS.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
│ └── TestVisionOS
│ ├── Assets.xcassets
│ ├── AppIcon.solidimagestack
│ │ ├── Back.solidimagestacklayer
│ │ │ ├── Content.imageset
│ │ │ │ └── Contents.json
│ │ │ └── Contents.json
│ │ ├── Contents.json
│ │ ├── Front.solidimagestacklayer
│ │ │ ├── Content.imageset
│ │ │ │ └── Contents.json
│ │ │ └── Contents.json
│ │ └── Middle.solidimagestacklayer
│ │ │ ├── Content.imageset
│ │ │ └── Contents.json
│ │ │ └── Contents.json
│ └── Contents.json
│ ├── ContentView.swift
│ ├── Info.plist
│ ├── Preview Content
│ └── Preview Assets.xcassets
│ │ └── Contents.json
│ └── TestVisionOSApp.swift
├── LookinServer.podspec
├── LookinShared.podspec
├── Package.swift
├── README.md
└── Src
├── Base
├── LookinIvarTrace.h
└── LookinIvarTrace.m
├── Main
├── Server
│ ├── Category
│ │ ├── CALayer+LookinServer.h
│ │ ├── CALayer+LookinServer.m
│ │ ├── NSObject+LookinServer.h
│ │ ├── NSObject+LookinServer.m
│ │ ├── UIBlurEffect+LookinServer.h
│ │ ├── UIBlurEffect+LookinServer.m
│ │ ├── UIColor+LookinServer.h
│ │ ├── UIColor+LookinServer.m
│ │ ├── UIImage+LookinServer.h
│ │ ├── UIImage+LookinServer.m
│ │ ├── UIImageView+LookinServer.h
│ │ ├── UIImageView+LookinServer.m
│ │ ├── UILabel+LookinServer.h
│ │ ├── UILabel+LookinServer.m
│ │ ├── UITableView+LookinServer.h
│ │ ├── UITableView+LookinServer.m
│ │ ├── UITextField+LookinServer.h
│ │ ├── UITextField+LookinServer.m
│ │ ├── UITextView+LookinServer.h
│ │ ├── UITextView+LookinServer.m
│ │ ├── UIView+LookinServer.h
│ │ ├── UIView+LookinServer.m
│ │ ├── UIViewController+LookinServer.h
│ │ ├── UIViewController+LookinServer.m
│ │ ├── UIVisualEffectView+LookinServer.h
│ │ └── UIVisualEffectView+LookinServer.m
│ ├── Connection
│ │ ├── LKS_ConnectionManager.h
│ │ ├── LKS_ConnectionManager.m
│ │ ├── LKS_RequestHandler.h
│ │ ├── LKS_RequestHandler.m
│ │ └── RequestHandler
│ │ │ ├── LKS_AttrModificationPatchHandler.h
│ │ │ ├── LKS_AttrModificationPatchHandler.m
│ │ │ ├── LKS_CustomAttrModificationHandler.h
│ │ │ ├── LKS_CustomAttrModificationHandler.m
│ │ │ ├── LKS_HierarchyDetailsHandler.h
│ │ │ ├── LKS_HierarchyDetailsHandler.m
│ │ │ ├── LKS_InbuiltAttrModificationHandler.h
│ │ │ └── LKS_InbuiltAttrModificationHandler.m
│ ├── LookinServer.h
│ └── Others
│ │ ├── LKSConfigManager.h
│ │ ├── LKSConfigManager.m
│ │ ├── LKS_AttrGroupsMaker.h
│ │ ├── LKS_AttrGroupsMaker.m
│ │ ├── LKS_CustomAttrGroupsMaker.h
│ │ ├── LKS_CustomAttrGroupsMaker.m
│ │ ├── LKS_CustomAttrSetterManager.h
│ │ ├── LKS_CustomAttrSetterManager.m
│ │ ├── LKS_CustomDisplayItemsMaker.h
│ │ ├── LKS_CustomDisplayItemsMaker.m
│ │ ├── LKS_EventHandlerMaker.h
│ │ ├── LKS_EventHandlerMaker.m
│ │ ├── LKS_ExportManager.h
│ │ ├── LKS_ExportManager.m
│ │ ├── LKS_GestureTargetActionsSearcher.h
│ │ ├── LKS_GestureTargetActionsSearcher.m
│ │ ├── LKS_Helper.h
│ │ ├── LKS_Helper.m
│ │ ├── LKS_HierarchyDisplayItemsMaker.h
│ │ ├── LKS_HierarchyDisplayItemsMaker.m
│ │ ├── LKS_MultiplatformAdapter.h
│ │ ├── LKS_MultiplatformAdapter.m
│ │ ├── LKS_ObjectRegistry.h
│ │ ├── LKS_ObjectRegistry.m
│ │ ├── LKS_TraceManager.h
│ │ ├── LKS_TraceManager.m
│ │ └── LookinServerDefines.h
└── Shared
│ ├── Category
│ ├── CALayer+Lookin.h
│ ├── CALayer+Lookin.m
│ ├── Color+Lookin.h
│ ├── Color+Lookin.m
│ ├── Image+Lookin.h
│ ├── Image+Lookin.m
│ ├── NSArray+Lookin.h
│ ├── NSArray+Lookin.m
│ ├── NSObject+Lookin.h
│ ├── NSObject+Lookin.m
│ ├── NSSet+Lookin.h
│ ├── NSSet+Lookin.m
│ ├── NSString+Lookin.h
│ └── NSString+Lookin.m
│ ├── LookinAppInfo.h
│ ├── LookinAppInfo.m
│ ├── LookinAttrIdentifiers.h
│ ├── LookinAttrIdentifiers.m
│ ├── LookinAttrType.h
│ ├── LookinAttribute.h
│ ├── LookinAttribute.m
│ ├── LookinAttributeModification.h
│ ├── LookinAttributeModification.m
│ ├── LookinAttributesGroup.h
│ ├── LookinAttributesGroup.m
│ ├── LookinAttributesSection.h
│ ├── LookinAttributesSection.m
│ ├── LookinAutoLayoutConstraint.h
│ ├── LookinAutoLayoutConstraint.m
│ ├── LookinCodingValueType.h
│ ├── LookinConnectionAttachment.h
│ ├── LookinConnectionAttachment.m
│ ├── LookinConnectionResponseAttachment.h
│ ├── LookinConnectionResponseAttachment.m
│ ├── LookinCustomAttrModification.h
│ ├── LookinCustomAttrModification.m
│ ├── LookinCustomDisplayItemInfo.h
│ ├── LookinCustomDisplayItemInfo.m
│ ├── LookinDashboardBlueprint.h
│ ├── LookinDashboardBlueprint.m
│ ├── LookinDefines.h
│ ├── LookinDisplayItem.h
│ ├── LookinDisplayItem.m
│ ├── LookinDisplayItemDetail.h
│ ├── LookinDisplayItemDetail.m
│ ├── LookinEventHandler.h
│ ├── LookinEventHandler.m
│ ├── LookinHierarchyFile.h
│ ├── LookinHierarchyFile.m
│ ├── LookinHierarchyInfo.h
│ ├── LookinHierarchyInfo.m
│ ├── LookinObject.h
│ ├── LookinObject.m
│ ├── LookinStaticAsyncUpdateTask.h
│ ├── LookinStaticAsyncUpdateTask.m
│ ├── LookinTuple.h
│ ├── LookinTuple.m
│ ├── LookinWeakContainer.h
│ ├── LookinWeakContainer.m
│ └── Peertalk
│ ├── Lookin_PTChannel.h
│ ├── Lookin_PTChannel.m
│ ├── Lookin_PTPrivate.h
│ ├── Lookin_PTProtocol.h
│ ├── Lookin_PTProtocol.m
│ ├── Lookin_PTUSBHub.h
│ ├── Lookin_PTUSBHub.m
│ └── Peertalk.h
└── Swift
└── LKS_SwiftTraceManager.swift
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) [2023] [LI KAI]
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/LookinDemo/LookinCustomInfoDemo/LookinCustomInfoDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/LookinDemo/LookinCustomInfoDemo/LookinCustomInfoDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/LookinDemo/LookinCustomInfoDemo/LookinCustomInfoDemo.xcodeproj/xcshareddata/xcschemes/LookinCustomInfoDemo.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
42 |
44 |
50 |
51 |
52 |
53 |
59 |
61 |
67 |
68 |
69 |
70 |
72 |
73 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/LookinDemo/LookinCustomInfoDemo/LookinCustomInfoDemo.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/LookinDemo/LookinCustomInfoDemo/LookinCustomInfoDemo/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // LookinCustomInfoDemo
4 | //
5 | // Created by likai.123 on 2023/11/2.
6 | //
7 |
8 | import UIKit
9 |
10 | @main
11 | class AppDelegate: UIResponder, UIApplicationDelegate {
12 |
13 |
14 |
15 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
16 | // Override point for customization after application launch.
17 | return true
18 | }
19 |
20 | // MARK: UISceneSession Lifecycle
21 |
22 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
23 | // Called when a new scene session is being created.
24 | // Use this method to select a configuration to create the new scene with.
25 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
26 | }
27 |
28 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) {
29 | // Called when the user discards a scene session.
30 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
31 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
32 | }
33 |
34 |
35 | }
36 |
37 |
--------------------------------------------------------------------------------
/LookinDemo/LookinCustomInfoDemo/LookinCustomInfoDemo/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/LookinDemo/LookinCustomInfoDemo/LookinCustomInfoDemo/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "platform" : "ios",
6 | "size" : "1024x1024"
7 | }
8 | ],
9 | "info" : {
10 | "author" : "xcode",
11 | "version" : 1
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/LookinDemo/LookinCustomInfoDemo/LookinCustomInfoDemo/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/LookinDemo/LookinCustomInfoDemo/LookinCustomInfoDemo/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/LookinDemo/LookinCustomInfoDemo/LookinCustomInfoDemo/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/LookinDemo/LookinCustomInfoDemo/LookinCustomInfoDemo/Demo/ObjectiveC/CatView.h:
--------------------------------------------------------------------------------
1 | //
2 | // CatView.h
3 | // LookinDemoOC
4 | //
5 | // Created by likai.123 on 2023/10/16.
6 | //
7 |
8 | #import
9 |
10 | @interface CatView : UIView
11 |
12 | @end
13 |
--------------------------------------------------------------------------------
/LookinDemo/LookinCustomInfoDemo/LookinCustomInfoDemo/Demo/ObjectiveC/DogLayer.h:
--------------------------------------------------------------------------------
1 | //
2 | // DogLayer.h
3 | // LookinCustomInfoDemo
4 | //
5 | // Created by likai.123 on 2023/11/2.
6 | //
7 |
8 | #import
9 |
10 | NS_ASSUME_NONNULL_BEGIN
11 |
12 | @interface DogLayer : CALayer
13 |
14 | @end
15 |
16 | NS_ASSUME_NONNULL_END
17 |
--------------------------------------------------------------------------------
/LookinDemo/LookinCustomInfoDemo/LookinCustomInfoDemo/Demo/ObjectiveC/SomeViewModel.h:
--------------------------------------------------------------------------------
1 | //
2 | // SomeViewModel.h
3 | // LookinCustomInfoDemo
4 | //
5 | // Created by likai.123 on 2023/11/11.
6 | //
7 |
8 | #import
9 |
10 | NS_ASSUME_NONNULL_BEGIN
11 |
12 | @interface SomeViewModel : NSObject
13 |
14 | @property(nonatomic, strong) UIView *viewModelTargetView;
15 |
16 | @end
17 |
18 | NS_ASSUME_NONNULL_END
19 |
--------------------------------------------------------------------------------
/LookinDemo/LookinCustomInfoDemo/LookinCustomInfoDemo/Demo/ObjectiveC/SomeViewModel.m:
--------------------------------------------------------------------------------
1 | //
2 | // SomeViewModel.m
3 | // LookinCustomInfoDemo
4 | //
5 | // Created by likai.123 on 2023/11/11.
6 | //
7 |
8 | #import "SomeViewModel.h"
9 |
10 | @implementation SomeViewModel
11 |
12 | - (instancetype)init
13 | {
14 | self = [super init];
15 | if (self) {
16 | [[NSNotificationCenter defaultCenter] postNotificationName:@"Lookin_RelationSearch" object:self];
17 | }
18 | return self;
19 | }
20 |
21 | @end
22 |
--------------------------------------------------------------------------------
/LookinDemo/LookinCustomInfoDemo/LookinCustomInfoDemo/Demo/ObjectiveC/UIView+Custom.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIView+Custom.h
3 | // LookinCustomInfoDemo
4 | //
5 | // Created by likai.123 on 2023/11/2.
6 | //
7 |
8 | #import
9 |
10 | NS_ASSUME_NONNULL_BEGIN
11 |
12 | @interface UIView (Custom)
13 |
14 | @end
15 |
16 | NS_ASSUME_NONNULL_END
17 |
--------------------------------------------------------------------------------
/LookinDemo/LookinCustomInfoDemo/LookinCustomInfoDemo/Demo/ObjectiveC/UIView+Custom.m:
--------------------------------------------------------------------------------
1 | //
2 | // UIView+Custom.m
3 | // LookinCustomInfoDemo
4 | //
5 | // Created by likai.123 on 2023/11/2.
6 | //
7 |
8 | #import "UIView+Custom.h"
9 |
10 | @implementation UIView (Custom)
11 |
12 | /// 实现该方法以在 Lookin 中展示自定义属性
13 | /// 请留意该方法是否已经被父类、子类、分类实现了,如果是,为了避免冲突,你可以把该方法更名为 lookin_customDebugInfos_0(末尾的数字 0 可以被替换为 0 ~ 5 中的任意数字)
14 | /// 每次 Lookin 刷新时都会调用该方法,因此若该方法耗时较长,则会拖慢刷新速度
15 | ///
16 | /// Implement this method to display custom properties in Lookin.
17 | /// Please note if this method has already been implemented by the superclass, subclass, or category. If so, to avoid conflicts, you can rename this method to lookin_customDebugInfos_0 (the trailing number 0 can be replaced with any number from 0 to 5).
18 | /// This method is called every time Lookin refreshes, so if this method takes a long time to execute, it will slow down the refresh speed.
19 | ///
20 | /// https://bytedance.feishu.cn/docx/TRridRXeUoErMTxs94bcnGchnlb
21 | - (NSDictionary *)lookin_customDebugInfos_0 {
22 | NSDictionary *ret = @{
23 | @"properties": [self category_makeCustomProperties],
24 | };
25 | return ret;
26 | }
27 |
28 | - (NSArray *)category_makeCustomProperties {
29 | NSMutableArray *properties = [NSMutableArray array];
30 |
31 | [properties addObject:@{
32 | @"section": @"Appearance",
33 | @"title": @"Brightness",
34 | @"value": @8.8,
35 | @"valueType": @"number"
36 | }];
37 |
38 | return [properties copy];;
39 | }
40 |
41 | @end
42 |
--------------------------------------------------------------------------------
/LookinDemo/LookinCustomInfoDemo/LookinCustomInfoDemo/Demo/Swift/CALayer+Custom.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CALayer+Custom.swift
3 | // LookinCustomInfoDemo
4 | //
5 | // Created by likai.123 on 2023/11/2.
6 | //
7 |
8 | import UIKit
9 |
10 | extension CALayer {
11 | /// 实现该方法以在 Lookin 中展示自定义属性
12 | /// 请留意该方法是否已经被父类、子类、分类实现了,如果是,为了避免冲突,你可以把该方法更名为 lookin_customDebugInfos_0(末尾的数字 0 可以被替换为 0 ~ 5 中的任意数字)
13 | /// 每次 Lookin 刷新时都会调用该方法,因此若该方法耗时较长,则会拖慢刷新速度
14 | ///
15 | /// Implement this method to display custom properties in Lookin.
16 | /// Please note if this method has already been implemented by the superclass, subclass, or category. If so, to avoid conflicts, you can rename this method to lookin_customDebugInfos_0 (the trailing number 0 can be replaced with any number from 0 to 5).
17 | /// This method is called every time Lookin refreshes, so if this method takes a long time to execute, it will slow down the refresh speed.
18 | ///
19 | /// https://bytedance.feishu.cn/docx/TRridRXeUoErMTxs94bcnGchnlb
20 | @objc func lookin_customDebugInfos_1() -> [String:Any]? {
21 | let ret: [String:Any] = [
22 | "properties": self.cusotm_makeCustomProperties()
23 | ]
24 | return ret
25 | }
26 |
27 | private func cusotm_makeCustomProperties() -> [Any] {
28 | let stringProperty: [String:Any] = [
29 | "section": "Life Style",
30 | "title": "Hobby",
31 | "value": "Bike",
32 | "valueType": "string"
33 | ]
34 |
35 | return [stringProperty]
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/LookinDemo/LookinCustomInfoDemo/LookinCustomInfoDemo/Demo/Swift/GoodViewModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // GoodViewModel.swift
3 | // LookinCustomInfoDemo
4 | //
5 | // Created by likai.123 on 2023/11/11.
6 | //
7 |
8 | import Foundation
9 |
10 | class GoodViewModel {
11 | var viewModelTargetView: UIView?
12 |
13 | init() {
14 | NotificationCenter.default.post(name: .init("Lookin_RelationSearch"), object: self)
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/LookinDemo/LookinCustomInfoDemo/LookinCustomInfoDemo/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | UIApplicationSceneManifest
6 |
7 | UIApplicationSupportsMultipleScenes
8 |
9 | UISceneConfigurations
10 |
11 | UIWindowSceneSessionRoleApplication
12 |
13 |
14 | UISceneConfigurationName
15 | Default Configuration
16 | UISceneDelegateClassName
17 | $(PRODUCT_MODULE_NAME).SceneDelegate
18 | UISceneStoryboardFile
19 | Main
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/LookinDemo/LookinCustomInfoDemo/LookinCustomInfoDemo/LookinCustomInfoDemo-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | //
2 | // Use this file to import your target's public headers that you would like to expose to Swift.
3 | //
4 |
5 | #import "CatView.h"
6 | #import "DogLayer.h"
7 | #import "SomeViewModel.h"
8 |
--------------------------------------------------------------------------------
/LookinDemo/LookinCustomInfoDemo/LookinCustomInfoDemo/SceneDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SceneDelegate.swift
3 | // LookinCustomInfoDemo
4 | //
5 | // Created by likai.123 on 2023/11/2.
6 | //
7 |
8 | import UIKit
9 |
10 | class SceneDelegate: UIResponder, UIWindowSceneDelegate {
11 |
12 | var window: UIWindow?
13 |
14 |
15 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
16 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
17 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
18 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
19 | guard let _ = (scene as? UIWindowScene) else { return }
20 | }
21 |
22 | func sceneDidDisconnect(_ scene: UIScene) {
23 | // Called as the scene is being released by the system.
24 | // This occurs shortly after the scene enters the background, or when its session is discarded.
25 | // Release any resources associated with this scene that can be re-created the next time the scene connects.
26 | // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
27 | }
28 |
29 | func sceneDidBecomeActive(_ scene: UIScene) {
30 | // Called when the scene has moved from an inactive state to an active state.
31 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
32 | }
33 |
34 | func sceneWillResignActive(_ scene: UIScene) {
35 | // Called when the scene will move from an active state to an inactive state.
36 | // This may occur due to temporary interruptions (ex. an incoming phone call).
37 | }
38 |
39 | func sceneWillEnterForeground(_ scene: UIScene) {
40 | // Called as the scene transitions from the background to the foreground.
41 | // Use this method to undo the changes made on entering the background.
42 | }
43 |
44 | func sceneDidEnterBackground(_ scene: UIScene) {
45 | // Called as the scene transitions from the foreground to the background.
46 | // Use this method to save data, release shared resources, and store enough scene-specific state information
47 | // to restore the scene back to its current state.
48 | }
49 |
50 |
51 | }
52 |
53 |
--------------------------------------------------------------------------------
/LookinDemo/LookinCustomInfoDemo/Podfile:
--------------------------------------------------------------------------------
1 | use_frameworks!
2 |
3 | target 'LookinCustomInfoDemo' do
4 | pod 'LookinServer', :path=>'../../', :subspecs => ['Swift'], :configurations => ['Debug']
5 | end
6 |
--------------------------------------------------------------------------------
/LookinDemo/LookinCustomInfoDemo/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - LookinServer/Core (1.2.7)
3 | - LookinServer/Swift (1.2.7):
4 | - LookinServer/Core
5 |
6 | DEPENDENCIES:
7 | - LookinServer/Swift (from `../../`)
8 |
9 | EXTERNAL SOURCES:
10 | LookinServer:
11 | :path: "../../"
12 |
13 | SPEC CHECKSUMS:
14 | LookinServer: fccc36fcab6ea15ae70692872877add9ce005f56
15 |
16 | PODFILE CHECKSUM: 46caada19d34f471f9e44165d96af39e799fd091
17 |
18 | COCOAPODS: 1.13.0
19 |
--------------------------------------------------------------------------------
/LookinDemo/OC_Pod/LookinDemoOC.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/LookinDemo/OC_Pod/LookinDemoOC.xcodeproj/xcshareddata/xcschemes/LookinDemoOC.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
45 |
51 |
52 |
53 |
54 |
60 |
62 |
68 |
69 |
70 |
71 |
73 |
74 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/LookinDemo/OC_Pod/LookinDemoOC.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/LookinDemo/OC_Pod/LookinDemoOC.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/LookinDemo/OC_Pod/LookinDemoOC/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // LookinDemoOC
4 | //
5 | // Created by likai.123 on 2022/10/10.
6 | //
7 |
8 | #import
9 |
10 | @interface AppDelegate : UIResponder
11 |
12 |
13 | @end
14 |
15 |
--------------------------------------------------------------------------------
/LookinDemo/OC_Pod/LookinDemoOC/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // LookinDemoOC
4 | //
5 | // Created by likai.123 on 2022/10/10.
6 | //
7 |
8 | #import "AppDelegate.h"
9 |
10 | @interface AppDelegate ()
11 |
12 | @end
13 |
14 | @implementation AppDelegate
15 |
16 |
17 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
18 | // Override point for customization after application launch.
19 | return YES;
20 | }
21 |
22 |
23 | #pragma mark - UISceneSession lifecycle
24 |
25 |
26 | - (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options {
27 | // Called when a new scene session is being created.
28 | // Use this method to select a configuration to create the new scene with.
29 | return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role];
30 | }
31 |
32 |
33 | - (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet *)sceneSessions {
34 | // Called when the user discards a scene session.
35 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
36 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
37 | }
38 |
39 |
40 | @end
41 |
--------------------------------------------------------------------------------
/LookinDemo/OC_Pod/LookinDemoOC/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/LookinDemo/OC_Pod/LookinDemoOC/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "platform" : "ios",
6 | "size" : "1024x1024"
7 | }
8 | ],
9 | "info" : {
10 | "author" : "xcode",
11 | "version" : 1
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/LookinDemo/OC_Pod/LookinDemoOC/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/LookinDemo/OC_Pod/LookinDemoOC/Assets.xcassets/Logo_128.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "filename" : "Logo_128.png",
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/LookinDemo/OC_Pod/LookinDemoOC/Assets.xcassets/Logo_128.imageset/Logo_128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QMUI/LookinServer/ae396132ce6494477457cf450116dc760518d8ad/LookinDemo/OC_Pod/LookinDemoOC/Assets.xcassets/Logo_128.imageset/Logo_128.png
--------------------------------------------------------------------------------
/LookinDemo/OC_Pod/LookinDemoOC/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/LookinDemo/OC_Pod/LookinDemoOC/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/LookinDemo/OC_Pod/LookinDemoOC/CatView.h:
--------------------------------------------------------------------------------
1 | //
2 | // CatView.h
3 | // LookinDemoOC
4 | //
5 | // Created by likai.123 on 2023/10/16.
6 | //
7 |
8 | #import
9 |
10 | NS_ASSUME_NONNULL_BEGIN
11 |
12 | @interface CatView : UIView
13 |
14 | - (NSDictionary *)lookin_customDebugInfos;
15 |
16 | @end
17 |
18 | NS_ASSUME_NONNULL_END
19 |
--------------------------------------------------------------------------------
/LookinDemo/OC_Pod/LookinDemoOC/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | UIApplicationSceneManifest
6 |
7 | UIApplicationSupportsMultipleScenes
8 |
9 | UISceneConfigurations
10 |
11 | UIWindowSceneSessionRoleApplication
12 |
13 |
14 | UISceneConfigurationName
15 | Default Configuration
16 | UISceneDelegateClassName
17 | SceneDelegate
18 | UISceneStoryboardFile
19 | Main
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/LookinDemo/OC_Pod/LookinDemoOC/SceneDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // SceneDelegate.h
3 | // LookinDemoOC
4 | //
5 | // Created by likai.123 on 2022/10/10.
6 | //
7 |
8 | #import
9 |
10 | @interface SceneDelegate : UIResponder
11 |
12 | @property (strong, nonatomic) UIWindow * window;
13 |
14 | @end
15 |
16 |
--------------------------------------------------------------------------------
/LookinDemo/OC_Pod/LookinDemoOC/SceneDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // SceneDelegate.m
3 | // LookinDemoOC
4 | //
5 | // Created by likai.123 on 2022/10/10.
6 | //
7 |
8 | #import "SceneDelegate.h"
9 |
10 | @interface SceneDelegate ()
11 |
12 | @end
13 |
14 | @implementation SceneDelegate
15 |
16 |
17 | - (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
18 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
19 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
20 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
21 | }
22 |
23 |
24 | - (void)sceneDidDisconnect:(UIScene *)scene {
25 | // Called as the scene is being released by the system.
26 | // This occurs shortly after the scene enters the background, or when its session is discarded.
27 | // Release any resources associated with this scene that can be re-created the next time the scene connects.
28 | // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
29 | }
30 |
31 |
32 | - (void)sceneDidBecomeActive:(UIScene *)scene {
33 | // Called when the scene has moved from an inactive state to an active state.
34 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
35 | }
36 |
37 |
38 | - (void)sceneWillResignActive:(UIScene *)scene {
39 | // Called when the scene will move from an active state to an inactive state.
40 | // This may occur due to temporary interruptions (ex. an incoming phone call).
41 | }
42 |
43 |
44 | - (void)sceneWillEnterForeground:(UIScene *)scene {
45 | // Called as the scene transitions from the background to the foreground.
46 | // Use this method to undo the changes made on entering the background.
47 | }
48 |
49 |
50 | - (void)sceneDidEnterBackground:(UIScene *)scene {
51 | // Called as the scene transitions from the foreground to the background.
52 | // Use this method to save data, release shared resources, and store enough scene-specific state information
53 | // to restore the scene back to its current state.
54 | }
55 |
56 |
57 | @end
58 |
--------------------------------------------------------------------------------
/LookinDemo/OC_Pod/LookinDemoOC/ViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.h
3 | // LookinDemoOC
4 | //
5 | // Created by likai.123 on 2022/10/10.
6 | //
7 |
8 | #import
9 |
10 | @interface ViewController : UIViewController
11 |
12 |
13 | @end
14 |
15 |
--------------------------------------------------------------------------------
/LookinDemo/OC_Pod/LookinDemoOC/ViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.m
3 | // LookinDemoOC
4 | //
5 | // Created by likai.123 on 2022/10/10.
6 | //
7 |
8 | #import "ViewController.h"
9 | #import "CatView.h"
10 |
11 | @interface ViewController ()
12 |
13 | @end
14 |
15 | @implementation ViewController
16 |
17 | - (void)viewDidLoad {
18 | [super viewDidLoad];
19 | // 创建 UIStackView
20 | UIStackView *stackView = [[UIStackView alloc] init];
21 | stackView.axis = UILayoutConstraintAxisVertical; // 设置布局方向为垂直
22 | stackView.alignment = UIStackViewAlignmentFill; // 设置对齐方式为居中对齐
23 | stackView.distribution = UIStackViewDistributionFillEqually; // 设置子视图的分布方式为均匀分布
24 | stackView.spacing = 10.0; // 设置子视图之间的间距为10
25 |
26 | // 创建子视图
27 | UIView *view1 = [[UIView alloc] init];
28 | view1.backgroundColor = [UIColor redColor];
29 | UIView *view2 = [[UIView alloc] init];
30 | view2.backgroundColor = [UIColor greenColor];
31 | UIView *view3 = [[UIView alloc] init];
32 | view3.backgroundColor = [UIColor blueColor];
33 |
34 | // 将子视图添加到 UIStackView 中
35 | [stackView addArrangedSubview:view1];
36 | [stackView addArrangedSubview:view2];
37 | [stackView addArrangedSubview:view3];
38 |
39 | // 将 UIStackView 添加到父视图中
40 | [self.view addSubview:stackView];
41 |
42 | stackView.frame = self.view.bounds;
43 | }
44 |
45 | @end
46 |
--------------------------------------------------------------------------------
/LookinDemo/OC_Pod/LookinDemoOC/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // LookinDemoOC
4 | //
5 | // Created by likai.123 on 2022/10/10.
6 | //
7 |
8 | #import
9 | #import "AppDelegate.h"
10 |
11 | int main(int argc, char * argv[]) {
12 | NSString * appDelegateClassName;
13 | @autoreleasepool {
14 | // Setup code that might create autoreleased objects goes here.
15 | appDelegateClassName = NSStringFromClass([AppDelegate class]);
16 | }
17 | return UIApplicationMain(argc, argv, nil, appDelegateClassName);
18 | }
19 |
--------------------------------------------------------------------------------
/LookinDemo/OC_Pod/Podfile:
--------------------------------------------------------------------------------
1 | use_frameworks!
2 |
3 | target 'LookinDemoOC' do
4 | pod 'LookinServer', :path=>'../../'
5 | end
6 |
--------------------------------------------------------------------------------
/LookinDemo/OC_Pod/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - LookinServer (1.2.6):
3 | - LookinServer/Core (= 1.2.6)
4 | - LookinServer/Core (1.2.6)
5 |
6 | DEPENDENCIES:
7 | - LookinServer (from `../../`)
8 |
9 | EXTERNAL SOURCES:
10 | LookinServer:
11 | :path: "../../"
12 |
13 | SPEC CHECKSUMS:
14 | LookinServer: de929b55f8fa2e241c18c39af3f900eaa9166389
15 |
16 | PODFILE CHECKSUM: c1b5f203c9e81bcbf3888ba95a03c31e2435a4f7
17 |
18 | COCOAPODS: 1.13.0
19 |
--------------------------------------------------------------------------------
/LookinDemo/Swift_SPM_Debug/LookinDemoSwift.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/LookinDemo/Swift_SPM_Debug/LookinDemoSwift.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/LookinDemo/Swift_SPM_Debug/LookinDemoSwift.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved:
--------------------------------------------------------------------------------
1 | {
2 | "pins" : [
3 | {
4 | "identity" : "lookinserver",
5 | "kind" : "remoteSourceControl",
6 | "location" : "https://github.com/QMUI/LookinServer",
7 | "state" : {
8 | "branch" : "develop",
9 | "revision" : "6637da86966513ceaf584e48835518d36f5aa977"
10 | }
11 | }
12 | ],
13 | "version" : 2
14 | }
15 |
--------------------------------------------------------------------------------
/LookinDemo/Swift_SPM_Debug/LookinDemoSwift.xcodeproj/xcshareddata/xcschemes/LookinDemoSwift.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
45 |
51 |
52 |
53 |
54 |
60 |
62 |
68 |
69 |
70 |
71 |
73 |
74 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/LookinDemo/Swift_SPM_Debug/LookinDemoSwift/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // LookinDemoSwift
4 | //
5 | // Created by likai.123 on 2022/10/10.
6 | //
7 |
8 | import UIKit
9 |
10 | @main
11 | class AppDelegate: UIResponder, UIApplicationDelegate {
12 |
13 |
14 |
15 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
16 | // Override point for customization after application launch.
17 | return true
18 | }
19 |
20 | // MARK: UISceneSession Lifecycle
21 |
22 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
23 | // Called when a new scene session is being created.
24 | // Use this method to select a configuration to create the new scene with.
25 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
26 | }
27 |
28 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) {
29 | // Called when the user discards a scene session.
30 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
31 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
32 | }
33 |
34 |
35 | }
36 |
37 |
--------------------------------------------------------------------------------
/LookinDemo/Swift_SPM_Debug/LookinDemoSwift/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/LookinDemo/Swift_SPM_Debug/LookinDemoSwift/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "platform" : "ios",
6 | "size" : "1024x1024"
7 | }
8 | ],
9 | "info" : {
10 | "author" : "xcode",
11 | "version" : 1
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/LookinDemo/Swift_SPM_Debug/LookinDemoSwift/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/LookinDemo/Swift_SPM_Debug/LookinDemoSwift/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/LookinDemo/Swift_SPM_Debug/LookinDemoSwift/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/LookinDemo/Swift_SPM_Debug/LookinDemoSwift/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | UIApplicationSceneManifest
6 |
7 | UIApplicationSupportsMultipleScenes
8 |
9 | UISceneConfigurations
10 |
11 | UIWindowSceneSessionRoleApplication
12 |
13 |
14 | UISceneConfigurationName
15 | Default Configuration
16 | UISceneDelegateClassName
17 | $(PRODUCT_MODULE_NAME).SceneDelegate
18 | UISceneStoryboardFile
19 | Main
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/LookinDemo/Swift_SPM_Debug/LookinDemoSwift/SceneDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SceneDelegate.swift
3 | // LookinDemoSwift
4 | //
5 | // Created by likai.123 on 2022/10/10.
6 | //
7 |
8 | import UIKit
9 |
10 | class SceneDelegate: UIResponder, UIWindowSceneDelegate {
11 |
12 | var window: UIWindow?
13 |
14 |
15 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
16 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
17 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
18 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
19 | guard let _ = (scene as? UIWindowScene) else { return }
20 | }
21 |
22 | func sceneDidDisconnect(_ scene: UIScene) {
23 | // Called as the scene is being released by the system.
24 | // This occurs shortly after the scene enters the background, or when its session is discarded.
25 | // Release any resources associated with this scene that can be re-created the next time the scene connects.
26 | // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
27 | }
28 |
29 | func sceneDidBecomeActive(_ scene: UIScene) {
30 | // Called when the scene has moved from an inactive state to an active state.
31 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
32 | }
33 |
34 | func sceneWillResignActive(_ scene: UIScene) {
35 | // Called when the scene will move from an active state to an inactive state.
36 | // This may occur due to temporary interruptions (ex. an incoming phone call).
37 | }
38 |
39 | func sceneWillEnterForeground(_ scene: UIScene) {
40 | // Called as the scene transitions from the background to the foreground.
41 | // Use this method to undo the changes made on entering the background.
42 | }
43 |
44 | func sceneDidEnterBackground(_ scene: UIScene) {
45 | // Called as the scene transitions from the foreground to the background.
46 | // Use this method to save data, release shared resources, and store enough scene-specific state information
47 | // to restore the scene back to its current state.
48 | }
49 |
50 |
51 | }
52 |
53 |
--------------------------------------------------------------------------------
/LookinDemo/Swift_SPM_Debug/LookinDemoSwift/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // LookinDemoSwift
4 | //
5 | // Created by likai.123 on 2022/10/10.
6 | //
7 |
8 | import UIKit
9 |
10 | extension NSObject {
11 | @objc func lookin_shouldCaptureImageOfView(_ view: UIView) -> Bool {
12 | if view.tag == 1234 {
13 | return true
14 | } else {
15 | return true
16 | }
17 | }
18 |
19 | @objc func lookin_collapsedClassList() -> [String] {
20 | return ["UIDropShadowView"]
21 | }
22 |
23 | @objc func lookin_colorAlias() -> [String:UIColor] {
24 | return ["MyWhite": UIColor.init(red: 1, green: 1, blue: 1, alpha: 1)]
25 | }
26 | }
27 |
28 | class MyView: UIView {
29 | @objc func lookin_shouldCaptureImage() -> Bool {
30 | return false
31 | }
32 | }
33 |
34 | class ViewController: UIViewController {
35 | private let myButton = MyView()
36 |
37 | private let textView = UITextView()
38 |
39 | override func viewDidLoad() {
40 | super.viewDidLoad()
41 | // Do any additional setup after loading the view.
42 | self.view.layer.borderColor = UIColor.red.cgColor
43 |
44 | textView.frame = CGRect(x: 20, y: 100, width: 200, height: 200)
45 | view.addSubview(textView)
46 |
47 | myButton.tag = 1234
48 | myButton.frame = CGRect(x: 20, y: 20, width: 50, height: 50)
49 | view.addSubview(myButton)
50 | }
51 |
52 |
53 | }
54 |
55 |
--------------------------------------------------------------------------------
/LookinDemo/Swift_SPM_Release/LookinDemoSwift.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/LookinDemo/Swift_SPM_Release/LookinDemoSwift.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/LookinDemo/Swift_SPM_Release/LookinDemoSwift.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved:
--------------------------------------------------------------------------------
1 | {
2 | "pins" : [
3 | {
4 | "identity" : "lookinserver",
5 | "kind" : "remoteSourceControl",
6 | "location" : "https://github.com/QMUI/LookinServer",
7 | "state" : {
8 | "branch" : "develop",
9 | "revision" : "58067cf9cd30662f7082681d8f5083524a4262b1"
10 | }
11 | }
12 | ],
13 | "version" : 2
14 | }
15 |
--------------------------------------------------------------------------------
/LookinDemo/Swift_SPM_Release/LookinDemoSwift.xcodeproj/xcshareddata/xcschemes/LookinDemoSwift.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
45 |
51 |
52 |
53 |
54 |
60 |
62 |
68 |
69 |
70 |
71 |
73 |
74 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/LookinDemo/Swift_SPM_Release/LookinDemoSwift/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // LookinDemoSwift
4 | //
5 | // Created by likai.123 on 2022/10/10.
6 | //
7 |
8 | import UIKit
9 |
10 | @main
11 | class AppDelegate: UIResponder, UIApplicationDelegate {
12 |
13 |
14 |
15 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
16 | // Override point for customization after application launch.
17 | return true
18 | }
19 |
20 | // MARK: UISceneSession Lifecycle
21 |
22 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
23 | // Called when a new scene session is being created.
24 | // Use this method to select a configuration to create the new scene with.
25 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
26 | }
27 |
28 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) {
29 | // Called when the user discards a scene session.
30 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
31 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
32 | }
33 |
34 |
35 | }
36 |
37 |
--------------------------------------------------------------------------------
/LookinDemo/Swift_SPM_Release/LookinDemoSwift/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/LookinDemo/Swift_SPM_Release/LookinDemoSwift/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "platform" : "ios",
6 | "size" : "1024x1024"
7 | }
8 | ],
9 | "info" : {
10 | "author" : "xcode",
11 | "version" : 1
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/LookinDemo/Swift_SPM_Release/LookinDemoSwift/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/LookinDemo/Swift_SPM_Release/LookinDemoSwift/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/LookinDemo/Swift_SPM_Release/LookinDemoSwift/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/LookinDemo/Swift_SPM_Release/LookinDemoSwift/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | UIApplicationSceneManifest
6 |
7 | UIApplicationSupportsMultipleScenes
8 |
9 | UISceneConfigurations
10 |
11 | UIWindowSceneSessionRoleApplication
12 |
13 |
14 | UISceneConfigurationName
15 | Default Configuration
16 | UISceneDelegateClassName
17 | $(PRODUCT_MODULE_NAME).SceneDelegate
18 | UISceneStoryboardFile
19 | Main
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/LookinDemo/Swift_SPM_Release/LookinDemoSwift/SceneDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SceneDelegate.swift
3 | // LookinDemoSwift
4 | //
5 | // Created by likai.123 on 2022/10/10.
6 | //
7 |
8 | import UIKit
9 |
10 | class SceneDelegate: UIResponder, UIWindowSceneDelegate {
11 |
12 | var window: UIWindow?
13 |
14 |
15 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
16 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
17 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
18 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
19 | guard let _ = (scene as? UIWindowScene) else { return }
20 | }
21 |
22 | func sceneDidDisconnect(_ scene: UIScene) {
23 | // Called as the scene is being released by the system.
24 | // This occurs shortly after the scene enters the background, or when its session is discarded.
25 | // Release any resources associated with this scene that can be re-created the next time the scene connects.
26 | // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
27 | }
28 |
29 | func sceneDidBecomeActive(_ scene: UIScene) {
30 | // Called when the scene has moved from an inactive state to an active state.
31 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
32 | }
33 |
34 | func sceneWillResignActive(_ scene: UIScene) {
35 | // Called when the scene will move from an active state to an inactive state.
36 | // This may occur due to temporary interruptions (ex. an incoming phone call).
37 | }
38 |
39 | func sceneWillEnterForeground(_ scene: UIScene) {
40 | // Called as the scene transitions from the background to the foreground.
41 | // Use this method to undo the changes made on entering the background.
42 | }
43 |
44 | func sceneDidEnterBackground(_ scene: UIScene) {
45 | // Called as the scene transitions from the foreground to the background.
46 | // Use this method to save data, release shared resources, and store enough scene-specific state information
47 | // to restore the scene back to its current state.
48 | }
49 |
50 |
51 | }
52 |
53 |
--------------------------------------------------------------------------------
/LookinDemo/Swift_SPM_Release/LookinDemoSwift/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // LookinDemoSwift
4 | //
5 | // Created by likai.123 on 2022/10/10.
6 | //
7 |
8 | import UIKit
9 |
10 | extension NSObject {
11 | @objc func lookin_shouldCaptureImageOfView(_ view: UIView) -> Bool {
12 | if view.tag == 1234 {
13 | return true
14 | } else {
15 | return true
16 | }
17 | }
18 |
19 | @objc func lookin_collapsedClassList() -> [String] {
20 | return ["UIDropShadowView"]
21 | }
22 |
23 | @objc func lookin_colorAlias() -> [String:UIColor] {
24 | return ["MyWhite": UIColor.init(red: 1, green: 1, blue: 1, alpha: 1)]
25 | }
26 | }
27 |
28 | class MyView: UIView {
29 | @objc func lookin_shouldCaptureImage() -> Bool {
30 | return false
31 | }
32 | }
33 |
34 | class ViewController: UIViewController {
35 | private let myButton = MyView()
36 |
37 | private let textView = UITextView()
38 |
39 | override func viewDidLoad() {
40 | super.viewDidLoad()
41 | // Do any additional setup after loading the view.
42 | self.view.layer.borderColor = UIColor.red.cgColor
43 |
44 | textView.frame = CGRect(x: 20, y: 100, width: 200, height: 200)
45 | view.addSubview(textView)
46 |
47 | myButton.tag = 1234
48 | myButton.frame = CGRect(x: 20, y: 20, width: 50, height: 50)
49 | view.addSubview(myButton)
50 | }
51 |
52 |
53 | }
54 |
55 |
--------------------------------------------------------------------------------
/LookinDemo/TestVisionOS/Podfile:
--------------------------------------------------------------------------------
1 | use_frameworks!
2 |
3 | target 'TestVisionOS' do
4 | pod 'LookinServer', :path=>'../../', :subspecs => ['Swift'], :configurations => ['Debug']
5 | end
6 |
--------------------------------------------------------------------------------
/LookinDemo/TestVisionOS/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - LookinServer/Core (1.2.7)
3 | - LookinServer/Swift (1.2.7):
4 | - LookinServer/Core
5 |
6 | DEPENDENCIES:
7 | - LookinServer/Swift (from `../../`)
8 |
9 | EXTERNAL SOURCES:
10 | LookinServer:
11 | :path: "../../"
12 |
13 | SPEC CHECKSUMS:
14 | LookinServer: fccc36fcab6ea15ae70692872877add9ce005f56
15 |
16 | PODFILE CHECKSUM: 1dcff374267c2c2621d26b1dcf8fa7af55b2055b
17 |
18 | COCOAPODS: 1.13.0
19 |
--------------------------------------------------------------------------------
/LookinDemo/TestVisionOS/TestVisionOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/LookinDemo/TestVisionOS/TestVisionOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/LookinDemo/TestVisionOS/TestVisionOS.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/LookinDemo/TestVisionOS/TestVisionOS.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/LookinDemo/TestVisionOS/TestVisionOS/Assets.xcassets/AppIcon.solidimagestack/Back.solidimagestacklayer/Content.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "vision",
5 | "scale" : "2x"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/LookinDemo/TestVisionOS/TestVisionOS/Assets.xcassets/AppIcon.solidimagestack/Back.solidimagestacklayer/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/LookinDemo/TestVisionOS/TestVisionOS/Assets.xcassets/AppIcon.solidimagestack/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | },
6 | "layers" : [
7 | {
8 | "filename" : "Front.solidimagestacklayer"
9 | },
10 | {
11 | "filename" : "Middle.solidimagestacklayer"
12 | },
13 | {
14 | "filename" : "Back.solidimagestacklayer"
15 | }
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/LookinDemo/TestVisionOS/TestVisionOS/Assets.xcassets/AppIcon.solidimagestack/Front.solidimagestacklayer/Content.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "vision",
5 | "scale" : "2x"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/LookinDemo/TestVisionOS/TestVisionOS/Assets.xcassets/AppIcon.solidimagestack/Front.solidimagestacklayer/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/LookinDemo/TestVisionOS/TestVisionOS/Assets.xcassets/AppIcon.solidimagestack/Middle.solidimagestacklayer/Content.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "vision",
5 | "scale" : "2x"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/LookinDemo/TestVisionOS/TestVisionOS/Assets.xcassets/AppIcon.solidimagestack/Middle.solidimagestacklayer/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/LookinDemo/TestVisionOS/TestVisionOS/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/LookinDemo/TestVisionOS/TestVisionOS/ContentView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ContentView.swift
3 | // TestVisionOS
4 | //
5 | // Created by likai.123 on 2024/4/6.
6 | //
7 |
8 | import SwiftUI
9 | import RealityKit
10 | import RealityKitContent
11 |
12 | struct ContentView: View {
13 | var body: some View {
14 | VStack {
15 | Model3D(named: "Scene", bundle: realityKitContentBundle)
16 | .padding(.bottom, 50)
17 |
18 | Text("Hello, world!")
19 | }
20 | .padding()
21 | }
22 | }
23 |
24 | #Preview(windowStyle: .automatic) {
25 | ContentView()
26 | }
27 |
--------------------------------------------------------------------------------
/LookinDemo/TestVisionOS/TestVisionOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | UIApplicationSceneManifest
6 |
7 | UIApplicationPreferredDefaultSceneSessionRole
8 | UIWindowSceneSessionRoleApplication
9 | UIApplicationSupportsMultipleScenes
10 |
11 | UISceneConfigurations
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/LookinDemo/TestVisionOS/TestVisionOS/Preview Content/Preview Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/LookinDemo/TestVisionOS/TestVisionOS/TestVisionOSApp.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TestVisionOSApp.swift
3 | // TestVisionOS
4 | //
5 | // Created by likai.123 on 2024/4/6.
6 | //
7 |
8 | import SwiftUI
9 |
10 | @main
11 | struct TestVisionOSApp: App {
12 | var body: some Scene {
13 | WindowGroup {
14 | ContentView()
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/LookinServer.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |spec|
2 | spec.name = "LookinServer"
3 | spec.version = "1.2.8"
4 | spec.summary = "The iOS framework of Lookin."
5 | spec.description = "Embed this framework into your iOS project to enable Lookin mac app."
6 | spec.homepage = "https://lookin.work"
7 | spec.license = "GPL-3.0"
8 | spec.author = { "Li Kai" => "lookin@lookin.work" }
9 | spec.ios.deployment_target = "9.0"
10 | spec.tvos.deployment_target = '9.0'
11 | spec.visionos.deployment_target = "1.0"
12 | spec.default_subspecs = 'Core'
13 | spec.source = { :git => "https://github.com/QMUI/LookinServer.git", :tag => "1.2.8"}
14 | spec.framework = "UIKit"
15 | spec.requires_arc = true
16 |
17 | spec.subspec 'Core' do |ss|
18 | ss.source_files = ['Src/Main/**/*', 'Src/Base/**/*']
19 | ss.pod_target_xcconfig = {
20 | 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) SHOULD_COMPILE_LOOKIN_SERVER=1',
21 | 'SWIFT_ACTIVE_COMPILATION_CONDITIONS' => '$(inherited) SHOULD_COMPILE_LOOKIN_SERVER'
22 | }
23 | end
24 |
25 | spec.subspec 'Swift' do |ss|
26 | ss.dependency 'LookinServer/Core'
27 | ss.source_files = 'Src/Swift/**/*'
28 | ss.pod_target_xcconfig = {
29 | 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) LOOKIN_SERVER_SWIFT_ENABLED=1',
30 | 'SWIFT_ACTIVE_COMPILATION_CONDITIONS' => '$(inherited) LOOKIN_SERVER_SWIFT_ENABLED'
31 | }
32 | end
33 |
34 | spec.subspec 'NoHook' do |ss|
35 | ss.dependency 'LookinServer/Core'
36 | ss.pod_target_xcconfig = {
37 | 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) LOOKIN_SERVER_DISABLE_HOOK=1',
38 | }
39 | end
40 |
41 | # CocoaPods 不支持多个 subspecs 和 configurations 并列
42 | # "pod 'LookinServer', :subspecs => ['Swift', 'NoHook'], :configurations => ['Debug']" is not supported by CocoaPods
43 | # https://github.com/QMUI/LookinServer/issues/134
44 | spec.subspec 'SwiftAndNoHook' do |ss|
45 | ss.dependency 'LookinServer/Core'
46 | ss.source_files = 'Src/Swift/**/*'
47 | ss.pod_target_xcconfig = {
48 | 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) LOOKIN_SERVER_SWIFT_ENABLED=1 LOOKIN_SERVER_DISABLE_HOOK=1',
49 | 'SWIFT_ACTIVE_COMPILATION_CONDITIONS' => '$(inherited) LOOKIN_SERVER_SWIFT_ENABLED'
50 | }
51 | end
52 |
53 | end
54 |
--------------------------------------------------------------------------------
/LookinShared.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |spec|
2 | spec.name = "LookinShared"
3 | spec.version = "1.2.8"
4 | spec.summary = "The shared files between client and server side of Lookin."
5 | spec.description = "Embed this framework into your iOS project to enable Lookin mac app."
6 | spec.homepage = "https://lookin.work"
7 | spec.license = "GPL-3.0"
8 | spec.author = { "Li Kai" => "lookin@lookin.work" }
9 | spec.ios.deployment_target = "9.0"
10 | spec.tvos.deployment_target = '9.0'
11 | spec.macos.deployment_target = "10.14"
12 | spec.visionos.deployment_target = "1.0"
13 | spec.source = { :git => "https://github.com/QMUI/LookinServer.git", :tag => "1.2.8"}
14 | #spec.framework = "UIKit"
15 | spec.requires_arc = true
16 | spec.source_files = [
17 | 'Src/Main/Shared/**/*',
18 | 'Src/Base/**/*'
19 | ]
20 | spec.pod_target_xcconfig = {
21 | 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) SHOULD_COMPILE_LOOKIN_SERVER=1'
22 | }
23 | end
24 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.3
2 | // The swift-tools-version declares the minimum version of Swift required to build this package.
3 |
4 | import PackageDescription
5 |
6 | let package = Package(
7 | name: "LookinServer",
8 | platforms: [
9 | .iOS(.v9),.tvOS(.v9)
10 | ],
11 | products: [
12 | // Products define the executables and libraries a package produces, and make them visible to other packages.
13 | .library(
14 | name: "LookinServer",
15 | targets: ["LookinServer"]),
16 | ],
17 | dependencies: [
18 | // Dependencies declare other packages that this package depends on.
19 | // .package(url: /* package url */, from: "1.0.0"),
20 | ],
21 | targets: [
22 | // Targets are the basic building blocks of a package. A target can define a module or a test suite.
23 | // Targets can depend on other targets in this package, and on products in packages this package depends on.
24 | .target(
25 | name: "LookinServer",
26 | dependencies: [.target(name: "LookinServerSwift")],
27 | path: "Src/Main",
28 | publicHeadersPath: "",
29 | cSettings: [
30 | .headerSearchPath("**"),
31 | .headerSearchPath("Server"),
32 | .headerSearchPath("Server/Category"),
33 | .headerSearchPath("Server/Connection"),
34 | .headerSearchPath("Server/Connection/RequestHandler"),
35 | .headerSearchPath("Server/Inspect"),
36 | .headerSearchPath("Server/Others"),
37 | .headerSearchPath("Server/Perspective"),
38 | .headerSearchPath("Shared"),
39 | .headerSearchPath("Shared/Category"),
40 | .headerSearchPath("Shared/Message"),
41 | .headerSearchPath("Shared/Peertalk"),
42 | ],
43 | cxxSettings: [
44 | .define("SHOULD_COMPILE_LOOKIN_SERVER", to: "1", .when(configuration: .debug)),
45 | .define("SPM_LOOKIN_SERVER_ENABLED", to: "1", .when(configuration: .debug))
46 | ]
47 | ),
48 | .target(
49 | name: "LookinServerSwift",
50 | dependencies: [.target(name: "LookinServerBase")],
51 | path: "Src/Swift",
52 | cxxSettings: [
53 | .define("SHOULD_COMPILE_LOOKIN_SERVER", to: "1", .when(configuration: .debug)),
54 | .define("SPM_LOOKIN_SERVER_ENABLED", to: "1", .when(configuration: .debug))
55 | ],
56 | swiftSettings: [
57 | .define("SHOULD_COMPILE_LOOKIN_SERVER", .when(configuration: .debug)),
58 | .define("SPM_LOOKIN_SERVER_ENABLED", .when(configuration: .debug))
59 | ]
60 | ),
61 | .target(
62 | name: "LookinServerBase",
63 | dependencies: [],
64 | path: "Src/Base",
65 | publicHeadersPath: "",
66 | cxxSettings: [
67 | .define("SHOULD_COMPILE_LOOKIN_SERVER", to: "1", .when(configuration: .debug))
68 | ]
69 | )
70 | ]
71 | )
72 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | # Introduction
4 | You can inspect and modify views in iOS app via Lookin, just like UI Inspector in Xcode, or another app called Reveal.
5 |
6 | Official Website:https://lookin.work/
7 |
8 | # Integration Guide
9 | To use Lookin macOS app, you need to integrate LookinServer (iOS Framework of Lookin) into your iOS project.
10 |
11 | > **Warning**
12 | > 1. Never integrate LookinServer in Release building configuration.
13 | > 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
14 |
15 | ## via CocoaPods:
16 | ### Swift Project
17 | `pod 'LookinServer', :subspecs => ['Swift'], :configurations => ['Debug']`
18 | ### Objective-C Project
19 | `pod 'LookinServer', :configurations => ['Debug']`
20 | ## via Swift Package Manager:
21 | `https://github.com/QMUI/LookinServer/`
22 |
23 | # Repository
24 | LookinServer: https://github.com/QMUI/LookinServer
25 |
26 | macOS app: https://github.com/hughkli/Lookin/
27 |
28 | # Tips
29 | - How to display custom information in Lookin: https://bytedance.larkoffice.com/docx/TRridRXeUoErMTxs94bcnGchnlb
30 | - How to display more member variables in Lookin: https://bytedance.larkoffice.com/docx/CKRndHqdeoub11xSqUZcMlFhnWe
31 | - How to turn on Swift optimization for Lookin: https://bytedance.larkoffice.com/docx/GFRLdzpeKoakeyxvwgCcZ5XdnTb
32 | - Documentation Collection: https://bytedance.larkoffice.com/docx/Yvv1d57XQoe5l0xZ0ZRc0ILfnWb
33 |
34 | # Acknowledgements
35 | https://qxh1ndiez2w.feishu.cn/docx/YIFjdE4gIolp3hxn1tGckiBxnWf
36 |
37 | ---
38 | # 简介
39 | Lookin 可以查看与修改 iOS App 里的 UI 对象,类似于 Xcode 自带的 UI Inspector 工具,或另一款叫做 Reveal 的软件。
40 |
41 | 官网:https://lookin.work/
42 |
43 | # 安装 LookinServer Framework
44 | 如果这是你的 iOS 项目第一次使用 Lookin,则需要先把 LookinServer 这款 iOS Framework 集成到你的 iOS 项目中。
45 |
46 | > **Warning**
47 | >
48 | > 1. 不要在 AppStore 模式下集成 LookinServer。
49 | > 2. 不要使用早于 1.0.6 的版本,因为它包含一个严重 Bug,可能导致线上事故: https://qxh1ndiez2w.feishu.cn/wiki/Z9SpwT7zWiqvYvkBe7Lc6Disnab
50 | ## 通过 CocoaPods:
51 |
52 | ### Swift 项目
53 | `pod 'LookinServer', :subspecs => ['Swift'], :configurations => ['Debug']`
54 | ### Objective-C 项目
55 | `pod 'LookinServer', :configurations => ['Debug']`
56 |
57 | ## 通过 Swift Package Manager:
58 | `https://github.com/QMUI/LookinServer/`
59 |
60 | # 源代码仓库
61 |
62 | iOS 端 LookinServer:https://github.com/QMUI/LookinServer
63 |
64 | macOS 端软件:https://github.com/hughkli/Lookin/
65 |
66 | # 技巧
67 | - 如何在 Lookin 中展示自定义信息: https://bytedance.larkoffice.com/docx/TRridRXeUoErMTxs94bcnGchnlb
68 | - 如何在 Lookin 中展示更多成员变量: https://bytedance.larkoffice.com/docx/CKRndHqdeoub11xSqUZcMlFhnWe
69 | - 如何为 Lookin 开启 Swift 优化: https://bytedance.larkoffice.com/docx/GFRLdzpeKoakeyxvwgCcZ5XdnTb
70 | - 文档汇总:https://bytedance.larkoffice.com/docx/Yvv1d57XQoe5l0xZ0ZRc0ILfnWb
71 |
72 | # 鸣谢
73 | https://qxh1ndiez2w.feishu.cn/docx/YIFjdE4gIolp3hxn1tGckiBxnWf
74 |
--------------------------------------------------------------------------------
/Src/Base/LookinIvarTrace.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LookinIvarTrace.h
5 | // Lookin
6 | //
7 | // Created by Li Kai on 2019/4/30.
8 | // https://lookin.work
9 | //
10 |
11 | #import
12 |
13 | extern NSString *const LookinIvarTraceRelationValue_Self;
14 |
15 | /// 如果 hostClassName 和 ivarName 均 equal,则认为两个 LookinIvarTrace 对象彼此 equal
16 | /// 比如 A 是 B 的 superview,且 A 的 "_stageView" 指向 B,则 B 会有一个 LookinIvarTrace:hostType 为 “superview”,hostClassName 为 A 的 class,ivarName 为 “_stageView”
17 | @interface LookinIvarTrace : NSObject
18 |
19 | /// 该值可能是 "superview"、"superlayer"、“self” 或 nil
20 | @property(nonatomic, copy) NSString *relation;
21 |
22 | @property(nonatomic, copy) NSString *hostClassName;
23 |
24 | @property(nonatomic, copy) NSString *ivarName;
25 |
26 | #pragma mark - No Coding
27 |
28 | #if TARGET_OS_IPHONE
29 | @property(nonatomic, weak) id hostObject;
30 | #endif
31 |
32 | @end
33 |
34 | @interface NSObject (LookinServerTrace)
35 |
36 | @property(nonatomic, copy) NSArray *lks_ivarTraces;
37 |
38 | @end
39 |
40 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
41 |
--------------------------------------------------------------------------------
/Src/Base/LookinIvarTrace.m:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LookinIvarTrace.m
5 | // Lookin
6 | //
7 | // Created by Li Kai on 2019/4/30.
8 | // https://lookin.work
9 | //
10 |
11 | #import "LookinIvarTrace.h"
12 |
13 | NSString *const LookinIvarTraceRelationValue_Self = @"self";
14 |
15 | @implementation LookinIvarTrace
16 |
17 | #pragma mark - Equal
18 |
19 | - (NSUInteger)hash {
20 | return self.hostClassName.hash ^ self.ivarName.hash;
21 | }
22 |
23 | - (BOOL)isEqual:(id)object {
24 | if (self == object) {
25 | return YES;
26 | }
27 | if (![object isKindOfClass:[LookinIvarTrace class]]) {
28 | return NO;
29 | }
30 | LookinIvarTrace *comparedObj = object;
31 | if ([self.hostClassName isEqualToString:comparedObj.hostClassName] && [self.ivarName isEqualToString:comparedObj.ivarName]) {
32 | return YES;
33 | }
34 | return NO;
35 | }
36 |
37 | #pragma mark -
38 |
39 | - (id)copyWithZone:(NSZone *)zone {
40 | LookinIvarTrace *newTrace = [[LookinIvarTrace allocWithZone:zone] init];
41 | newTrace.relation = self.relation;
42 | newTrace.hostClassName = self.hostClassName;
43 | newTrace.ivarName = self.ivarName;
44 | return newTrace;
45 | }
46 |
47 | #pragma mark -
48 |
49 | - (void)encodeWithCoder:(NSCoder *)aCoder {
50 | [aCoder encodeObject:self.relation forKey:@"relation"];
51 | [aCoder encodeObject:self.hostClassName forKey:@"hostClassName"];
52 | [aCoder encodeObject:self.ivarName forKey:@"ivarName"];
53 | }
54 |
55 | - (instancetype)initWithCoder:(NSCoder *)aDecoder {
56 | if (self = [super init]) {
57 | self.relation = [aDecoder decodeObjectForKey:@"relation"];
58 | self.hostClassName = [aDecoder decodeObjectForKey:@"hostClassName"];
59 | self.ivarName = [aDecoder decodeObjectForKey:@"ivarName"];
60 | }
61 | return self;
62 | }
63 |
64 | + (BOOL)supportsSecureCoding {
65 | return YES;
66 | }
67 |
68 | @end
69 |
70 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
71 |
--------------------------------------------------------------------------------
/Src/Main/Server/Category/CALayer+LookinServer.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // UIView+LookinMobile.h
5 | // WeRead
6 | //
7 | // Created by Li Kai on 2018/11/30.
8 | // Copyright © 2018 tencent. All rights reserved.
9 | //
10 |
11 | #import "LookinDefines.h"
12 | #import "TargetConditionals.h"
13 | #import
14 |
15 | @interface CALayer (LookinServer)
16 |
17 | /// 如果 myView.layer == myLayer,则 myLayer.lks_hostView 会返回 myView
18 | @property(nonatomic, readonly, weak) UIView *lks_hostView;
19 |
20 | - (UIWindow *)lks_window;
21 |
22 | - (CGRect)lks_frameInWindow:(UIWindow *)window;
23 |
24 | - (UIImage *)lks_groupScreenshotWithLowQuality:(BOOL)lowQuality;
25 | /// 当没有 sublayers 时,该方法返回 nil
26 | - (UIImage *)lks_soloScreenshotWithLowQuality:(BOOL)lowQuality;
27 |
28 | /// 获取和该对象有关的对象的 Class 层级树
29 | - (NSArray *> *)lks_relatedClassChainList;
30 |
31 | - (NSArray *)lks_selfRelation;
32 |
33 | @property(nonatomic, strong) UIColor *lks_backgroundColor;
34 | @property(nonatomic, strong) UIColor *lks_borderColor;
35 | @property(nonatomic, strong) UIColor *lks_shadowColor;
36 | @property(nonatomic, assign) CGFloat lks_shadowOffsetWidth;
37 | @property(nonatomic, assign) CGFloat lks_shadowOffsetHeight;
38 |
39 | @end
40 |
41 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
42 |
--------------------------------------------------------------------------------
/Src/Main/Server/Category/NSObject+LookinServer.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // NSObject+LookinServer.h
5 | // LookinServer
6 | //
7 | // Created by Li Kai on 2019/4/21.
8 | // https://lookin.work
9 | //
10 |
11 | #import "LookinDefines.h"
12 | #import
13 |
14 | @class LookinIvarTrace;
15 |
16 | @interface NSObject (LookinServer)
17 |
18 | #pragma mark - oid
19 |
20 | /// 如果 oid 不存在则会创建新的 oid
21 | - (unsigned long)lks_registerOid;
22 |
23 | /// 0 表示不存在
24 | @property(nonatomic, assign) unsigned long lks_oid;
25 |
26 | + (NSObject *)lks_objectWithOid:(unsigned long)oid;
27 |
28 | #pragma mark - trace
29 |
30 | @property(nonatomic, copy) NSString *lks_specialTrace;
31 |
32 | + (void)lks_clearAllObjectsTraces;
33 |
34 | /**
35 | 获取当前对象的 Class 层级树,如 @[@"UIView", @"UIResponder", @"NSObject"]。未 demangle,有 Swift Module Name
36 | */
37 | - (NSArray *)lks_classChainList;
38 |
39 | @end
40 |
41 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
42 |
--------------------------------------------------------------------------------
/Src/Main/Server/Category/NSObject+LookinServer.m:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // NSObject+LookinServer.m
5 | // LookinServer
6 | //
7 | // Created by Li Kai on 2019/4/21.
8 | // https://lookin.work
9 | //
10 |
11 | #import "NSObject+Lookin.h"
12 | #import "NSObject+LookinServer.h"
13 | #import "LookinServerDefines.h"
14 | #import "LKS_ObjectRegistry.h"
15 | #import
16 |
17 | @implementation NSObject (LookinServer)
18 |
19 | #pragma mark - oid
20 |
21 | - (unsigned long)lks_registerOid {
22 | if (!self.lks_oid) {
23 | unsigned long oid = [[LKS_ObjectRegistry sharedInstance] addObject:self];
24 | self.lks_oid = oid;
25 | }
26 | return self.lks_oid;
27 | }
28 |
29 | - (void)setLks_oid:(unsigned long)lks_oid {
30 | [self lookin_bindObject:@(lks_oid) forKey:@"lks_oid"];
31 | }
32 |
33 | - (unsigned long)lks_oid {
34 | NSNumber *number = [self lookin_getBindObjectForKey:@"lks_oid"];
35 | return [number unsignedLongValue];
36 | }
37 |
38 | + (NSObject *)lks_objectWithOid:(unsigned long)oid {
39 | return [[LKS_ObjectRegistry sharedInstance] objectWithOid:oid];
40 | }
41 |
42 | #pragma mark - trace
43 |
44 | - (void)setLks_ivarTraces:(NSArray *)lks_ivarTraces {
45 | [self lookin_bindObject:lks_ivarTraces.copy forKey:@"lks_ivarTraces"];
46 |
47 | if (lks_ivarTraces) {
48 | [[NSObject lks_allObjectsWithTraces] addPointer:(void *)self];
49 | }
50 | }
51 |
52 | - (NSArray *)lks_ivarTraces {
53 | return [self lookin_getBindObjectForKey:@"lks_ivarTraces"];
54 | }
55 |
56 | - (void)setLks_specialTrace:(NSString *)lks_specialTrace {
57 | [self lookin_bindObject:lks_specialTrace forKey:@"lks_specialTrace"];
58 | if (lks_specialTrace) {
59 | [[NSObject lks_allObjectsWithTraces] addPointer:(void *)self];
60 | }
61 | }
62 | - (NSString *)lks_specialTrace {
63 | return [self lookin_getBindObjectForKey:@"lks_specialTrace"];
64 | }
65 |
66 | + (void)lks_clearAllObjectsTraces {
67 | [[[NSObject lks_allObjectsWithTraces] allObjects] enumerateObjectsUsingBlock:^(NSObject * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
68 | obj.lks_ivarTraces = nil;
69 | obj.lks_specialTrace = nil;
70 | }];
71 | [NSObject lks_allObjectsWithTraces].count = 0;
72 | }
73 |
74 | + (NSPointerArray *)lks_allObjectsWithTraces {
75 | static dispatch_once_t onceToken;
76 | static NSPointerArray *lks_allObjectsWithTraces = nil;
77 | dispatch_once(&onceToken,^{
78 | lks_allObjectsWithTraces = [NSPointerArray weakObjectsPointerArray];
79 | });
80 | return lks_allObjectsWithTraces;
81 | }
82 |
83 | - (NSArray *)lks_classChainList {
84 | NSMutableArray *classChainList = [NSMutableArray array];
85 | Class currentClass = self.class;
86 |
87 | while (currentClass) {
88 | NSString *currentClassName = NSStringFromClass(currentClass);
89 | if (currentClassName) {
90 | [classChainList addObject:currentClassName];
91 | }
92 | currentClass = [currentClass superclass];
93 | }
94 | return classChainList.copy;
95 | }
96 |
97 | @end
98 |
99 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
100 |
--------------------------------------------------------------------------------
/Src/Main/Server/Category/UIBlurEffect+LookinServer.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // UIBlurEffect+LookinServer.h
5 | // LookinServer
6 | //
7 | // Created by Li Kai on 2019/10/8.
8 | // https://lookin.work
9 | //
10 |
11 | #import
12 |
13 | @interface UIBlurEffect (LookinServer)
14 |
15 | /// 该 number 包装的对象是 UIBlurEffectStyle,之所以用 NSNumber 是因为想把 0 和 nil 区分开,毕竟这里是在 hook 系统,稳一点好。
16 | /// 该方法的实现需要 Hook,因此若定义了 LOOKIN_SERVER_DISABLE_HOOK 宏,则属性会返回 nil
17 | @property(nonatomic, strong) NSNumber *lks_effectStyleNumber;
18 |
19 | @end
20 |
21 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
22 |
--------------------------------------------------------------------------------
/Src/Main/Server/Category/UIBlurEffect+LookinServer.m:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // UIBlurEffect+LookinServer.m
5 | // LookinServer
6 | //
7 | // Created by Li Kai on 2019/10/8.
8 | // https://lookin.work
9 | //
10 |
11 | #import "UIBlurEffect+LookinServer.h"
12 | #import "NSObject+Lookin.h"
13 | #import
14 |
15 | @implementation UIBlurEffect (LookinServer)
16 |
17 | #ifdef LOOKIN_SERVER_DISABLE_HOOK
18 |
19 | - (void)setLks_effectStyleNumber:(NSNumber *)lks_effectStyleNumber {
20 | }
21 |
22 | - (NSNumber *)lks_effectStyleNumber {
23 | return nil;
24 | }
25 |
26 | #else
27 |
28 | + (void)load {
29 | static dispatch_once_t onceToken;
30 | dispatch_once(&onceToken, ^{
31 | Method oriMethod = class_getClassMethod([self class], @selector(effectWithStyle:));
32 | Method newMethod = class_getClassMethod([self class], @selector(lks_effectWithStyle:));
33 | method_exchangeImplementations(oriMethod, newMethod);
34 | });
35 | }
36 |
37 | + (UIBlurEffect *)lks_effectWithStyle:(UIBlurEffectStyle)style {
38 | id effect = [self lks_effectWithStyle:style];
39 | if ([effect respondsToSelector:@selector(setLks_effectStyleNumber:)]) {
40 | [effect setLks_effectStyleNumber:@(style)];
41 | }
42 | return effect;
43 | }
44 |
45 | - (void)setLks_effectStyleNumber:(NSNumber *)lks_effectStyleNumber {
46 | [self lookin_bindObject:lks_effectStyleNumber forKey:@"lks_effectStyleNumber"];
47 | }
48 |
49 | - (NSNumber *)lks_effectStyleNumber {
50 | return [self lookin_getBindObjectForKey:@"lks_effectStyleNumber"];
51 | }
52 |
53 | #endif /* LOOKIN_SERVER_DISABLE_HOOK */
54 |
55 | @end
56 |
57 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
58 |
--------------------------------------------------------------------------------
/Src/Main/Server/Category/UIColor+LookinServer.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // UIColor+LookinServer.h
5 | // LookinServer
6 | //
7 | // Created by Li Kai on 2019/6/5.
8 | // https://lookin.work
9 | //
10 |
11 | #import
12 |
13 | @interface UIColor (LookinServer)
14 |
15 | - (NSArray *)lks_rgbaComponents;
16 | + (instancetype)lks_colorFromRGBAComponents:(NSArray *)components;
17 |
18 | - (NSString *)lks_rgbaString;
19 | - (NSString *)lks_hexString;
20 |
21 | /// will check if the argument is a real CGColor
22 | + (UIColor *)lks_colorWithCGColor:(CGColorRef)cgColor;
23 |
24 | @end
25 |
26 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
27 |
--------------------------------------------------------------------------------
/Src/Main/Server/Category/UIImage+LookinServer.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // UIImage+LookinServer.h
5 | // LookinServer
6 | //
7 | // Created by Li Kai on 2019/5/14.
8 | // https://lookin.work
9 | //
10 |
11 | #import
12 |
13 | @interface UIImage (LookinServer)
14 |
15 | /// 该方法的实现需要 Hook,因此若定义了 LOOKIN_SERVER_DISABLE_HOOK 宏,则属性会返回 nil
16 | @property(nonatomic, copy) NSString *lks_imageSourceName;
17 |
18 | - (NSData *)lookin_data;
19 |
20 | @end
21 |
22 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
23 |
--------------------------------------------------------------------------------
/Src/Main/Server/Category/UIImageView+LookinServer.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // UIImageView+LookinServer.h
5 | // LookinServer
6 | //
7 | // Created by Li Kai on 2019/9/18.
8 | // https://lookin.work
9 | //
10 |
11 | #import
12 |
13 | @interface UIImageView (LookinServer)
14 |
15 | - (NSString *)lks_imageSourceName;
16 | - (NSNumber *)lks_imageViewOidIfHasImage;
17 |
18 | @end
19 |
20 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
21 |
--------------------------------------------------------------------------------
/Src/Main/Server/Category/UIImageView+LookinServer.m:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // UIImageView+LookinServer.m
5 | // LookinServer
6 | //
7 | // Created by Li Kai on 2019/9/18.
8 | // https://lookin.work
9 | //
10 |
11 | #import "UIImageView+LookinServer.h"
12 | #import "UIImage+LookinServer.h"
13 | #import "NSObject+LookinServer.h"
14 |
15 | @implementation UIImageView (LookinServer)
16 |
17 | - (NSString *)lks_imageSourceName {
18 | return self.image.lks_imageSourceName;
19 | }
20 |
21 | - (NSNumber *)lks_imageViewOidIfHasImage {
22 | if (!self.image) {
23 | return nil;
24 | }
25 | unsigned long oid = [self lks_registerOid];
26 | return @(oid);
27 | }
28 |
29 | @end
30 |
31 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
32 |
--------------------------------------------------------------------------------
/Src/Main/Server/Category/UILabel+LookinServer.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // UILabel+LookinServer.h
5 | // LookinServer
6 | //
7 | // Created by Li Kai on 2019/2/26.
8 | // https://lookin.work
9 | //
10 |
11 | #import
12 |
13 | @interface UILabel (LookinServer)
14 |
15 | @property(nonatomic, assign) CGFloat lks_fontSize;
16 |
17 | - (NSString *)lks_fontName;
18 |
19 | @end
20 |
21 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
22 |
--------------------------------------------------------------------------------
/Src/Main/Server/Category/UILabel+LookinServer.m:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // UILabel+LookinServer.m
5 | // LookinServer
6 | //
7 | // Created by Li Kai on 2019/2/26.
8 | // https://lookin.work
9 | //
10 |
11 | #import "UILabel+LookinServer.h"
12 |
13 | @implementation UILabel (LookinServer)
14 |
15 | - (CGFloat)lks_fontSize {
16 | return self.font.pointSize;
17 | }
18 | - (void)setLks_fontSize:(CGFloat)lks_fontSize {
19 | UIFont *font = [self.font fontWithSize:lks_fontSize];
20 | self.font = font;
21 | }
22 |
23 | - (NSString *)lks_fontName {
24 | return self.font.fontName;
25 | }
26 |
27 | @end
28 |
29 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
30 |
--------------------------------------------------------------------------------
/Src/Main/Server/Category/UITableView+LookinServer.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // UITableView+LookinServer.h
5 | // LookinServer
6 | //
7 | // Created by Li Kai on 2019/9/5.
8 | // https://lookin.work
9 | //
10 |
11 | #import
12 |
13 | @interface UITableView (LookinServer)
14 |
15 | - (NSArray *)lks_numberOfRows;
16 |
17 | @end
18 |
19 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
20 |
--------------------------------------------------------------------------------
/Src/Main/Server/Category/UITableView+LookinServer.m:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // UITableView+LookinServer.m
5 | // LookinServer
6 | //
7 | // Created by Li Kai on 2019/9/5.
8 | // https://lookin.work
9 | //
10 |
11 | #import "UITableView+LookinServer.h"
12 | #import "LookinServerDefines.h"
13 |
14 | @implementation UITableView (LookinServer)
15 |
16 | - (NSArray *)lks_numberOfRows {
17 | NSUInteger sectionsCount = MIN(self.numberOfSections, 10);
18 | NSArray *rowsCount = [NSArray lookin_arrayWithCount:sectionsCount block:^id(NSUInteger idx) {
19 | return @([self numberOfRowsInSection:idx]);
20 | }];
21 | if (rowsCount.count == 0) {
22 | return nil;
23 | }
24 | return rowsCount;
25 | }
26 |
27 | @end
28 |
29 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
30 |
--------------------------------------------------------------------------------
/Src/Main/Server/Category/UITextField+LookinServer.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // UITextField+LookinServer.h
5 | // LookinServer
6 | //
7 | // Created by Li Kai on 2019/2/26.
8 | // https://lookin.work
9 | //
10 |
11 | #import
12 |
13 | @interface UITextField (LookinServer)
14 |
15 | @property(nonatomic, assign) CGFloat lks_fontSize;
16 |
17 | - (NSString *)lks_fontName;
18 |
19 | @end
20 |
21 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
22 |
--------------------------------------------------------------------------------
/Src/Main/Server/Category/UITextField+LookinServer.m:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // UITextField+LookinServer.m
5 | // LookinServer
6 | //
7 | // Created by Li Kai on 2019/2/26.
8 | // https://lookin.work
9 | //
10 |
11 | #import "UITextField+LookinServer.h"
12 |
13 | @implementation UITextField (LookinServer)
14 |
15 | - (CGFloat)lks_fontSize {
16 | return self.font.pointSize;
17 | }
18 | - (void)setLks_fontSize:(CGFloat)lks_fontSize {
19 | UIFont *font = [self.font fontWithSize:lks_fontSize];
20 | self.font = font;
21 | }
22 |
23 | - (NSString *)lks_fontName {
24 | return self.font.fontName;
25 | }
26 |
27 | @end
28 |
29 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
30 |
--------------------------------------------------------------------------------
/Src/Main/Server/Category/UITextView+LookinServer.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // UITextView+LookinServer.h
5 | // LookinServer
6 | //
7 | // Created by Li Kai on 2019/2/26.
8 | // https://lookin.work
9 | //
10 |
11 | #import
12 |
13 | @interface UITextView (LookinServer)
14 |
15 | @property(nonatomic, assign) CGFloat lks_fontSize;
16 |
17 | - (NSString *)lks_fontName;
18 |
19 | @end
20 |
21 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
22 |
--------------------------------------------------------------------------------
/Src/Main/Server/Category/UITextView+LookinServer.m:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // UITextView+LookinServer.m
5 | // LookinServer
6 | //
7 | // Created by Li Kai on 2019/2/26.
8 | // https://lookin.work
9 | //
10 |
11 | #import "UITextView+LookinServer.h"
12 |
13 | @implementation UITextView (LookinServer)
14 |
15 | - (CGFloat)lks_fontSize {
16 | return self.font.pointSize;
17 | }
18 | - (void)setLks_fontSize:(CGFloat)lks_fontSize {
19 | UIFont *font = [self.font fontWithSize:lks_fontSize];
20 | self.font = font;
21 | }
22 |
23 | - (NSString *)lks_fontName {
24 | return self.font.fontName;
25 | }
26 |
27 | @end
28 |
29 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
30 |
--------------------------------------------------------------------------------
/Src/Main/Server/Category/UIView+LookinServer.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // UIView+LookinServer.h
5 | // LookinServer
6 | //
7 | // Created by Li Kai on 2019/3/19.
8 | // https://lookin.work
9 | //
10 |
11 | #import "LookinDefines.h"
12 | #import
13 |
14 | @interface UIView (LookinServer)
15 |
16 | /// 如果 myViewController.view = myView,则可以通过 myView 的 lks_findHostViewController 方法找到 myViewController
17 | - (UIViewController *)lks_findHostViewController;
18 |
19 | /// 是否是 UITabBar 的 childrenView,如果是的话,则截图时需要强制使用 renderInContext: 的方式而非 drawViewHierarchyInRect:afterScreenUpdates: 否则在 iOS 13 上获取到的图像是空的不知道为什么
20 | @property(nonatomic, assign) BOOL lks_isChildrenViewOfTabBar;
21 |
22 | /// point 是相对于 receiver 自身的坐标系
23 | - (UIView *)lks_subviewAtPoint:(CGPoint)point preferredClasses:(NSArray *)preferredClasses;
24 |
25 | - (CGFloat)lks_bestWidth;
26 | - (CGFloat)lks_bestHeight;
27 | - (CGSize)lks_bestSize;
28 |
29 | @property(nonatomic, assign) float lks_horizontalContentHuggingPriority;
30 | @property(nonatomic, assign) float lks_verticalContentHuggingPriority;
31 |
32 | @property(nonatomic, assign) float lks_horizontalContentCompressionResistancePriority;
33 | @property(nonatomic, assign) float lks_verticalContentCompressionResistancePriority;
34 |
35 | /// 遍历全局的 view 并给他们设置 lks_involvedRawConstraints 属性
36 | + (void)lks_rebuildGlobalInvolvedRawConstraints;
37 | /// 该属性保存了牵扯到当前 view 的所有 constraints,包括那些没有生效的
38 | @property(nonatomic, strong) NSMutableArray *lks_involvedRawConstraints;
39 |
40 | - (NSArray *> *)lks_constraints;
41 |
42 | @end
43 |
44 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
45 |
--------------------------------------------------------------------------------
/Src/Main/Server/Category/UIViewController+LookinServer.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // UIViewController+LookinServer.h
5 | // LookinServer
6 | //
7 | // Created by Li Kai on 2019/4/22.
8 | // https://lookin.work
9 | //
10 |
11 | #import
12 |
13 | @interface UIViewController (LookinServer)
14 |
15 | + (UIViewController *)lks_visibleViewController;
16 |
17 | @end
18 |
19 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
20 |
--------------------------------------------------------------------------------
/Src/Main/Server/Category/UIViewController+LookinServer.m:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // UIViewController+LookinServer.m
5 | // LookinServer
6 | //
7 | // Created by Li Kai on 2019/4/22.
8 | // https://lookin.work
9 | //
10 |
11 | #import "UIViewController+LookinServer.h"
12 | #import "UIView+LookinServer.h"
13 | #import
14 | #import "LKS_MultiplatformAdapter.h"
15 |
16 | @implementation UIViewController (LookinServer)
17 |
18 | + (nullable UIViewController *)lks_visibleViewController {
19 |
20 | UIViewController *rootViewController = [LKS_MultiplatformAdapter keyWindow].rootViewController;
21 | UIViewController *visibleViewController = [rootViewController lks_visibleViewControllerIfExist];
22 | return visibleViewController;
23 | }
24 |
25 | - (UIViewController *)lks_visibleViewControllerIfExist {
26 |
27 | if (self.presentedViewController) {
28 | return [self.presentedViewController lks_visibleViewControllerIfExist];
29 | }
30 |
31 | if ([self isKindOfClass:[UINavigationController class]]) {
32 | return [((UINavigationController *)self).visibleViewController lks_visibleViewControllerIfExist];
33 | }
34 |
35 | if ([self isKindOfClass:[UITabBarController class]]) {
36 | return [((UITabBarController *)self).selectedViewController lks_visibleViewControllerIfExist];
37 | }
38 |
39 | if (self.isViewLoaded && !self.view.hidden && self.view.alpha > 0.01) {
40 | return self;
41 | } else {
42 | return nil;
43 | }
44 | }
45 |
46 | @end
47 |
48 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
49 |
--------------------------------------------------------------------------------
/Src/Main/Server/Category/UIVisualEffectView+LookinServer.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // UIVisualEffectView+LookinServer.h
5 | // LookinServer
6 | //
7 | // Created by Li Kai on 2019/10/8.
8 | // https://lookin.work
9 | //
10 |
11 | #import
12 |
13 | @interface UIVisualEffectView (LookinServer)
14 |
15 | - (void)setLks_blurEffectStyleNumber:(NSNumber *)lks_blurEffectStyleNumber;
16 |
17 | - (NSNumber *)lks_blurEffectStyleNumber;
18 |
19 | @end
20 |
21 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
22 |
--------------------------------------------------------------------------------
/Src/Main/Server/Category/UIVisualEffectView+LookinServer.m:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // UIVisualEffectView+LookinServer.m
5 | // LookinServer
6 | //
7 | // Created by Li Kai on 2019/10/8.
8 | // https://lookin.work
9 | //
10 |
11 | #import "UIVisualEffectView+LookinServer.h"
12 | #import "UIBlurEffect+LookinServer.h"
13 |
14 | @implementation UIVisualEffectView (LookinServer)
15 |
16 | - (void)setLks_blurEffectStyleNumber:(NSNumber *)lks_blurEffectStyleNumber {
17 | UIBlurEffectStyle style = [lks_blurEffectStyleNumber integerValue];
18 | UIBlurEffect *effect = [UIBlurEffect effectWithStyle:style];
19 | self.effect = effect;
20 | }
21 |
22 | - (NSNumber *)lks_blurEffectStyleNumber {
23 | UIVisualEffect *effect = self.effect;
24 | if (![effect isKindOfClass:[UIBlurEffect class]]) {
25 | return nil;
26 | }
27 | UIBlurEffect *blurEffect = (UIBlurEffect *)effect;
28 | return blurEffect.lks_effectStyleNumber;
29 | }
30 |
31 | @end
32 |
33 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
34 |
--------------------------------------------------------------------------------
/Src/Main/Server/Connection/LKS_ConnectionManager.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // Lookin.h
5 | // Lookin
6 | //
7 | // Created by Li Kai on 2018/8/5.
8 | // https://lookin.work
9 | //
10 |
11 | #import
12 |
13 | extern NSString *const LKS_ConnectionDidEndNotificationName;
14 |
15 | @class LookinConnectionResponseAttachment;
16 |
17 | @interface LKS_ConnectionManager : NSObject
18 |
19 | + (instancetype)sharedInstance;
20 |
21 | @property(nonatomic, assign) BOOL applicationIsActive;
22 |
23 | - (void)respond:(LookinConnectionResponseAttachment *)data requestType:(uint32_t)requestType tag:(uint32_t)tag;
24 |
25 | - (void)pushData:(NSObject *)data type:(uint32_t)type;
26 |
27 | @end
28 |
29 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
30 |
--------------------------------------------------------------------------------
/Src/Main/Server/Connection/LKS_RequestHandler.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LKS_RequestHandler.h
5 | // LookinServer
6 | //
7 | // Created by Li Kai on 2019/1/15.
8 | // https://lookin.work
9 | //
10 |
11 | #import
12 |
13 | @interface LKS_RequestHandler : NSObject
14 |
15 | - (BOOL)canHandleRequestType:(uint32_t)requestType;
16 |
17 | - (void)handleRequestType:(uint32_t)requestType tag:(uint32_t)tag object:(id)object;
18 |
19 | @end
20 |
21 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
22 |
--------------------------------------------------------------------------------
/Src/Main/Server/Connection/RequestHandler/LKS_AttrModificationPatchHandler.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LKS_AttrModificationPatchHandler.h
5 | // LookinServer
6 | //
7 | // Created by Li Kai on 2019/6/12.
8 | // https://lookin.work
9 | //
10 |
11 | #import
12 |
13 | @class LookinDisplayItemDetail;
14 |
15 | @interface LKS_AttrModificationPatchHandler : NSObject
16 |
17 | /**
18 | @param oids 数组内 idx 较小的应该为 displayItems 里的 subItem,idx 较大的应该为 superItem
19 | @param lowImageQuality 是否采用低图像质量
20 | @param block 该 block 会被多次调用,其中 tasksTotalCount 是总的调用次数(即可被用来作为 TotalResponseCount)
21 | */
22 | + (void)handleLayerOids:(NSArray *)oids lowImageQuality:(BOOL)lowImageQuality block:(void (^)(LookinDisplayItemDetail *detail, NSUInteger tasksTotalCount, NSError *error))block;
23 |
24 | @end
25 |
26 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
27 |
--------------------------------------------------------------------------------
/Src/Main/Server/Connection/RequestHandler/LKS_AttrModificationPatchHandler.m:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LKS_AttrModificationPatchHandler.m
5 | // LookinServer
6 | //
7 | // Created by Li Kai on 2019/6/12.
8 | // https://lookin.work
9 | //
10 |
11 | #import "LKS_AttrModificationPatchHandler.h"
12 | #import "LookinDisplayItemDetail.h"
13 | #import "LookinServerDefines.h"
14 |
15 | @implementation LKS_AttrModificationPatchHandler
16 |
17 | + (void)handleLayerOids:(NSArray *)oids lowImageQuality:(BOOL)lowImageQuality block:(void (^)(LookinDisplayItemDetail *detail, NSUInteger tasksTotalCount, NSError *error))block {
18 | if (!block) {
19 | NSAssert(NO, @"");
20 | return;
21 | }
22 | if (![oids isKindOfClass:[NSArray class]]) {
23 | block(nil, 1, LookinErr_Inner);
24 | return;
25 | }
26 |
27 | [oids enumerateObjectsUsingBlock:^(NSNumber * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
28 | unsigned long oid = [obj unsignedLongValue];
29 | LookinDisplayItemDetail *detail = [LookinDisplayItemDetail new];
30 | detail.displayItemOid = oid;
31 |
32 | CALayer *layer = (CALayer *)[NSObject lks_objectWithOid:oid];
33 | if (![layer isKindOfClass:[CALayer class]]) {
34 | block(nil, idx + 1, LookinErr_ObjNotFound);
35 | *stop = YES;
36 | return;
37 | }
38 |
39 | if (idx == 0) {
40 | detail.soloScreenshot = [layer lks_soloScreenshotWithLowQuality:lowImageQuality];
41 | detail.groupScreenshot = [layer lks_groupScreenshotWithLowQuality:lowImageQuality];
42 | } else {
43 | detail.groupScreenshot = [layer lks_groupScreenshotWithLowQuality:lowImageQuality];
44 | }
45 | block(detail, oids.count, nil);
46 | }];
47 | }
48 |
49 | @end
50 |
51 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
52 |
--------------------------------------------------------------------------------
/Src/Main/Server/Connection/RequestHandler/LKS_CustomAttrModificationHandler.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 | //
3 | // LKS_CustomAttrModificationHandler.h
4 | // LookinServer
5 | //
6 | // Created by likaimacbookhome on 2023/11/4.
7 | //
8 |
9 | #import
10 | #import "LookinCustomAttrModification.h"
11 |
12 | @interface LKS_CustomAttrModificationHandler : NSObject
13 |
14 | /// 返回值表示是否修改成功(有成功调用 setter block 就算成功)
15 | + (BOOL)handleModification:(LookinCustomAttrModification *)modification;
16 |
17 | @end
18 |
19 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
20 |
--------------------------------------------------------------------------------
/Src/Main/Server/Connection/RequestHandler/LKS_HierarchyDetailsHandler.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LKS_HierarchyDetailsHandler.h
5 | // LookinServer
6 | //
7 | // Created by Li Kai on 2019/6/20.
8 | // https://lookin.work
9 | //
10 |
11 | #import
12 |
13 | @class LookinDisplayItemDetail, LookinStaticAsyncUpdateTasksPackage;
14 |
15 | typedef void (^LKS_HierarchyDetailsHandler_ProgressBlock)(NSArray *details);
16 | typedef void (^LKS_HierarchyDetailsHandler_FinishBlock)(void);
17 |
18 | @interface LKS_HierarchyDetailsHandler : NSObject
19 |
20 | /// packages 会按照 idx 从小到大的顺序被执行
21 | /// 全部任务完成时,finishBlock 会被调用
22 | /// 如果调用了 cancel,则 finishBlock 不会被执行
23 | - (void)startWithPackages:(NSArray *)packages block:(LKS_HierarchyDetailsHandler_ProgressBlock)progressBlock finishedBlock:(LKS_HierarchyDetailsHandler_FinishBlock)finishBlock;
24 |
25 | /// 取消所有任务
26 | - (void)cancel;
27 |
28 | @end
29 |
30 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
31 |
--------------------------------------------------------------------------------
/Src/Main/Server/Connection/RequestHandler/LKS_InbuiltAttrModificationHandler.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LKS_InbuiltAttrModificationHandler.h
5 | // LookinServer
6 | //
7 | // Created by Li Kai on 2019/6/12.
8 | // https://lookin.work
9 | //
10 |
11 | #import
12 |
13 | @class LookinAttributeModification, LookinDisplayItemDetail, LookinStaticAsyncUpdateTask;
14 |
15 | @interface LKS_InbuiltAttrModificationHandler : NSObject
16 |
17 | + (void)handleModification:(LookinAttributeModification *)modification completion:(void (^)(LookinDisplayItemDetail *data, NSError *error))completion;
18 |
19 | + (void)handlePatchWithTasks:(NSArray *)tasks block:(void (^)(LookinDisplayItemDetail *data))block;
20 |
21 | @end
22 |
23 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
24 |
--------------------------------------------------------------------------------
/Src/Main/Server/LookinServer.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LookinServer.h
5 | // LookinServer
6 | //
7 | // Created by Li Kai on 2019/7/20.
8 | // https://lookin.work
9 | //
10 |
11 | #ifndef LookinServer_h
12 | #define LookinServer_h
13 |
14 |
15 | #endif /* LookinServer_h */
16 |
17 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
18 |
--------------------------------------------------------------------------------
/Src/Main/Server/Others/LKSConfigManager.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LKSConfigManager.h
5 | // LookinServer
6 | //
7 | // Created by likai.123 on 2023/1/10.
8 | //
9 |
10 | #import
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | @interface LKSConfigManager : NSObject
15 |
16 | + (NSArray *)collapsedClassList;
17 |
18 | + (NSDictionary *)colorAlias;
19 |
20 | + (BOOL)shouldCaptureScreenshotOfLayer:(CALayer *)layer;
21 |
22 | @end
23 |
24 | NS_ASSUME_NONNULL_END
25 |
26 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
27 |
--------------------------------------------------------------------------------
/Src/Main/Server/Others/LKS_AttrGroupsMaker.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LKS_AttrGroupsMaker.h
5 | // LookinServer
6 | //
7 | // Created by Li Kai on 2019/6/6.
8 | // https://lookin.work
9 | //
10 |
11 | #import "LookinDefines.h"
12 |
13 | @class LookinAttributesGroup;
14 |
15 | @interface LKS_AttrGroupsMaker : NSObject
16 |
17 | + (NSArray *)attrGroupsForLayer:(CALayer *)layer;
18 |
19 | @end
20 |
21 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
22 |
--------------------------------------------------------------------------------
/Src/Main/Server/Others/LKS_CustomAttrGroupsMaker.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 | //
3 | // LKS_CustomAttrGroupsMaker.h
4 | // LookinServer
5 | //
6 | // Created by LikaiMacStudioWork on 2023/10/31.
7 | //
8 |
9 | #import "LookinDefines.h"
10 |
11 | @class LookinAttributesGroup;
12 |
13 | @interface LKS_CustomAttrGroupsMaker : NSObject
14 |
15 | - (instancetype)initWithLayer:(CALayer *)layer;
16 |
17 | - (void)execute;
18 |
19 | - (NSArray *)getGroups;
20 | - (NSString *)getCustomDisplayTitle;
21 | - (NSString *)getDanceUISource;
22 |
23 | + (NSArray *)makeGroupsFromRawProperties:(NSArray *)rawProperties saveCustomSetter:(BOOL)saveCustomSetter;
24 |
25 | @end
26 |
27 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
28 |
--------------------------------------------------------------------------------
/Src/Main/Server/Others/LKS_CustomAttrSetterManager.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 | //
3 | // LKS_CustomAttrSetterManager.h
4 | // LookinServer
5 | //
6 | // Created by likai.123 on 2023/11/4.
7 | //
8 |
9 | #import
10 |
11 | typedef void(^LKS_StringSetter)(NSString *);
12 | typedef void(^LKS_NumberSetter)(NSNumber *);
13 | typedef void(^LKS_BoolSetter)(BOOL);
14 | typedef void(^LKS_ColorSetter)(UIColor *);
15 | typedef void(^LKS_EnumSetter)(NSString *);
16 | typedef void(^LKS_RectSetter)(CGRect);
17 | typedef void(^LKS_SizeSetter)(CGSize);
18 | typedef void(^LKS_PointSetter)(CGPoint);
19 | typedef void(^LKS_InsetsSetter)(UIEdgeInsets);
20 |
21 | @interface LKS_CustomAttrSetterManager : NSObject
22 |
23 | + (instancetype)sharedInstance;
24 |
25 | - (void)removeAll;
26 |
27 | - (void)saveStringSetter:(LKS_StringSetter)setter uniqueID:(NSString *)uniqueID;
28 | - (LKS_StringSetter)getStringSetterWithID:(NSString *)uniqueID;
29 |
30 | - (void)saveNumberSetter:(LKS_NumberSetter)setter uniqueID:(NSString *)uniqueID;
31 | - (LKS_NumberSetter)getNumberSetterWithID:(NSString *)uniqueID;
32 |
33 | - (void)saveBoolSetter:(LKS_BoolSetter)setter uniqueID:(NSString *)uniqueID;
34 | - (LKS_BoolSetter)getBoolSetterWithID:(NSString *)uniqueID;
35 |
36 | - (void)saveColorSetter:(LKS_ColorSetter)setter uniqueID:(NSString *)uniqueID;
37 | - (LKS_ColorSetter)getColorSetterWithID:(NSString *)uniqueID;
38 |
39 | - (void)saveEnumSetter:(LKS_EnumSetter)setter uniqueID:(NSString *)uniqueID;
40 | - (LKS_EnumSetter)getEnumSetterWithID:(NSString *)uniqueID;
41 |
42 | - (void)saveRectSetter:(LKS_RectSetter)setter uniqueID:(NSString *)uniqueID;
43 | - (LKS_RectSetter)getRectSetterWithID:(NSString *)uniqueID;
44 |
45 | - (void)saveSizeSetter:(LKS_SizeSetter)setter uniqueID:(NSString *)uniqueID;
46 | - (LKS_SizeSetter)getSizeSetterWithID:(NSString *)uniqueID;
47 |
48 | - (void)savePointSetter:(LKS_PointSetter)setter uniqueID:(NSString *)uniqueID;
49 | - (LKS_PointSetter)getPointSetterWithID:(NSString *)uniqueID;
50 |
51 | - (void)saveInsetsSetter:(LKS_InsetsSetter)setter uniqueID:(NSString *)uniqueID;
52 | - (LKS_InsetsSetter)getInsetsSetterWithID:(NSString *)uniqueID;
53 |
54 | @end
55 |
56 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
57 |
--------------------------------------------------------------------------------
/Src/Main/Server/Others/LKS_CustomDisplayItemsMaker.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LKS_CustomDisplayItemsMaker.h
5 | // LookinServer
6 | //
7 | // Created by likai.123 on 2023/11/1.
8 | //
9 |
10 | #import
11 |
12 | @class LookinDisplayItem;
13 |
14 | @interface LKS_CustomDisplayItemsMaker : NSObject
15 |
16 | - (instancetype)initWithLayer:(CALayer *)layer saveAttrSetter:(BOOL)saveAttrSetter;
17 |
18 | - (NSArray *)make;
19 |
20 | @end
21 |
22 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
23 |
--------------------------------------------------------------------------------
/Src/Main/Server/Others/LKS_EventHandlerMaker.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LKS_EventHandlerMaker.h
5 | // LookinServer
6 | //
7 | // Created by Li Kai on 2019/8/7.
8 | // https://lookin.work
9 | //
10 |
11 | #import "LookinDefines.h"
12 |
13 | @class LookinEventHandler;
14 |
15 | @interface LKS_EventHandlerMaker : NSObject
16 |
17 | + (NSArray *)makeForView:(UIView *)view;
18 |
19 | @end
20 |
21 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
22 |
--------------------------------------------------------------------------------
/Src/Main/Server/Others/LKS_ExportManager.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LKS_ExportManager.h
5 | // LookinServer
6 | //
7 | // Created by Li Kai on 2019/5/13.
8 | // https://lookin.work
9 | //
10 |
11 | #import
12 |
13 | @interface LKS_ExportManager : NSObject
14 |
15 | + (instancetype)sharedInstance;
16 |
17 | - (void)exportAndShare;
18 |
19 | @end
20 |
21 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
22 |
--------------------------------------------------------------------------------
/Src/Main/Server/Others/LKS_GestureTargetActionsSearcher.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LKS_GestureTargetActionsSearcher.h
5 | // LookinServer
6 | //
7 | // Created by likai.123 on 2023/9/11.
8 | //
9 |
10 | #import
11 |
12 | @class LookinTwoTuple;
13 |
14 | NS_ASSUME_NONNULL_BEGIN
15 |
16 | @interface LKS_GestureTargetActionsSearcher : NSObject
17 |
18 | /// 返回一个 UIGestureRecognizer 实例身上绑定的 target & action 信息
19 | /// tuple.first => LookinWeakContainer(包裹着 target),tuple.second => action(方法名字符串)
20 | + (NSArray *)getTargetActionsFromRecognizer:(UIGestureRecognizer *)recognizer;
21 |
22 | @end
23 |
24 | NS_ASSUME_NONNULL_END
25 |
26 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
27 |
--------------------------------------------------------------------------------
/Src/Main/Server/Others/LKS_GestureTargetActionsSearcher.m:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LKS_GestureTargetActionsSearcher.m
5 | // LookinServer
6 | //
7 | // Created by likai.123 on 2023/9/11.
8 | //
9 |
10 | #import "LKS_GestureTargetActionsSearcher.h"
11 | #import
12 | #import "NSArray+Lookin.h"
13 | #import "LookinTuple.h"
14 | #import "LookinWeakContainer.h"
15 |
16 | @implementation LKS_GestureTargetActionsSearcher
17 |
18 | + (NSArray *)getTargetActionsFromRecognizer:(UIGestureRecognizer *)recognizer {
19 | if (!recognizer) {
20 | return @[];
21 | }
22 | // KVC 要放到 try catch 里面防止 Crash
23 | @try {
24 | NSArray* targetsList = [recognizer valueForKey:@"_targets"];
25 | if (!targetsList || targetsList.count == 0) {
26 | return @[];
27 | }
28 | // 数组元素对象是 UIGestureRecognizerTarget*
29 | // 这个元素有两个属性,一个是名为 _target 的属性指向某个实例,另一个是名为 _action 的属性保存一个 SEL
30 | NSArray* ret = [targetsList lookin_map:^id(NSUInteger idx, id targetBox) {
31 | id targetObj = [targetBox valueForKey:@"_target"];
32 | if (!targetObj) {
33 | return nil;
34 | }
35 | SEL action = ((SEL (*)(id, Ivar))object_getIvar)(targetBox, class_getInstanceVariable([targetBox class], "_action"));
36 |
37 | LookinTwoTuple* tuple = [LookinTwoTuple new];
38 | tuple.first = [LookinWeakContainer containerWithObject:targetObj];
39 | tuple.second = (action == NULL ? @"NULL" : NSStringFromSelector(action));
40 | return tuple;
41 | }];
42 | return ret;
43 | }
44 | @catch (NSException * e) {
45 | NSLog(@"LookinServer - %@", e);
46 | return @[];
47 | }
48 | }
49 |
50 | @end
51 |
52 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
53 |
--------------------------------------------------------------------------------
/Src/Main/Server/Others/LKS_Helper.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LKS_Helper.h
5 | // LookinServer
6 | //
7 | // Created by Li Kai on 2019/7/20.
8 | // https://lookin.work
9 | //
10 |
11 | #import "LookinDefines.h"
12 |
13 |
14 |
15 | #import
16 |
17 | #define LKS_Localized(stringKey) NSLocalizedStringFromTableInBundle(stringKey, nil, [NSBundle bundleForClass:self.class], nil)
18 |
19 | @interface LKS_Helper : NSObject
20 |
21 | /// 如果 object 为 nil 则返回字符串 “nil”,否则返回字符串格式类似于 (UIView *)
22 | + (NSString *)descriptionOfObject:(id)object;
23 |
24 | /// 返回当前的bundle
25 | + (NSBundle *)bundle;
26 |
27 | @end
28 |
29 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
30 |
--------------------------------------------------------------------------------
/Src/Main/Server/Others/LKS_Helper.m:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LKS_Helper.m
5 | // LookinServer
6 | //
7 | // Created by Li Kai on 2019/7/20.
8 | // https://lookin.work
9 | //
10 |
11 | #import "LKS_Helper.h"
12 | #import "NSObject+LookinServer.h"
13 |
14 | @implementation LKS_Helper
15 |
16 | + (NSString *)descriptionOfObject:(id)object {
17 | if (!object) {
18 | return @"nil";
19 | }
20 | NSString *className = NSStringFromClass([object class]);
21 | return [NSString stringWithFormat:@"(%@ *)", className];
22 | }
23 |
24 | + (NSBundle *)bundle {
25 | static id bundle = nil;
26 | if (bundle != nil) {
27 | #ifdef SPM_RESOURCE_BUNDLE_IDENTIFITER
28 | bundle = [NSBundle bundleWithIdentifier:SPM_RESOURCE_BUNDLE_IDENTIFITER];
29 | #else
30 | bundle = [NSBundle bundleForClass:self.class];
31 | #endif
32 | }
33 | return bundle;
34 | }
35 |
36 | @end
37 |
38 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
39 |
--------------------------------------------------------------------------------
/Src/Main/Server/Others/LKS_HierarchyDisplayItemsMaker.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LKS_HierarchyDisplayItemsMaker.h
5 | // LookinServer
6 | //
7 | // Created by Li Kai on 2019/2/19.
8 | // https://lookin.work
9 | //
10 |
11 |
12 |
13 | #import "LookinDefines.h"
14 |
15 | @class LookinDisplayItem;
16 |
17 | @interface LKS_HierarchyDisplayItemsMaker : NSObject
18 |
19 | /// @param hasScreenshots 是否包含 soloScreenshots 和 groupScreenshot 属性
20 | /// @param hasAttrList 是否包含 attributesGroupList 属性
21 | /// @param lowQuality screenshots 是否为低质量(当 hasScreenshots 为 NO 时,该属性无意义)
22 | /// @param readCustomInfo 是否读取 lookin_customDebugInfos,比如低版本的 Lookin 发请求时,就无需读取(因为 Lookin 解析不了、还可能出 Bug)
23 | /// @param saveCustomSetter 是否要读取并保存用户给 attribute 配置的 custom setter
24 | + (NSArray *)itemsWithScreenshots:(BOOL)hasScreenshots attrList:(BOOL)hasAttrList lowImageQuality:(BOOL)lowQuality readCustomInfo:(BOOL)readCustomInfo saveCustomSetter:(BOOL)saveCustomSetter;
25 |
26 | /// 把 layer 的 sublayers 转换为 displayItem 数组并返回
27 | + (NSArray *)subitemsOfLayer:(CALayer *)layer;
28 |
29 | @end
30 |
31 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
32 |
--------------------------------------------------------------------------------
/Src/Main/Server/Others/LKS_MultiplatformAdapter.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 | //
3 | // LKS_MultiplatformAdapter.h
4 | //
5 | //
6 | // Created by nixjiang on 2024/3/12.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | @interface LKS_MultiplatformAdapter : NSObject
15 |
16 | + (UIWindow *)keyWindow;
17 |
18 | + (NSArray *)allWindows;
19 |
20 | + (CGRect)mainScreenBounds;
21 |
22 | + (CGFloat)mainScreenScale;
23 |
24 | + (BOOL)isiPad;
25 |
26 | @end
27 |
28 | NS_ASSUME_NONNULL_END
29 |
30 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
31 |
--------------------------------------------------------------------------------
/Src/Main/Server/Others/LKS_MultiplatformAdapter.m:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 | //
3 | // LKS_MultiplatformAdapter.m
4 | //
5 | //
6 | // Created by nixjiang on 2024/3/12.
7 | //
8 |
9 | #import "LKS_MultiplatformAdapter.h"
10 | #import
11 |
12 | @implementation LKS_MultiplatformAdapter
13 |
14 | + (BOOL)isiPad {
15 | static BOOL s_isiPad = NO;
16 |
17 | static dispatch_once_t onceToken;
18 | dispatch_once(&onceToken, ^{
19 | NSString *nsModel = [UIDevice currentDevice].model;
20 | s_isiPad = [nsModel hasPrefix:@"iPad"];
21 | });
22 |
23 | return s_isiPad;
24 | }
25 |
26 | + (CGRect)mainScreenBounds {
27 | #if TARGET_OS_VISION
28 | return [LKS_MultiplatformAdapter getFirstActiveWindowScene].coordinateSpace.bounds;
29 | #else
30 | return [UIScreen mainScreen].bounds;
31 | #endif
32 | }
33 |
34 | + (CGFloat)mainScreenScale {
35 | #if TARGET_OS_VISION
36 | return 2.f;
37 | #else
38 | return [UIScreen mainScreen].scale;
39 | #endif
40 | }
41 |
42 | #if TARGET_OS_VISION
43 | + (UIWindowScene *)getFirstActiveWindowScene {
44 | for (UIScene *scene in UIApplication.sharedApplication.connectedScenes) {
45 | if (![scene isKindOfClass:UIWindowScene.class]) {
46 | continue;
47 | }
48 | UIWindowScene *windowScene = (UIWindowScene *)scene;
49 | if (windowScene.activationState == UISceneActivationStateForegroundActive) {
50 | return windowScene;
51 | }
52 | }
53 | return nil;
54 | }
55 | #endif
56 |
57 | + (UIWindow *)keyWindow {
58 | #if TARGET_OS_VISION
59 | return [self getFirstActiveWindowScene].keyWindow;
60 | #else
61 | return [UIApplication sharedApplication].keyWindow;
62 | #endif
63 | }
64 |
65 | + (NSArray *)allWindows {
66 | #if TARGET_OS_VISION
67 | NSMutableArray *windows = [NSMutableArray new];
68 | for (UIScene *scene in
69 | UIApplication.sharedApplication.connectedScenes) {
70 | if (![scene isKindOfClass:UIWindowScene.class]) {
71 | continue;
72 | }
73 | UIWindowScene *windowScene = (UIWindowScene *)scene;
74 | [windows addObjectsFromArray:windowScene.windows];
75 |
76 | // 以UIModalPresentationFormSheet形式展示的页面由系统私有window承载,不出现在scene.windows,不过可以从scene.keyWindow中获取
77 | if (![windows containsObject:windowScene.keyWindow]) {
78 | if (![NSStringFromClass(windowScene.keyWindow.class) containsString:@"HUD"]) {
79 | [windows addObject:windowScene.keyWindow];
80 | }
81 | }
82 | }
83 |
84 | return [windows copy];
85 | #else
86 | return [[UIApplication sharedApplication].windows copy];
87 | #endif
88 | }
89 |
90 | @end
91 |
92 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
93 |
--------------------------------------------------------------------------------
/Src/Main/Server/Others/LKS_ObjectRegistry.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LKS_ObjectRegistry.h
5 | // LookinServer
6 | //
7 | // Created by Li Kai on 2019/4/21.
8 | // https://lookin.work
9 | //
10 |
11 | #import
12 |
13 | @interface LKS_ObjectRegistry : NSObject
14 |
15 | + (instancetype)sharedInstance;
16 |
17 | - (unsigned long)addObject:(NSObject *)object;
18 |
19 | - (NSObject *)objectWithOid:(unsigned long)oid;
20 |
21 | @end
22 |
23 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
24 |
--------------------------------------------------------------------------------
/Src/Main/Server/Others/LKS_ObjectRegistry.m:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LKS_ObjectRegistry.m
5 | // LookinServer
6 | //
7 | // Created by Li Kai on 2019/4/21.
8 | // https://lookin.work
9 | //
10 |
11 | #import "LKS_ObjectRegistry.h"
12 | #import
13 |
14 | @interface LKS_ObjectRegistry ()
15 |
16 | @property(nonatomic, strong) NSPointerArray *data;
17 |
18 | @end
19 |
20 | @implementation LKS_ObjectRegistry
21 |
22 | + (instancetype)sharedInstance {
23 | static dispatch_once_t onceToken;
24 | static LKS_ObjectRegistry *instance = nil;
25 | dispatch_once(&onceToken,^{
26 | instance = [[super allocWithZone:NULL] init];
27 | });
28 | return instance;
29 | }
30 |
31 | + (id)allocWithZone:(struct _NSZone *)zone{
32 | return [self sharedInstance];
33 | }
34 |
35 | - (instancetype)init {
36 | if (self = [super init]) {
37 | self.data = [NSPointerArray weakObjectsPointerArray];
38 | // index 为 0 用 Null 填充
39 | self.data.count = 1;
40 | }
41 | return self;
42 | }
43 |
44 | - (unsigned long)addObject:(NSObject *)object {
45 | if (!object) {
46 | return 0;
47 | }
48 | [self.data addPointer:(void *)object];
49 | return self.data.count - 1;
50 | }
51 |
52 | - (NSObject *)objectWithOid:(unsigned long)oid {
53 | if (self.data.count <= oid) {
54 | return nil;
55 | }
56 | id object = [self.data pointerAtIndex:oid];
57 | return object;
58 | }
59 |
60 | @end
61 |
62 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
63 |
--------------------------------------------------------------------------------
/Src/Main/Server/Others/LKS_TraceManager.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LKS_TraceManager.h
5 | // LookinServer
6 | //
7 | // Created by Li Kai on 2019/5/5.
8 | // https://lookin.work
9 | //
10 |
11 |
12 |
13 | #import
14 |
15 | @class LookinIvarTrace;
16 |
17 | @interface LKS_TraceManager : NSObject
18 |
19 | + (instancetype)sharedInstance;
20 |
21 | - (void)reload;
22 |
23 | - (void)addSearchTarger:(id)target;
24 |
25 | @end
26 |
27 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
28 |
--------------------------------------------------------------------------------
/Src/Main/Server/Others/LookinServerDefines.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LookinServer_PrefixHeader.pch
5 | // LookinServer
6 | //
7 | // Created by Li Kai on 2018/12/21.
8 | // https://lookin.work
9 | //
10 |
11 | #import "TargetConditionals.h"
12 | #import "LookinDefines.h"
13 | #import "LKS_Helper.h"
14 | #import "NSObject+LookinServer.h"
15 | #import "NSArray+Lookin.h"
16 | #import "NSSet+Lookin.h"
17 | #import "CALayer+Lookin.h"
18 | #import "UIView+LookinServer.h"
19 | #import "CALayer+LookinServer.h"
20 | #import "NSObject+Lookin.h"
21 | #import "NSString+Lookin.h"
22 |
23 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
24 |
--------------------------------------------------------------------------------
/Src/Main/Shared/Category/CALayer+Lookin.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // CALayer+Lookin.h
5 | // Lookin
6 | //
7 | // Created by Li Kai on 2018/8/4.
8 | // https://lookin.work
9 | //
10 |
11 | #import "LookinDefines.h"
12 |
13 |
14 |
15 | #import
16 |
17 | @interface CALayer (Lookin)
18 |
19 | - (void)lookin_removeImplicitAnimations;
20 |
21 | @end
22 |
23 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
24 |
--------------------------------------------------------------------------------
/Src/Main/Shared/Category/Color+Lookin.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // Color+Lookin.h
5 | // LookinShared
6 | //
7 | // Created by 李凯 on 2022/4/2.
8 | //
9 |
10 | #import
11 |
12 | #if TARGET_OS_IPHONE
13 |
14 | #elif TARGET_OS_MAC
15 |
16 | @interface NSColor (Lookin)
17 |
18 | + (instancetype)lookin_colorFromRGBAComponents:(NSArray *)components;
19 |
20 | - (NSArray *)lookin_rgbaComponents;
21 |
22 | @end
23 |
24 | #endif
25 |
26 |
27 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
28 |
--------------------------------------------------------------------------------
/Src/Main/Shared/Category/Color+Lookin.m:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // Color+Lookin.m
5 | // LookinShared
6 | //
7 | // Created by 李凯 on 2022/4/2.
8 | //
9 |
10 | #import "Image+Lookin.h"
11 |
12 | #if TARGET_OS_IPHONE
13 |
14 | #elif TARGET_OS_MAC
15 |
16 | @implementation NSColor (Lookin)
17 |
18 | + (instancetype)lookin_colorFromRGBAComponents:(NSArray *)components {
19 | if (!components) {
20 | return nil;
21 | }
22 | if (components.count != 4) {
23 | NSAssert(NO, @"");
24 | return nil;
25 | }
26 | NSColor *color = [NSColor colorWithRed:components[0].doubleValue green:components[1].doubleValue blue:components[2].doubleValue alpha:components[3].doubleValue];
27 | return color;
28 | }
29 |
30 | - (NSArray *)lookin_rgbaComponents {
31 | NSColor *rgbColor = [self colorUsingColorSpace:NSColorSpace.sRGBColorSpace];
32 | CGFloat r, g, b, a;
33 | [rgbColor getRed:&r green:&g blue:&b alpha:&a];
34 | NSArray *rgba = @[@(r), @(g), @(b), @(a)];
35 | return rgba;
36 | }
37 |
38 | @end
39 |
40 | #endif
41 |
42 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
43 |
--------------------------------------------------------------------------------
/Src/Main/Shared/Category/Image+Lookin.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // Image+Lookin.h
5 | // LookinShared
6 | //
7 | // Created by 李凯 on 2022/4/2.
8 | //
9 |
10 | #import
11 |
12 | #if TARGET_OS_IPHONE
13 |
14 | #elif TARGET_OS_MAC
15 |
16 | @interface NSImage (LookinClient)
17 |
18 | - (NSData *)lookin_data;
19 |
20 | @end
21 |
22 | #endif
23 |
24 |
25 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
26 |
--------------------------------------------------------------------------------
/Src/Main/Shared/Category/Image+Lookin.m:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // Image+Lookin.m
5 | // LookinShared
6 | //
7 | // Created by 李凯 on 2022/4/2.
8 | //
9 |
10 | #import "Image+Lookin.h"
11 |
12 | #if TARGET_OS_IPHONE
13 |
14 | #elif TARGET_OS_MAC
15 |
16 | @implementation NSImage (LookinClient)
17 |
18 | - (NSData *)lookin_data {
19 | return [self TIFFRepresentation];
20 | }
21 |
22 | @end
23 |
24 | #endif
25 |
26 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
27 |
--------------------------------------------------------------------------------
/Src/Main/Shared/Category/NSArray+Lookin.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // NSArray+Lookin.h
5 | // Lookin
6 | //
7 | // Created by Li Kai on 2018/9/3.
8 | // https://lookin.work
9 | //
10 |
11 | #import "LookinDefines.h"
12 |
13 |
14 |
15 | #import
16 | #import
17 |
18 | @interface NSArray<__covariant ValueType> (Lookin)
19 |
20 | /**
21 | 初始化一个新的 NSArray 并返回,新数组的长度为 count,如果当前数组长度比 count 小则会补充新元素(被补充的元素由 addBlock 返回),如果当前数组长度比 count 大则会舍弃多余的元素,被舍弃的元素会作为参数传入 removeBlock。最终,新数组的所有元素均会作为参数被传入 doBlock。
22 | */
23 | - (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));
24 |
25 | + (NSArray *)lookin_arrayWithCount:(NSUInteger)count block:(id (^)(NSUInteger idx))block;
26 |
27 | /**
28 | 检查 index 位置是否有元素存在
29 | */
30 | - (BOOL)lookin_hasIndex:(NSInteger)index;
31 |
32 | - (NSArray *)lookin_map:(id (^)(NSUInteger idx, ValueType value))block;
33 |
34 | - (NSArray *)lookin_filter:(BOOL (^)( ValueType obj))block;
35 |
36 | - (ValueType)lookin_firstFiltered:(BOOL (^)(ValueType obj))block;
37 |
38 | /// 返回最后一个 block 返回 YES 的元素
39 | - (ValueType)lookin_lastFiltered:(BOOL (^)(ValueType obj))block;
40 |
41 | - (id)lookin_reduce:(id (^)(id accumulator, NSUInteger idx, ValueType obj))block;
42 |
43 | - (CGFloat)lookin_reduceCGFloat:(CGFloat (^)(CGFloat accumulator, NSUInteger idx, ValueType obj))block initialAccumlator:(CGFloat)initialAccumlator;
44 | - (NSInteger)lookin_reduceInteger:(NSInteger (^)(NSInteger accumulator, NSUInteger idx, ValueType obj))block initialAccumlator:(NSInteger)initialAccumlator;
45 |
46 | - (BOOL)lookin_all:(BOOL (^)(ValueType obj))block;
47 |
48 | - (BOOL)lookin_any:(BOOL (^)(ValueType obj))block;
49 |
50 | - (NSArray *)lookin_arrayByRemovingObject:(ValueType)obj;
51 |
52 | - (NSArray *)lookin_nonredundantArray;
53 |
54 | - (ValueType)lookin_safeObjectAtIndex:(NSInteger)idx;
55 |
56 | /// 字符串长度从短到长,即 length 小的字符串的 idx 更小
57 | - (NSArray *)lookin_sortedArrayByStringLength;
58 |
59 | @end
60 |
61 | @interface NSMutableArray (Lookin)
62 |
63 | /**
64 | 如果当前数组长度比 count 小则会补充新元素(被补充的元素由 addBlock 返回),如果当前数组长度比 count 大则多余的元素会被作为参数传入 notDequeued。然后从 idx 为 0 算起,前 count 个元素会被作为参数传入 doBlock
65 | */
66 | - (void)lookin_dequeueWithCount:(NSUInteger)count add:(ValueType (^)(NSUInteger idx))addBlock notDequeued:(void (^)(NSUInteger idx, ValueType obj))notDequeuedBlock doNext:(void (^)(NSUInteger idx, ValueType obj))doBlock;
67 |
68 | - (void)lookin_removeObjectsPassingTest:(BOOL (^)(NSUInteger idx, ValueType obj))block;
69 |
70 | @end
71 |
72 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
73 |
--------------------------------------------------------------------------------
/Src/Main/Shared/Category/NSObject+Lookin.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // NSObject+Lookin.h
5 | // Lookin
6 | //
7 | // Created by Li Kai on 2018/12/22.
8 | // https://lookin.work
9 | //
10 |
11 | #import "LookinDefines.h"
12 |
13 |
14 |
15 | #import
16 | #import "LookinCodingValueType.h"
17 |
18 | @interface NSObject (Lookin)
19 |
20 | #pragma mark - Data Bind
21 |
22 | /**
23 | 给对象绑定上另一个对象以供后续取出使用,如果 object 传入 nil 则会清除该 key 之前绑定的对象
24 |
25 | @attention 被绑定的对象会被 strong 强引用
26 | @note 内部是使用 objc_setAssociatedObject / objc_getAssociatedObject 来实现
27 |
28 | @code
29 | - (UITableViewCell *)cellForIndexPath:(NSIndexPath *)indexPath {
30 | // 1)在这里给 button 绑定上 indexPath 对象
31 | [cell lookin_bindObject:indexPath forKey:@"indexPath"];
32 | }
33 |
34 | - (void)didTapButton:(UIButton *)button {
35 | // 2)在这里取出被点击的 button 的 indexPath 对象
36 | NSIndexPath *indexPathTapped = [button lookin_getBindObjectForKey:@"indexPath"];
37 | }
38 | @endcode
39 | */
40 | - (void)lookin_bindObject:(id)object forKey:(NSString *)key;
41 |
42 | /**
43 | 给对象绑定上另一个对象以供后续取出使用,但相比于 lookin_bindObject:forKey:,该方法不会 strong 强引用传入的 object
44 | */
45 | - (void)lookin_bindObjectWeakly:(id)object forKey:(NSString *)key;
46 |
47 | /**
48 | 取出之前使用 bind 方法绑定的对象
49 | */
50 | - (id)lookin_getBindObjectForKey:(NSString *)key;
51 |
52 | /**
53 | 给对象绑定上一个 double 值以供后续取出使用
54 | */
55 | - (void)lookin_bindDouble:(double)doubleValue forKey:(NSString *)key;
56 |
57 | /**
58 | 取出之前用 lookin_bindDouble:forKey: 绑定的值
59 | */
60 | - (double)lookin_getBindDoubleForKey:(NSString *)key;
61 |
62 | /**
63 | 给对象绑定上一个 BOOL 值以供后续取出使用
64 | */
65 | - (void)lookin_bindBOOL:(BOOL)boolValue forKey:(NSString *)key;
66 |
67 | /**
68 | 取出之前用 lookin_bindBOOL:forKey: 绑定的值
69 | */
70 | - (BOOL)lookin_getBindBOOLForKey:(NSString *)key;
71 |
72 | /**
73 | 给对象绑定上一个 long 值以供后续取出使用
74 | */
75 | - (void)lookin_bindLong:(long)longValue forKey:(NSString *)key;
76 |
77 | /**
78 | 取出之前用 lookin_bindLong:forKey: 绑定的值
79 | */
80 | - (long)lookin_getBindLongForKey:(NSString *)key;
81 |
82 | /**
83 | 给对象绑定上一个 CGPoint 值以供后续取出使用
84 | */
85 | - (void)lookin_bindPoint:(CGPoint)pointValue forKey:(NSString *)key;
86 |
87 | /**
88 | 取出之前用 lookin_bindPoint:forKey: 绑定的值
89 | */
90 | - (CGPoint)lookin_getBindPointForKey:(NSString *)key;
91 |
92 | /**
93 | 移除之前使用 bind 方法绑定的对象
94 | */
95 | - (void)lookin_clearBindForKey:(NSString *)key;
96 |
97 | @end
98 |
99 | @interface NSObject (Lookin_Coding)
100 |
101 | /// 会把 NSImage/UIImage 转换为 NSData,把 NSColor/UIColor 转换回 NSNumber 数组(rgba)
102 | - (id)lookin_encodedObjectWithType:(LookinCodingValueType)type;
103 | /// 会把 NSData 转换回 NSImage/UIImage,把 NSNumber 数组(rgba) 转换为 NSColor/UIColor
104 | - (id)lookin_decodedObjectWithType:(LookinCodingValueType)type;
105 |
106 | @end
107 |
108 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
109 |
--------------------------------------------------------------------------------
/Src/Main/Shared/Category/NSSet+Lookin.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // NSSet+Lookin.h
5 | // Lookin
6 | //
7 | // Created by Li Kai on 2019/1/13.
8 | // https://lookin.work
9 | //
10 |
11 | #import "LookinDefines.h"
12 |
13 |
14 |
15 | #import "TargetConditionals.h"
16 | #if TARGET_OS_IPHONE
17 | #import
18 | #elif TARGET_OS_MAC
19 | #import
20 | #endif
21 |
22 | @interface NSSet<__covariant ValueType> (Lookin)
23 |
24 | - (NSSet *)lookin_map:(id (^)(ValueType obj))block;
25 |
26 | - (ValueType)lookin_firstFiltered:(BOOL (^)(ValueType obj))block;
27 |
28 | - (NSSet *)lookin_filter:(BOOL (^)(ValueType obj))block;
29 |
30 |
31 | /**
32 | 是否有任何一个元素满足某条件
33 | @note 元素将被依次传入 block 里,如果任何一个 block 返回 YES,则该方法返回 YES。如果所有 block 均返回 NO,则该方法返回 NO。
34 | */
35 | - (BOOL)lookin_any:(BOOL (^)(ValueType obj))block;
36 |
37 | @end
38 |
39 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
40 |
--------------------------------------------------------------------------------
/Src/Main/Shared/Category/NSSet+Lookin.m:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // NSSet+Lookin.m
5 | // Lookin
6 | //
7 | // Created by Li Kai on 2019/1/13.
8 | // https://lookin.work
9 | //
10 |
11 |
12 |
13 | #import "NSSet+Lookin.h"
14 |
15 | @implementation NSSet (Lookin)
16 |
17 | - (NSSet *)lookin_map:(id (^)(id obj))block {
18 | if (!block) {
19 | NSAssert(NO, @"");
20 | return nil;
21 | }
22 |
23 | NSMutableSet *newSet = [NSMutableSet setWithCapacity:self.count];
24 | [self enumerateObjectsUsingBlock:^(id _Nonnull obj, BOOL * _Nonnull stop) {
25 | id newObj = block(obj);
26 | if (newObj) {
27 | [newSet addObject:newObj];
28 | }
29 | }];
30 | return [newSet copy];
31 | }
32 |
33 | - (id)lookin_firstFiltered:(BOOL (^)(id obj))block {
34 | if (!block) {
35 | NSAssert(NO, @"");
36 | return nil;
37 | }
38 |
39 | __block id targetObj = nil;
40 | [self enumerateObjectsUsingBlock:^(id _Nonnull obj, BOOL * _Nonnull stop) {
41 | if (block(obj)) {
42 | targetObj = obj;
43 | *stop = YES;
44 | }
45 | }];
46 | return targetObj;
47 | }
48 |
49 | - (NSSet *)lookin_filter:(BOOL (^)(id obj))block {
50 | if (!block) {
51 | NSAssert(NO, @"");
52 | return nil;
53 | }
54 |
55 | NSMutableSet *mSet = [NSMutableSet set];
56 | [self enumerateObjectsUsingBlock:^(id _Nonnull obj, BOOL * _Nonnull stop) {
57 | if (block(obj)) {
58 | [mSet addObject:obj];
59 | }
60 | }];
61 | return [mSet copy];
62 | }
63 |
64 | - (BOOL)lookin_any:(BOOL (^)(id obj))block {
65 | if (!block) {
66 | NSAssert(NO, @"");
67 | return NO;
68 | }
69 | __block BOOL boolValue = NO;
70 | [self enumerateObjectsUsingBlock:^(id _Nonnull obj, BOOL * _Nonnull stop) {
71 | if (block(obj)) {
72 | boolValue = YES;
73 | *stop = YES;
74 | }
75 | }];
76 | return boolValue;
77 | }
78 |
79 | @end
80 |
81 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
82 |
--------------------------------------------------------------------------------
/Src/Main/Shared/Category/NSString+Lookin.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // NSString+Lookin.h
5 | // Lookin
6 | //
7 | // Created by Li Kai on 2019/5/11.
8 | // https://lookin.work
9 | //
10 |
11 | #import "LookinDefines.h"
12 |
13 |
14 |
15 | #import
16 |
17 | @interface NSString (Lookin)
18 |
19 | /**
20 | 把 CGFloat 转成字符串,最多保留 3 位小数,转换后末尾的 0 会被删除
21 | 如:1.2341 => @"1.234", 2.1002 => @"2.1", 3.000 => @"3"
22 | */
23 | + (NSString *)lookin_stringFromDouble:(double)doubleValue decimal:(NSUInteger)decimal;
24 |
25 | + (NSString *)lookin_stringFromRect:(CGRect)rect;
26 |
27 | + (NSString *)lookin_stringFromInset:(LookinInsets)insets;
28 |
29 | + (NSString *)lookin_stringFromSize:(CGSize)size;
30 |
31 | + (NSString *)lookin_stringFromPoint:(CGPoint)point;
32 |
33 | + (NSString *)lookin_rgbaStringFromColor:(LookinColor *)color;
34 |
35 | - (NSString *)lookin_safeInitWithUTF8String:(const char *)string;
36 |
37 | /// 把 1.2.3 这种 String 版本号转换成数字,可用于大小比较,如 110205 代表 11.2.5 版本
38 | - (NSInteger)lookin_numbericOSVersion;
39 |
40 | @end
41 |
42 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
43 |
--------------------------------------------------------------------------------
/Src/Main/Shared/LookinAppInfo.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LookinAppInfo.h
5 | // qmuidemo
6 | //
7 | // Created by Li Kai on 2018/11/3.
8 | // Copyright © 2018 QMUI Team. All rights reserved.
9 | //
10 |
11 |
12 |
13 | #import "LookinDefines.h"
14 |
15 | typedef NS_ENUM(NSInteger, LookinAppInfoDevice) {
16 | LookinAppInfoDeviceSimulator, // 模拟器
17 | LookinAppInfoDeviceIPad, // iPad 真机
18 | LookinAppInfoDeviceOthers // 应该视为 iPhone 真机
19 | };
20 |
21 | @interface LookinAppInfo : NSObject
22 |
23 | /// 每次启动 app 时都会随机生成一个 appInfoIdentifier 直到 app 被 kill 掉
24 | @property(nonatomic, assign) NSUInteger appInfoIdentifier;
25 | /// mac 端应该先读取该属性,如果为 YES 则表示应该使用之前保存的旧 appInfo 对象即可
26 | @property(nonatomic, assign) BOOL shouldUseCache;
27 | /// LookinServer 的版本
28 | @property(nonatomic, assign) int serverVersion;
29 | /// 类似 "1.1.9",只在 1.2.3 以及之后的 LookinServer 版本里有值
30 | @property(nonatomic, assign) NSString *serverReadableVersion;
31 | /// 如果 iOS 侧使用了 SPM 或引入了 Swift Subspec,则该属性为 1
32 | /// 如果 iOS 侧没使用,则该属性为 -1
33 | /// 如果不知道,则该属性为 0
34 | @property(nonatomic, assign) int swiftEnabledInLookinServer;
35 | /// app 的当前截图
36 | @property(nonatomic, strong) LookinImage *screenshot;
37 | /// 可能为 nil,比如新建的 iOS 空项目
38 | @property(nonatomic, strong) LookinImage *appIcon;
39 | /// @"微信读书"
40 | @property(nonatomic, copy) NSString *appName;
41 | /// hughkli.lookin
42 | @property(nonatomic, copy) NSString *appBundleIdentifier;
43 | /// @"iPhone X"
44 | @property(nonatomic, copy) NSString *deviceDescription;
45 | /// @"12.1"
46 | @property(nonatomic, copy) NSString *osDescription;
47 | /// 返回 os 的主版本号,比如 iOS 12.1 的设备将返回 12,iOS 13.2.1 的设备将返回 13
48 | @property(nonatomic, assign) NSUInteger osMainVersion;
49 | /// 设备类型
50 | @property(nonatomic, assign) LookinAppInfoDevice deviceType;
51 | /// 屏幕的宽度
52 | @property(nonatomic, assign) double screenWidth;
53 | /// 屏幕的高度
54 | @property(nonatomic, assign) double screenHeight;
55 | /// 是几倍的屏幕
56 | @property(nonatomic, assign) double screenScale;
57 |
58 | - (BOOL)isEqualToAppInfo:(LookinAppInfo *)info;
59 |
60 | #if TARGET_OS_IPHONE
61 |
62 | + (LookinAppInfo *)currentInfoWithScreenshot:(BOOL)hasScreenshot icon:(BOOL)hasIcon localIdentifiers:(NSArray *)localIdentifiers;
63 |
64 | #else
65 |
66 | @property(nonatomic, assign) NSTimeInterval cachedTimestamp;
67 |
68 | #endif
69 |
70 | @end
71 |
72 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
73 |
--------------------------------------------------------------------------------
/Src/Main/Shared/LookinAttrType.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LookinAttrIdentifiers.h
5 | // Lookin
6 | //
7 | // Created by Li Kai on 2018/12/1.
8 | // https://lookin.work
9 | //
10 |
11 | /// 注意:新属性只能加到末尾,否则新旧版本搭配时可能有兼容问题
12 | typedef NS_ENUM(NSInteger, LookinAttrType) {
13 | LookinAttrTypeNone,
14 | LookinAttrTypeVoid,
15 | LookinAttrTypeChar,
16 | LookinAttrTypeInt,
17 | LookinAttrTypeShort,
18 | LookinAttrTypeLong,
19 | LookinAttrTypeLongLong,
20 | LookinAttrTypeUnsignedChar,
21 | LookinAttrTypeUnsignedInt,
22 | LookinAttrTypeUnsignedShort,
23 | LookinAttrTypeUnsignedLong,
24 | LookinAttrTypeUnsignedLongLong,
25 | LookinAttrTypeFloat,
26 | LookinAttrTypeDouble,
27 | LookinAttrTypeBOOL,
28 | LookinAttrTypeSel,
29 | LookinAttrTypeClass,
30 | LookinAttrTypeCGPoint,
31 | LookinAttrTypeCGVector,
32 | LookinAttrTypeCGSize,
33 | LookinAttrTypeCGRect,
34 | LookinAttrTypeCGAffineTransform,
35 | LookinAttrTypeUIEdgeInsets,
36 | LookinAttrTypeUIOffset,
37 | LookinAttrTypeNSString,
38 | LookinAttrTypeEnumInt,
39 | LookinAttrTypeEnumLong,
40 | /// value 实际为 RGBA 数组,即 @[NSNumber, NSNumber, NSNumber, NSNumber],NSNumber 范围是 0 ~ 1
41 | LookinAttrTypeUIColor,
42 | /// 业务需要根据具体的 AttrIdentifier 来解析
43 | LookinAttrTypeCustomObj,
44 |
45 | LookinAttrTypeEnumString,
46 | LookinAttrTypeShadow,
47 | LookinAttrTypeJson
48 | };
49 |
50 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
51 |
--------------------------------------------------------------------------------
/Src/Main/Shared/LookinAttribute.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LookinAttribute.h
5 | // qmuidemo
6 | //
7 | // Created by Li Kai on 2018/11/17.
8 | // Copyright © 2018 QMUI Team. All rights reserved.
9 | //
10 |
11 | #import "LookinAttrIdentifiers.h"
12 | #import "LookinCodingValueType.h"
13 | #import "LookinAttrType.h"
14 |
15 | @class LookinDisplayItem;
16 |
17 | @interface LookinAttribute : NSObject
18 |
19 | @property(nonatomic, copy) LookinAttrIdentifier identifier;
20 |
21 | /// 只有 Custom Attr 才有该属性
22 | @property(nonatomic, copy) NSString *displayTitle;
23 |
24 | /// 标识 value 的具体类型(如 double / NSString /...)
25 | @property(nonatomic, assign) LookinAttrType attrType;
26 |
27 | /// 具体的值,需配合 attrType 属性来解析它
28 | /// 对于 String、Color 等 attyType,该属性可能为 nil
29 | @property(nonatomic, strong) id value;
30 |
31 | /// 额外信息,大部分情况下它是 nil
32 | /// 当 attyType 为 LookinAttrTypeEnumString 时,extraValue 是一个 [String] 且保存了 allEnumCases
33 | @property(nonatomic, strong) id extraValue;
34 |
35 | /// 仅 Custom Attr 可能有该属性
36 | /// 对于有 retainedSetter 的 Custom Attr,它的 setter 会以 customSetterID 作为 key 被保存到 LKS_CustomAttrSetterManager 里,后续可以通过这个 uniqueID 重新把 setter 从 LKS_CustomAttrSetterManager 里取出来并调用
37 | @property(nonatomic, copy) NSString *customSetterID;
38 |
39 | #pragma mark - 以下属性不会参与 encode/decode
40 |
41 | /// 标识该 LookinAttribute 对象隶属于哪一个 LookinDisplayItem
42 | @property(nonatomic, weak) LookinDisplayItem *targetDisplayItem;
43 |
44 | - (BOOL)isUserCustom;
45 |
46 | @end
47 |
48 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
49 |
--------------------------------------------------------------------------------
/Src/Main/Shared/LookinAttribute.m:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LookinAttribute.m
5 | // qmuidemo
6 | //
7 | // Created by Li Kai on 2018/11/17.
8 | // Copyright © 2018 QMUI Team. All rights reserved.
9 | //
10 |
11 |
12 |
13 | #import "LookinAttribute.h"
14 | #import "LookinDisplayItem.h"
15 |
16 | @implementation LookinAttribute
17 |
18 | #pragma mark -
19 |
20 | - (id)copyWithZone:(NSZone *)zone {
21 | LookinAttribute *newAttr = [[LookinAttribute allocWithZone:zone] init];
22 | newAttr.identifier = self.identifier;
23 | newAttr.displayTitle = self.displayTitle;
24 | newAttr.value = self.value;
25 | newAttr.attrType = self.attrType;
26 | newAttr.extraValue = self.extraValue;
27 | newAttr.customSetterID = self.customSetterID;
28 | return newAttr;
29 | }
30 |
31 | #pragma mark -
32 |
33 | - (void)encodeWithCoder:(NSCoder *)aCoder {
34 | [aCoder encodeObject:self.displayTitle forKey:@"displayTitle"];
35 | [aCoder encodeObject:self.identifier forKey:@"identifier"];
36 | [aCoder encodeInteger:self.attrType forKey:@"attrType"];
37 | [aCoder encodeObject:self.value forKey:@"value"];
38 | [aCoder encodeObject:self.extraValue forKey:@"extraValue"];
39 | [aCoder encodeObject:self.customSetterID forKey:@"customSetterID"];
40 | }
41 |
42 | - (instancetype)initWithCoder:(NSCoder *)aDecoder {
43 | if (self = [super init]) {
44 | self.displayTitle = [aDecoder decodeObjectForKey:@"displayTitle"];
45 | self.identifier = [aDecoder decodeObjectForKey:@"identifier"];
46 | self.attrType = [aDecoder decodeIntegerForKey:@"attrType"];
47 | self.value = [aDecoder decodeObjectForKey:@"value"];
48 | self.extraValue = [aDecoder decodeObjectForKey:@"extraValue"];
49 | self.customSetterID = [aDecoder decodeObjectForKey:@"customSetterID"];
50 | }
51 | return self;
52 | }
53 |
54 | + (BOOL)supportsSecureCoding {
55 | return YES;
56 | }
57 |
58 | - (BOOL)isUserCustom {
59 | return [self.identifier isEqualToString:LookinAttr_UserCustom];
60 | }
61 |
62 | @end
63 |
64 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
65 |
--------------------------------------------------------------------------------
/Src/Main/Shared/LookinAttributeModification.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LookinAttributeModification.h
5 | // Lookin
6 | //
7 | // Created by Li Kai on 2018/11/20.
8 | // https://lookin.work
9 | //
10 |
11 |
12 |
13 | #import
14 | #import "LookinAttrType.h"
15 |
16 | @interface LookinAttributeModification : NSObject
17 |
18 | @property(nonatomic, assign) unsigned long targetOid;
19 |
20 | @property(nonatomic, assign) SEL setterSelector;
21 | @property(nonatomic, assign) SEL getterSelector;
22 |
23 | @property(nonatomic, assign) LookinAttrType attrType;
24 | @property(nonatomic, strong) id value;
25 |
26 | /// 1.0.4 开始加入这个参数
27 | @property(nonatomic, copy) NSString *clientReadableVersion;
28 |
29 | @end
30 |
31 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
32 |
--------------------------------------------------------------------------------
/Src/Main/Shared/LookinAttributeModification.m:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LookinAttributeModification.m
5 | // Lookin
6 | //
7 | // Created by Li Kai on 2018/11/20.
8 | // https://lookin.work
9 | //
10 |
11 | #import "LookinAttributeModification.h"
12 |
13 | @implementation LookinAttributeModification
14 |
15 | - (void)encodeWithCoder:(NSCoder *)aCoder {
16 | [aCoder encodeObject:@(self.targetOid) forKey:@"targetOid"];
17 | [aCoder encodeObject:NSStringFromSelector(self.setterSelector) forKey:@"setterSelector"];
18 | [aCoder encodeInteger:self.attrType forKey:@"attrType"];
19 | [aCoder encodeObject:self.value forKey:@"value"];
20 | [aCoder encodeObject:self.clientReadableVersion forKey:@"clientReadableVersion"];
21 | }
22 |
23 | - (instancetype)initWithCoder:(NSCoder *)aDecoder {
24 | if (self = [super init]) {
25 | self.targetOid = [[aDecoder decodeObjectForKey:@"targetOid"] unsignedLongValue];
26 | self.setterSelector = NSSelectorFromString([aDecoder decodeObjectForKey:@"setterSelector"]);
27 | self.attrType = [aDecoder decodeIntegerForKey:@"attrType"];
28 | self.value = [aDecoder decodeObjectForKey:@"value"];
29 | self.clientReadableVersion = [aDecoder decodeObjectForKey:@"clientReadableVersion"];
30 | }
31 | return self;
32 | }
33 |
34 | + (BOOL)supportsSecureCoding {
35 | return YES;
36 | }
37 |
38 | @end
39 |
40 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
41 |
--------------------------------------------------------------------------------
/Src/Main/Shared/LookinAttributesGroup.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LookinAttributesGroup.h
5 | // Lookin
6 | //
7 | // Created by Li Kai on 2018/11/19.
8 | // https://lookin.work
9 | //
10 |
11 |
12 |
13 | #import
14 | #import "LookinAttrIdentifiers.h"
15 |
16 | @class LookinAttributesSection;
17 |
18 | /**
19 | In Lookin, a LookinAttributesGroup instance will be rendered as a property card.
20 |
21 | When isUserCustom is false: two LookinAttributesGroup instances will be regard as equal when they has the same LookinAttrGroupIdentifier.
22 | When isUserCustom is true: two LookinAttributesGroup instances will be regard as equal when they has the same title.
23 | 当 isUserCustom 为 false 时:若两个 attrGroup 有相同的 LookinAttrGroupIdentifier,则 isEqual: 返回 YES
24 | */
25 | @interface LookinAttributesGroup : NSObject
26 |
27 | /// 只有在 identifier 为 custom 时,才存在该值
28 | @property(nonatomic, copy) NSString *userCustomTitle;
29 |
30 | @property(nonatomic, copy) LookinAttrGroupIdentifier identifier;
31 |
32 | @property(nonatomic, copy) NSArray *attrSections;
33 |
34 | /// 如果是 custom 则返回 userCustomTitle,如果不是 custom 则返回 identifier
35 | - (NSString *)uniqueKey;
36 |
37 | - (BOOL)isUserCustom;
38 |
39 | @end
40 |
41 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
42 |
--------------------------------------------------------------------------------
/Src/Main/Shared/LookinAttributesGroup.m:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LookinAttributesGroup.m
5 | // Lookin
6 | //
7 | // Created by Li Kai on 2018/11/19.
8 | // https://lookin.work
9 | //
10 |
11 |
12 |
13 | #import "LookinAttributesGroup.h"
14 | #import "LookinAttribute.h"
15 | #import "LookinAttributesSection.h"
16 | #import "LookinDashboardBlueprint.h"
17 | #import "NSArray+Lookin.h"
18 |
19 | @implementation LookinAttributesGroup
20 |
21 | #pragma mark -
22 |
23 | - (id)copyWithZone:(NSZone *)zone {
24 | LookinAttributesGroup *newGroup = [[LookinAttributesGroup allocWithZone:zone] init];
25 | newGroup.userCustomTitle = self.userCustomTitle;
26 | newGroup.identifier = self.identifier;
27 | newGroup.attrSections = [self.attrSections lookin_map:^id(NSUInteger idx, LookinAttributesSection *value) {
28 | return value.copy;
29 | }];
30 | return newGroup;
31 | }
32 |
33 | #pragma mark -
34 |
35 | - (void)encodeWithCoder:(NSCoder *)aCoder {
36 | [aCoder encodeObject:self.userCustomTitle forKey:@"userCustomTitle"];
37 | [aCoder encodeObject:self.identifier forKey:@"identifier"];
38 | [aCoder encodeObject:self.attrSections forKey:@"attrSections"];
39 | }
40 |
41 | - (instancetype)initWithCoder:(NSCoder *)aDecoder {
42 | if (self = [super init]) {
43 | self.userCustomTitle = [aDecoder decodeObjectForKey:@"userCustomTitle"];
44 | self.identifier = [aDecoder decodeObjectForKey:@"identifier"];
45 | self.attrSections = [aDecoder decodeObjectForKey:@"attrSections"];
46 | }
47 | return self;
48 | }
49 |
50 | - (NSUInteger)hash {
51 | return self.uniqueKey.hash;
52 | }
53 |
54 | - (BOOL)isEqual:(id)object {
55 | if (self == object) {
56 | return YES;
57 | }
58 | if (![object isKindOfClass:[LookinAttributesGroup class]]) {
59 | return NO;
60 | }
61 | LookinAttributesGroup *targetObject = object;
62 |
63 | if (![self.identifier isEqualToString:targetObject.identifier]) {
64 | return false;
65 | }
66 | if ([self.identifier isEqualToString:LookinAttrGroup_UserCustom]) {
67 | BOOL ret = [self.userCustomTitle isEqualToString:targetObject.userCustomTitle];
68 | return ret;
69 | } else {
70 | return true;
71 | }
72 | }
73 |
74 | + (BOOL)supportsSecureCoding {
75 | return YES;
76 | }
77 |
78 | - (NSString *)uniqueKey {
79 | if ([self.identifier isEqualToString:LookinAttrGroup_UserCustom]) {
80 | return self.userCustomTitle;
81 | } else {
82 | return self.identifier;
83 | }
84 | }
85 |
86 | - (BOOL)isUserCustom {
87 | return [self.identifier isEqualToString:LookinAttrSec_UserCustom];
88 | }
89 |
90 | @end
91 |
92 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
93 |
--------------------------------------------------------------------------------
/Src/Main/Shared/LookinAttributesSection.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LookinAttributesSection.h
5 | // Lookin
6 | //
7 | // Created by Li Kai on 2019/3/2.
8 | // https://lookin.work
9 | //
10 |
11 |
12 |
13 | #import
14 | #import "LookinAttrIdentifiers.h"
15 |
16 | @class LookinAttribute;
17 |
18 | typedef NS_ENUM (NSInteger, LookinAttributesSectionStyle) {
19 | LookinAttributesSectionStyleDefault, // 每个 attr 独占一行
20 | LookinAttributesSectionStyle0, // frame 等卡片使用,前 4 个 attr 每行两个,之后每个 attr 在同一排,每个宽度为 1/4
21 | LookinAttributesSectionStyle1, // 第一个 attr 在第一排靠左,第二个 attr 在第一排靠右,之后的 attr 每个独占一行
22 | LookinAttributesSectionStyle2 // 第一排独占一行,剩下的在同一行且均分宽度
23 | };
24 |
25 | @interface LookinAttributesSection : NSObject
26 |
27 | @property(nonatomic, copy) LookinAttrSectionIdentifier identifier;
28 |
29 | @property(nonatomic, copy) NSArray *attributes;
30 |
31 | - (BOOL)isUserCustom;
32 |
33 | @end
34 |
35 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
36 |
--------------------------------------------------------------------------------
/Src/Main/Shared/LookinAttributesSection.m:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LookinAttributesSection.m
5 | // Lookin
6 | //
7 | // Created by Li Kai on 2019/3/2.
8 | // https://lookin.work
9 | //
10 |
11 |
12 |
13 | #import "LookinAttributesSection.h"
14 | #import "LookinAttribute.h"
15 |
16 | #import "NSArray+Lookin.h"
17 |
18 | @implementation LookinAttributesSection
19 |
20 | #pragma mark -
21 |
22 | - (id)copyWithZone:(NSZone *)zone {
23 | LookinAttributesSection *newSection = [[LookinAttributesSection allocWithZone:zone] init];
24 | newSection.identifier = self.identifier;
25 | newSection.attributes = [self.attributes lookin_map:^id(NSUInteger idx, LookinAttribute *value) {
26 | return value.copy;
27 | }];
28 | return newSection;
29 | }
30 |
31 | #pragma mark -
32 |
33 | - (void)encodeWithCoder:(NSCoder *)aCoder {
34 | [aCoder encodeObject:self.identifier forKey:@"identifier"];
35 | [aCoder encodeObject:self.attributes forKey:@"attributes"];
36 | }
37 |
38 | - (instancetype)initWithCoder:(NSCoder *)aDecoder {
39 | if (self = [super init]) {
40 | self.identifier = [aDecoder decodeObjectForKey:@"identifier"];
41 | self.attributes = [aDecoder decodeObjectForKey:@"attributes"];
42 | }
43 | return self;
44 | }
45 |
46 | + (BOOL)supportsSecureCoding {
47 | return YES;
48 | }
49 |
50 | - (BOOL)isUserCustom {
51 | return [self.identifier isEqualToString:LookinAttrSec_UserCustom];
52 | }
53 |
54 | @end
55 |
56 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
57 |
--------------------------------------------------------------------------------
/Src/Main/Shared/LookinAutoLayoutConstraint.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LookinAutoLayoutConstraint.h
5 | // Lookin
6 | //
7 | // Created by Li Kai on 2019/9/28.
8 | // https://lookin.work
9 | //
10 |
11 |
12 |
13 | #import "LookinDefines.h"
14 |
15 | @class LookinObject;
16 |
17 | typedef NS_ENUM(NSInteger, LookinConstraintItemType) {
18 | LookinConstraintItemTypeUnknown,
19 | LookinConstraintItemTypeNil,
20 | LookinConstraintItemTypeView,
21 | LookinConstraintItemTypeSelf,
22 | LookinConstraintItemTypeSuper,
23 | LookinConstraintItemTypeLayoutGuide
24 | };
25 |
26 | @interface LookinAutoLayoutConstraint : NSObject
27 |
28 | #if TARGET_OS_IPHONE
29 | + (instancetype)instanceFromNSConstraint:(NSLayoutConstraint *)constraint isEffective:(BOOL)isEffective firstItemType:(LookinConstraintItemType)firstItemType secondItemType:(LookinConstraintItemType)secondItemType;
30 | #endif
31 |
32 | @property(nonatomic, assign) BOOL effective;
33 | @property(nonatomic, assign) BOOL active;
34 | @property(nonatomic, assign) BOOL shouldBeArchived;
35 | @property(nonatomic, strong) LookinObject *firstItem;
36 | @property(nonatomic, assign) LookinConstraintItemType firstItemType;
37 | /// iOS 里的 NSLayoutAttribute,注意 iOS 和 macOS 虽然都有 NSLayoutAttribute 但是 value 非常不同,因此这里使用 NSInteger 避免混淆
38 | @property(nonatomic, assign) NSInteger firstAttribute;
39 | @property(nonatomic, assign) NSLayoutRelation relation;
40 | @property(nonatomic, strong) LookinObject *secondItem;
41 | @property(nonatomic, assign) LookinConstraintItemType secondItemType;
42 | /// iOS 里的 NSLayoutAttribute,注意 iOS 和 macOS 虽然都有 NSLayoutAttribute 但是 value 非常不同,因此这里使用 NSInteger 避免混淆
43 | @property(nonatomic, assign) NSInteger secondAttribute;
44 | @property(nonatomic, assign) CGFloat multiplier;
45 | @property(nonatomic, assign) CGFloat constant;
46 | @property(nonatomic, assign) CGFloat priority;
47 | @property(nonatomic, copy) NSString *identifier;
48 |
49 | @end
50 |
51 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
52 |
--------------------------------------------------------------------------------
/Src/Main/Shared/LookinCodingValueType.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LookinCodingValueType.h
5 | // Lookin
6 | //
7 | // Created by Li Kai on 2019/2/13.
8 | // https://lookin.work
9 | //
10 |
11 | typedef NS_ENUM(NSInteger, LookinCodingValueType) {
12 | LookinCodingValueTypeUnknown,
13 | LookinCodingValueTypeChar,
14 | LookinCodingValueTypeDouble,
15 | LookinCodingValueTypeFloat,
16 | LookinCodingValueTypeLongLong,
17 | // LookinCodingValueTypePoint,
18 | // LookinCodingValueTypeString,
19 | // LookinCodingValueTypeStringArray,
20 | // LookinCodingValueTypeEdgeInsets,
21 | // LookinCodingValueTypeRect,
22 | LookinCodingValueTypeBOOL,
23 | // LookinCodingValueTypeSize,
24 | LookinCodingValueTypeColor,
25 | LookinCodingValueTypeEnum,
26 | // LookinCodingValueTypeRange,
27 | LookinCodingValueTypeImage
28 | };
29 |
30 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
31 |
--------------------------------------------------------------------------------
/Src/Main/Shared/LookinConnectionAttachment.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LookinConnectionAttachment.h
5 | // Lookin
6 | //
7 | // Created by Li Kai on 2019/2/15.
8 | // https://lookin.work
9 | //
10 |
11 |
12 |
13 | #import
14 | #import "LookinCodingValueType.h"
15 |
16 | @interface LookinConnectionAttachment : NSObject
17 |
18 | @property(nonatomic, assign) LookinCodingValueType dataType;
19 |
20 | @property(nonatomic, strong) id data;
21 |
22 | @end
23 |
24 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
25 |
--------------------------------------------------------------------------------
/Src/Main/Shared/LookinConnectionAttachment.m:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LookinConnectionAttachment.m
5 | // Lookin
6 | //
7 | // Created by Li Kai on 2019/2/15.
8 | // https://lookin.work
9 | //
10 |
11 |
12 |
13 | #import "LookinConnectionAttachment.h"
14 | #import "LookinDefines.h"
15 | #import "NSObject+Lookin.h"
16 |
17 | static NSString * const Key_Data = @"0";
18 | static NSString * const Key_DataType = @"1";
19 |
20 | @interface LookinConnectionAttachment ()
21 |
22 | @end
23 |
24 | @implementation LookinConnectionAttachment
25 |
26 | - (instancetype)init {
27 | if (self = [super init]) {
28 | }
29 | return self;
30 | }
31 |
32 | - (void)encodeWithCoder:(NSCoder *)aCoder {
33 |
34 | [aCoder encodeObject:[self.data lookin_encodedObjectWithType:self.dataType] forKey:Key_Data];
35 | [aCoder encodeInteger:self.dataType forKey:Key_DataType];
36 | }
37 |
38 | - (instancetype)initWithCoder:(NSCoder *)aDecoder {
39 | if (self = [super init]) {
40 | self.dataType = [aDecoder decodeIntegerForKey:Key_DataType];
41 | self.data = [[aDecoder decodeObjectForKey:Key_Data] lookin_decodedObjectWithType:self.dataType];
42 | }
43 | return self;
44 | }
45 |
46 | + (BOOL)supportsSecureCoding {
47 | return YES;
48 | }
49 |
50 | @end
51 |
52 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
53 |
--------------------------------------------------------------------------------
/Src/Main/Shared/LookinConnectionResponseAttachment.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LookinConnectionResponse.h
5 | // Lookin
6 | //
7 | // Created by Li Kai on 2019/1/15.
8 | // https://lookin.work
9 | //
10 |
11 |
12 |
13 | #import
14 | #import "LookinConnectionAttachment.h"
15 |
16 | @interface LookinConnectionResponseAttachment : LookinConnectionAttachment
17 |
18 | + (instancetype)attachmentWithError:(NSError *)error;
19 |
20 | @property(nonatomic, assign) int lookinServerVersion;
21 |
22 | @property(nonatomic, strong) NSError *error;
23 |
24 | /// 如果为 YES,则表示 app 正处于后台模式,默认为 NO
25 | @property(nonatomic, assign) BOOL appIsInBackground;
26 |
27 | /**
28 | dataTotalCount 为 0 时表示仅有这一个 response,默认为 0
29 | dataTotalCount 大于 0 时表示可能有多个 response,当所有 response 的 currentDataCount 的总和大于 dataTotalCount 即表示所有 response 已接收完毕
30 | */
31 | @property(nonatomic, assign) NSUInteger dataTotalCount;
32 | @property(nonatomic, assign) NSUInteger currentDataCount;
33 |
34 | @end
35 |
36 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
37 |
--------------------------------------------------------------------------------
/Src/Main/Shared/LookinConnectionResponseAttachment.m:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LookinConnectionResponse.m
5 | // Lookin
6 | //
7 | // Created by Li Kai on 2019/1/15.
8 | // https://lookin.work
9 | //
10 |
11 |
12 |
13 | #import "LookinConnectionResponseAttachment.h"
14 | #import "LookinDefines.h"
15 |
16 | @interface LookinConnectionResponseAttachment ()
17 |
18 | @end
19 |
20 | @implementation LookinConnectionResponseAttachment
21 |
22 | - (void)encodeWithCoder:(NSCoder *)aCoder {
23 | [super encodeWithCoder:aCoder];
24 | [aCoder encodeInt:self.lookinServerVersion forKey:@"lookinServerVersion"];
25 | [aCoder encodeObject:self.error forKey:@"error"];
26 | [aCoder encodeObject:@(self.dataTotalCount) forKey:@"dataTotalCount"];
27 | [aCoder encodeObject:@(self.currentDataCount) forKey:@"currentDataCount"];
28 | [aCoder encodeBool:self.appIsInBackground forKey:@"appIsInBackground"];
29 | }
30 |
31 | - (instancetype)init {
32 | if (self = [super init]) {
33 | self.lookinServerVersion = LOOKIN_SERVER_VERSION;
34 | self.dataTotalCount = 0;
35 | }
36 | return self;
37 | }
38 |
39 | - (instancetype)initWithCoder:(NSCoder *)aDecoder {
40 | if (self = [super initWithCoder:aDecoder]) {
41 | self.lookinServerVersion = [aDecoder decodeIntForKey:@"lookinServerVersion"];
42 | self.error = [aDecoder decodeObjectForKey:@"error"];
43 | self.dataTotalCount = [[aDecoder decodeObjectForKey:@"dataTotalCount"] unsignedIntegerValue];
44 | self.currentDataCount = [[aDecoder decodeObjectForKey:@"currentDataCount"] unsignedIntegerValue];
45 | self.appIsInBackground = [aDecoder decodeBoolForKey:@"appIsInBackground"];
46 | }
47 | return self;
48 | }
49 |
50 | + (BOOL)supportsSecureCoding {
51 | return YES;
52 | }
53 |
54 | + (instancetype)attachmentWithError:(NSError *)error {
55 | LookinConnectionResponseAttachment *attachment = [LookinConnectionResponseAttachment new];
56 | attachment.error = error;
57 | return attachment;
58 | }
59 |
60 | @end
61 |
62 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
63 |
--------------------------------------------------------------------------------
/Src/Main/Shared/LookinCustomAttrModification.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 | //
3 | // LookinCustomAttrModification.h
4 | // LookinShared
5 | //
6 | // Created by likaimacbookhome on 2023/11/4.
7 | //
8 |
9 | #import
10 | #import "LookinAttrType.h"
11 |
12 | @interface LookinCustomAttrModification : NSObject
13 |
14 | @property(nonatomic, assign) LookinAttrType attrType;
15 | @property(nonatomic, copy) NSString *customSetterID;
16 | @property(nonatomic, strong) id value;
17 |
18 | @end
19 |
20 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
21 |
--------------------------------------------------------------------------------
/Src/Main/Shared/LookinCustomAttrModification.m:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 | //
3 | // LookinCustomAttrModification.m
4 | // LookinShared
5 | //
6 | // Created by likaimacbookhome on 2023/11/4.
7 | //
8 |
9 | #import "LookinCustomAttrModification.h"
10 |
11 | @implementation LookinCustomAttrModification
12 |
13 | - (void)encodeWithCoder:(NSCoder *)aCoder {
14 | [aCoder encodeInteger:self.attrType forKey:@"attrType"];
15 | [aCoder encodeObject:self.value forKey:@"value"];
16 | [aCoder encodeObject:self.customSetterID forKey:@"customSetterID"];
17 | }
18 |
19 | - (instancetype)initWithCoder:(NSCoder *)aDecoder {
20 | if (self = [super init]) {
21 | self.attrType = [aDecoder decodeIntegerForKey:@"attrType"];
22 | self.value = [aDecoder decodeObjectForKey:@"value"];
23 | self.customSetterID = [aDecoder decodeObjectForKey:@"customSetterID"];
24 | }
25 | return self;
26 | }
27 |
28 | + (BOOL)supportsSecureCoding {
29 | return YES;
30 | }
31 |
32 | @end
33 |
34 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
35 |
--------------------------------------------------------------------------------
/Src/Main/Shared/LookinCustomDisplayItemInfo.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 | //
3 | // LookinCustomDisplayItemInfo.h
4 | // LookinServer
5 | //
6 | // Created by likai.123 on 2023/11/1.
7 | //
8 |
9 | #import
10 |
11 | @interface LookinCustomDisplayItemInfo : NSObject
12 |
13 | /// 该属性可能有值(CGRect)也可能是 nil(nil 时则表示无图像)
14 | @property(nonatomic, strong) NSValue *frameInWindow;
15 | @property(nonatomic, copy) NSString *title;
16 | @property(nonatomic, copy) NSString *subtitle;
17 | @property(nonatomic, copy) NSString *danceuiSource;
18 |
19 | @end
20 |
21 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
22 |
--------------------------------------------------------------------------------
/Src/Main/Shared/LookinCustomDisplayItemInfo.m:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LookinCustomDisplayItemInfo.m
5 | // LookinServer
6 | //
7 | // Created by likai.123 on 2023/11/1.
8 | //
9 |
10 | #import "LookinCustomDisplayItemInfo.h"
11 | #if TARGET_OS_IPHONE
12 | #import
13 | #endif
14 |
15 | @implementation LookinCustomDisplayItemInfo
16 |
17 | - (id)copyWithZone:(NSZone *)zone {
18 | LookinCustomDisplayItemInfo *newInstance = [[LookinCustomDisplayItemInfo allocWithZone:zone] init];
19 |
20 | if (self.frameInWindow) {
21 | #if TARGET_OS_IPHONE
22 | CGRect rect = [self.frameInWindow CGRectValue];
23 | newInstance.frameInWindow = [NSValue valueWithCGRect:rect];
24 | #elif TARGET_OS_MAC
25 | CGRect rect = [self.frameInWindow rectValue];
26 | newInstance.frameInWindow = [NSValue valueWithRect:rect];
27 | #endif
28 | }
29 | newInstance.title = self.title;
30 | newInstance.subtitle = self.subtitle;
31 | newInstance.danceuiSource = self.danceuiSource;
32 |
33 | return newInstance;
34 | }
35 |
36 | - (void)encodeWithCoder:(NSCoder *)aCoder {
37 | [aCoder encodeObject:self.frameInWindow forKey:@"frameInWindow"];
38 | [aCoder encodeObject:self.title forKey:@"title"];
39 | [aCoder encodeObject:self.subtitle forKey:@"subtitle"];
40 | [aCoder encodeObject:self.danceuiSource forKey:@"danceuiSource"];
41 | }
42 |
43 | - (instancetype)initWithCoder:(NSCoder *)aDecoder {
44 | if (self = [super init]) {
45 | self.frameInWindow = [aDecoder decodeObjectForKey:@"frameInWindow"];
46 | self.title = [aDecoder decodeObjectForKey:@"title"];
47 | self.subtitle = [aDecoder decodeObjectForKey:@"subtitle"];
48 | self.danceuiSource = [aDecoder decodeObjectForKey:@"danceuiSource"];
49 | }
50 | return self;
51 | }
52 |
53 | + (BOOL)supportsSecureCoding {
54 | return YES;
55 | }
56 |
57 | @end
58 |
59 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
60 |
--------------------------------------------------------------------------------
/Src/Main/Shared/LookinDashboardBlueprint.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LookinDashboardBlueprint.h
5 | // Lookin
6 | //
7 | // Created by Li Kai on 2019/6/5.
8 | // https://lookin.work
9 | //
10 |
11 |
12 |
13 | #import
14 | #import "LookinAttrIdentifiers.h"
15 | #import "LookinAttrType.h"
16 |
17 | /**
18 | 该对象定义了:
19 | - 每一个 Attr 的信息
20 | - 哪些 GroupID, SectionID, AttrID 是合法的
21 | - 这些 ID 的父子顺序,比如 LookinAttrGroup_Frame 包含哪些 Section
22 | - 这些 ID 展示顺序(比如哪个 Group 在前、哪个 Group 在后)
23 | */
24 | @interface LookinDashboardBlueprint : NSObject
25 |
26 | + (NSArray *)groupIDs;
27 |
28 | + (NSArray *)sectionIDsForGroupID:(LookinAttrGroupIdentifier)groupID;
29 |
30 | + (NSArray *)attrIDsForSectionID:(LookinAttrSectionIdentifier)sectionID;
31 |
32 | /// 返回包含目标 attr 的 groupID 和 sectionID
33 | + (void)getHostGroupID:(inout LookinAttrGroupIdentifier *)groupID sectionID:(inout LookinAttrSectionIdentifier *)sectionID fromAttrID:(LookinAttrIdentifier)attrID;
34 |
35 | /// 返回某个 group 的标题
36 | + (NSString *)groupTitleWithGroupID:(LookinAttrGroupIdentifier)groupID;
37 |
38 | /// 返回某个 section 的标题,nil 则表示不显示标题
39 | + (NSString *)sectionTitleWithSectionID:(LookinAttrSectionIdentifier)secID;
40 |
41 | /// 当某个 LookinAttribute 确定是 NSObject 类型时,该方法返回它具体是什么对象,比如 UIColor 等
42 | + (LookinAttrType)objectAttrTypeWithAttrID:(LookinAttrIdentifier)attrID;
43 |
44 | /// 返回某个 LookinAttribute 代表的属性是哪一个类拥有的,比如 LookinAttrSec_UILabel_TextColor 是 UILabel 才有的
45 | + (NSString *)classNameWithAttrID:(LookinAttrIdentifier)attrID;
46 |
47 | /// 一个 attr 要么属于 UIView 要么属于 CALayer,如果它属于 UIView 那么该方法返回 YES
48 | + (BOOL)isUIViewPropertyWithAttrID:(LookinAttrIdentifier)attrID;
49 |
50 | /// 如果某个 attribute 是 enum,则这里会返回相应的 enum 的名称(如 @"NSTextAlignment"),进而可通过这个名称查询可用的枚举值列表
51 | + (NSString *)enumListNameWithAttrID:(LookinAttrIdentifier)attrID;
52 |
53 | /// 如果返回 YES,则说明用户在 Lookin 里修改了该 Attribute 的值后,应该重新拉取和更新相关图层的位置、截图等信息
54 | + (BOOL)needPatchAfterModificationWithAttrID:(LookinAttrIdentifier)attrID;
55 |
56 | /// 完整的名字
57 | + (NSString *)fullTitleWithAttrID:(LookinAttrIdentifier)attrID;
58 |
59 | /// 在某些 textField 和 checkbox 里会显示这里返回的 title
60 | + (NSString *)briefTitleWithAttrID:(LookinAttrIdentifier)attrID;
61 |
62 | /// 获取 getter 方法
63 | + (SEL)getterWithAttrID:(LookinAttrIdentifier)attrID;
64 |
65 | /// 获取 setter 方法
66 | + (SEL)setterWithAttrID:(LookinAttrIdentifier)attrID;
67 |
68 | /// 获取 “hideIfNil” 的值。如果为 YES,则当读取 getter 获取的 value 为 nil 时,Lookin 不会传输该 attr
69 | /// 如果为 NO,则即使 value 为 nil 也会传输(比如 label 的 text 属性,即使它是 nil 我们也要显示,所以它的 hideIfNil 应该为 NO)
70 | + (BOOL)hideIfNilWithAttrID:(LookinAttrIdentifier)attrID;
71 |
72 | /// 该属性需要的最低的 iOS 版本,比如 safeAreaInsets 从 iOS 11.0 开始出现,则该方法返回 11,如果返回 0 则表示不限制 iOS 版本(注意 Lookin 项目仅支持 iOS 8.0+)
73 | + (NSInteger)minAvailableOSVersionWithAttrID:(LookinAttrIdentifier)attrID;
74 |
75 | @end
76 |
77 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
78 |
--------------------------------------------------------------------------------
/Src/Main/Shared/LookinDisplayItemDetail.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LookinDisplayItemDetail.h
5 | // Lookin
6 | //
7 | // Created by Li Kai on 2019/2/19.
8 | // https://lookin.work
9 | //
10 |
11 | #import "LookinDefines.h"
12 |
13 | @class LookinAttributesGroup;
14 | @class LookinDisplayItem;
15 |
16 | @interface LookinDisplayItemDetail : NSObject
17 |
18 | @property(nonatomic, assign) unsigned long displayItemOid;
19 |
20 | @property(nonatomic, strong) LookinImage *groupScreenshot;
21 |
22 | @property(nonatomic, strong) LookinImage *soloScreenshot;
23 |
24 | @property(nonatomic, strong) NSValue *frameValue;
25 |
26 | @property(nonatomic, strong) NSValue *boundsValue;
27 |
28 | @property(nonatomic, strong) NSNumber *hiddenValue;
29 |
30 | @property(nonatomic, strong) NSNumber *alphaValue;
31 |
32 | @property(nonatomic, copy) NSString *customDisplayTitle;
33 |
34 | @property(nonatomic, copy) NSString *danceUISource;
35 |
36 | @property(nonatomic, copy) NSArray *attributesGroupList;
37 | @property(nonatomic, copy) NSArray *customAttrGroupList;
38 |
39 | /// 注意 nil 和空数组的区别:nil 表示该属性无意义,空数组表示 subviews 为空
40 | /// Client 1.0.7 & Server 1.2.7 开始支持该属性
41 | /// 默认为 nil
42 | @property(nonatomic, copy) NSArray *subitems;
43 |
44 | /// 当 Server 找不到 task 对应的图层时,会返回一个特殊的 LookinDisplayItemDetail 对象,这个对象会被设置 displayItemOid 和 failureCode,其中 failureCode 会被置为 -1
45 | /// Client 1.0.7 & Server 1.2.7 开始支持该属性
46 | /// 默认为 0
47 | @property(nonatomic, assign) NSInteger failureCode;
48 |
49 | @end
50 |
51 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
52 |
--------------------------------------------------------------------------------
/Src/Main/Shared/LookinDisplayItemDetail.m:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LookinDisplayItemDetail.m
5 | // Lookin
6 | //
7 | // Created by Li Kai on 2019/2/19.
8 | // https://lookin.work
9 | //
10 |
11 | #import "LookinDisplayItemDetail.h"
12 | #import "Image+Lookin.h"
13 |
14 | #if TARGET_OS_IPHONE
15 | #import "UIImage+LookinServer.h"
16 | #endif
17 |
18 | @implementation LookinDisplayItemDetail
19 |
20 | - (void)encodeWithCoder:(NSCoder *)aCoder {
21 | [aCoder encodeObject:@(self.displayItemOid) forKey:@"displayItemOid"];
22 | [aCoder encodeObject:self.groupScreenshot.lookin_data forKey:@"groupScreenshot"];
23 | [aCoder encodeObject:self.soloScreenshot.lookin_data forKey:@"soloScreenshot"];
24 | [aCoder encodeObject:self.frameValue forKey:@"frameValue"];
25 | [aCoder encodeObject:self.boundsValue forKey:@"boundsValue"];
26 | [aCoder encodeObject:self.hiddenValue forKey:@"hiddenValue"];
27 | [aCoder encodeObject:self.alphaValue forKey:@"alphaValue"];
28 | [aCoder encodeObject:self.attributesGroupList forKey:@"attributesGroupList"];
29 | [aCoder encodeObject:self.customAttrGroupList forKey:@"customAttrGroupList"];
30 | [aCoder encodeObject:self.customDisplayTitle forKey:@"customDisplayTitle"];
31 | [aCoder encodeObject:self.danceUISource forKey:@"danceUISource"];
32 | [aCoder encodeInteger:self.failureCode forKey:@"failureCode"];
33 | if (self.subitems) {
34 | [aCoder encodeObject:self.subitems forKey:@"subitems"];
35 | }
36 | }
37 |
38 | - (instancetype)initWithCoder:(NSCoder *)aDecoder {
39 | if (self = [super init]) {
40 | self.displayItemOid = [[aDecoder decodeObjectForKey:@"displayItemOid"] unsignedLongValue];
41 | self.groupScreenshot = [[LookinImage alloc] initWithData:[aDecoder decodeObjectForKey:@"groupScreenshot"]];
42 | self.soloScreenshot = [[LookinImage alloc] initWithData:[aDecoder decodeObjectForKey:@"soloScreenshot"]];
43 | self.frameValue = [aDecoder decodeObjectForKey:@"frameValue"];
44 | self.boundsValue = [aDecoder decodeObjectForKey:@"boundsValue"];
45 | self.hiddenValue = [aDecoder decodeObjectForKey:@"hiddenValue"];
46 | self.alphaValue = [aDecoder decodeObjectForKey:@"alphaValue"];
47 | self.attributesGroupList = [aDecoder decodeObjectForKey:@"attributesGroupList"];
48 | self.customAttrGroupList = [aDecoder decodeObjectForKey:@"customAttrGroupList"];
49 | self.customDisplayTitle = [aDecoder decodeObjectForKey:@"customDisplayTitle"];
50 | self.danceUISource = [aDecoder decodeObjectForKey:@"danceUISource"];
51 |
52 | if ([aDecoder containsValueForKey:@"failureCode"]) {
53 | self.failureCode = [aDecoder decodeIntegerForKey:@"failureCode"];
54 | } else {
55 | self.failureCode = 0;
56 | }
57 |
58 | if ([aDecoder containsValueForKey:@"subitems"]) {
59 | self.subitems = [aDecoder decodeObjectForKey:@"subitems"];
60 | }
61 | }
62 | return self;
63 | }
64 |
65 | + (BOOL)supportsSecureCoding {
66 | return YES;
67 | }
68 |
69 | @end
70 |
71 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
72 |
--------------------------------------------------------------------------------
/Src/Main/Shared/LookinEventHandler.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LookinEventHandler.h
5 | // Lookin
6 | //
7 | // Created by Li Kai on 2019/8/7.
8 | // https://lookin.work
9 | //
10 |
11 |
12 |
13 | #import
14 |
15 | @class LookinObject, LookinIvarTrace, LookinStringTwoTuple;
16 |
17 | typedef NS_ENUM(NSInteger, LookinEventHandlerType) {
18 | LookinEventHandlerTypeTargetAction,
19 | LookinEventHandlerTypeGesture
20 | };
21 |
22 | @interface LookinEventHandler : NSObject
23 |
24 | @property(nonatomic, assign) LookinEventHandlerType handlerType;
25 |
26 | /// 比如 "UIControlEventTouchUpInside", "UITapGestureRecognizer"
27 | @property(nonatomic, copy) NSString *eventName;
28 | /// tuple.first => @"",tuple.second => @"handleTap"
29 | @property(nonatomic, copy) NSArray *targetActions;
30 |
31 | /// 返回当前 recognizer 是继承自哪一个基本款 recognizer。
32 | /// 基本款 recognizer 指的是 TapRecognizer, PinchRecognizer 之类的常见 recognizer
33 | /// 如果当前 recognizer 本身就是基本款 recognizer,则该属性为 nil
34 | @property(nonatomic, copy) NSString *inheritedRecognizerName;
35 | @property(nonatomic, assign) BOOL gestureRecognizerIsEnabled;
36 | @property(nonatomic, copy) NSString *gestureRecognizerDelegator;
37 | @property(nonatomic, copy) NSArray *recognizerIvarTraces;
38 | /// recognizer 对象
39 | @property(nonatomic, assign) unsigned long long recognizerOid;
40 |
41 | @end
42 |
43 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
44 |
--------------------------------------------------------------------------------
/Src/Main/Shared/LookinEventHandler.m:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LookinEventHandler.m
5 | // Lookin
6 | //
7 | // Created by Li Kai on 2019/8/7.
8 | // https://lookin.work
9 | //
10 |
11 |
12 |
13 | #import "LookinEventHandler.h"
14 | #import "LookinObject.h"
15 | #import "LookinTuple.h"
16 |
17 | #import "NSArray+Lookin.h"
18 |
19 | @implementation LookinEventHandler
20 |
21 | #pragma mark -
22 |
23 | - (id)copyWithZone:(NSZone *)zone {
24 | LookinEventHandler *newHandler = [[LookinEventHandler allocWithZone:zone] init];
25 | newHandler.handlerType = self.handlerType;
26 | newHandler.eventName = self.eventName;
27 | newHandler.targetActions = [self.targetActions lookin_map:^id(NSUInteger idx, LookinStringTwoTuple *value) {
28 | return value.copy;
29 | }];
30 | newHandler.gestureRecognizerIsEnabled = self.gestureRecognizerIsEnabled;
31 | newHandler.gestureRecognizerDelegator = self.gestureRecognizerDelegator;
32 | newHandler.inheritedRecognizerName = self.inheritedRecognizerName;
33 | newHandler.recognizerIvarTraces = self.recognizerIvarTraces.copy;
34 | newHandler.recognizerOid = self.recognizerOid;
35 | return newHandler;
36 | }
37 |
38 | #pragma mark -
39 |
40 | - (void)encodeWithCoder:(NSCoder *)aCoder {
41 | [aCoder encodeInteger:self.handlerType forKey:@"handlerType"];
42 | [aCoder encodeBool:self.gestureRecognizerIsEnabled forKey:@"gestureRecognizerIsEnabled"];
43 | [aCoder encodeObject:self.eventName forKey:@"eventName"];
44 | [aCoder encodeObject:self.gestureRecognizerDelegator forKey:@"gestureRecognizerDelegator"];
45 | [aCoder encodeObject:self.targetActions forKey:@"targetActions"];
46 | [aCoder encodeObject:self.inheritedRecognizerName forKey:@"inheritedRecognizerName"];
47 | [aCoder encodeObject:self.recognizerIvarTraces forKey:@"recognizerIvarTraces"];
48 | [aCoder encodeObject:@(self.recognizerOid) forKey:@"recognizerOid"];
49 | }
50 |
51 | - (instancetype)initWithCoder:(NSCoder *)aDecoder {
52 | if (self = [super init]) {
53 | self.handlerType = [aDecoder decodeIntegerForKey:@"handlerType"];
54 | self.gestureRecognizerIsEnabled = [aDecoder decodeBoolForKey:@"gestureRecognizerIsEnabled"];
55 | self.eventName = [aDecoder decodeObjectForKey:@"eventName"];
56 | self.gestureRecognizerDelegator = [aDecoder decodeObjectForKey:@"gestureRecognizerDelegator"];
57 | self.targetActions = [aDecoder decodeObjectForKey:@"targetActions"];
58 | self.inheritedRecognizerName = [aDecoder decodeObjectForKey:@"inheritedRecognizerName"];
59 | self.recognizerIvarTraces = [aDecoder decodeObjectForKey:@"recognizerIvarTraces"];
60 | self.recognizerOid = ((NSNumber *)[aDecoder decodeObjectForKey:@"recognizerOid"]).unsignedLongValue;
61 | }
62 | return self;
63 | }
64 |
65 | + (BOOL)supportsSecureCoding {
66 | return YES;
67 | }
68 |
69 | @end
70 |
71 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
72 |
--------------------------------------------------------------------------------
/Src/Main/Shared/LookinHierarchyFile.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LookinHierarchyFile.h
5 | // Lookin
6 | //
7 | // Created by Li Kai on 2019/5/12.
8 | // https://lookin.work
9 | //
10 |
11 |
12 |
13 | #import
14 |
15 | @class LookinHierarchyInfo;
16 |
17 | @interface LookinHierarchyFile : NSObject
18 |
19 | /// 记录创建该文件的 LookinServer 的版本
20 | @property(nonatomic, assign) int serverVersion;
21 |
22 | @property(nonatomic, strong) LookinHierarchyInfo *hierarchyInfo;
23 |
24 | @property(nonatomic, copy) NSDictionary *soloScreenshots;
25 | @property(nonatomic, copy) NSDictionary *groupScreenshots;
26 |
27 | /// 验证 file 的版本之类的是否和当前 Lookin 客户端匹配,如果没有问题则返回 nil,如果有问题则返回 error
28 | + (NSError *)verifyHierarchyFile:(LookinHierarchyFile *)file;
29 |
30 | @end
31 |
32 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
33 |
--------------------------------------------------------------------------------
/Src/Main/Shared/LookinHierarchyFile.m:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LookinHierarchyFile.m
5 | // Lookin
6 | //
7 | // Created by Li Kai on 2019/5/12.
8 | // https://lookin.work
9 | //
10 |
11 |
12 |
13 | #import "LookinHierarchyFile.h"
14 |
15 | #import "NSArray+Lookin.h"
16 |
17 | @implementation LookinHierarchyFile
18 |
19 | - (void)encodeWithCoder:(NSCoder *)aCoder {
20 | [aCoder encodeInt:self.serverVersion forKey:@"serverVersion"];
21 | [aCoder encodeObject:self.hierarchyInfo forKey:@"hierarchyInfo"];
22 | [aCoder encodeObject:self.soloScreenshots forKey:@"soloScreenshots"];
23 | [aCoder encodeObject:self.groupScreenshots forKey:@"groupScreenshots"];
24 | }
25 |
26 | - (instancetype)initWithCoder:(NSCoder *)aDecoder {
27 | if (self = [super init]) {
28 | self.serverVersion = [aDecoder decodeIntForKey:@"serverVersion"];
29 | self.hierarchyInfo = [aDecoder decodeObjectForKey:@"hierarchyInfo"];
30 | self.soloScreenshots = [aDecoder decodeObjectForKey:@"soloScreenshots"];
31 | self.groupScreenshots = [aDecoder decodeObjectForKey:@"groupScreenshots"];
32 | }
33 | return self;
34 | }
35 |
36 | + (BOOL)supportsSecureCoding {
37 | return YES;
38 | }
39 |
40 | + (NSError *)verifyHierarchyFile:(LookinHierarchyFile *)hierarchyFile {
41 | if (![hierarchyFile isKindOfClass:[LookinHierarchyFile class]]) {
42 | return LookinErr_Inner;
43 | }
44 |
45 | if (hierarchyFile.serverVersion < LOOKIN_SUPPORTED_SERVER_MIN) {
46 | // 文件版本太旧
47 | // 如果不存在 serverVersion 这个字段,说明版本是 6
48 | int fileVersion = hierarchyFile.serverVersion ? : 6;
49 | 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)];
50 | return [NSError errorWithDomain:LookinErrorDomain code:LookinErrCode_ServerVersionTooLow userInfo:@{NSLocalizedDescriptionKey:NSLocalizedString(@"Failed to open the document.", nil), NSLocalizedRecoverySuggestionErrorKey:detail}];
51 | }
52 |
53 | if (hierarchyFile.serverVersion > LOOKIN_SUPPORTED_SERVER_MAX) {
54 | // 文件版本太新
55 | 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)];
56 | return [NSError errorWithDomain:LookinErrorDomain code:LookinErrCode_ServerVersionTooHigh userInfo:@{NSLocalizedDescriptionKey:NSLocalizedString(@"Failed to open the document.", nil), NSLocalizedRecoverySuggestionErrorKey:detail}];
57 | }
58 |
59 | return nil;
60 | }
61 |
62 | @end
63 |
64 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
65 |
--------------------------------------------------------------------------------
/Src/Main/Shared/LookinHierarchyInfo.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LookinDisplayInfo.h
5 | // WeRead
6 | //
7 | // Created by Li Kai on 2018/10/22.
8 | // Copyright © 2018年 tencent. All rights reserved.
9 | //
10 |
11 |
12 |
13 | #import "LookinDefines.h"
14 | #import "TargetConditionals.h"
15 | #if TARGET_OS_IPHONE
16 | #import
17 | #elif TARGET_OS_MAC
18 | #import
19 | #endif
20 |
21 | @class LookinDisplayItem, LookinAttributesGroup, LookinAppInfo;
22 |
23 | @interface LookinHierarchyInfo : NSObject
24 |
25 | #if TARGET_OS_IPHONE
26 |
27 | /// version 可能为 nil,此时说明 Client 版本号 < 1.0.4
28 | + (instancetype)staticInfoWithLookinVersion:(NSString *)version;
29 |
30 | + (instancetype)exportedInfo;
31 |
32 | #endif
33 |
34 | /// 这里其实就是顶端的那几个 UIWindow
35 | @property(nonatomic, copy) NSArray *displayItems;
36 |
37 | @property(nonatomic, copy) NSDictionary *colorAlias;
38 |
39 | @property(nonatomic, copy) NSArray *collapsedClassList;
40 |
41 | @property(nonatomic, strong) LookinAppInfo *appInfo;
42 |
43 | @property(nonatomic, assign) int serverVersion;
44 |
45 | @end
46 |
47 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
48 |
--------------------------------------------------------------------------------
/Src/Main/Shared/LookinObject.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LookinObject.h
5 | // Lookin
6 | //
7 | // Created by Li Kai on 2019/4/20.
8 | // https://lookin.work
9 | //
10 |
11 |
12 |
13 | #import
14 |
15 | @class LookinObjectIvar, LookinIvarTrace;
16 |
17 | @interface LookinObject : NSObject
18 |
19 | #if TARGET_OS_IPHONE
20 | + (instancetype)instanceWithObject:(NSObject *)object;
21 | #endif
22 |
23 | @property(nonatomic, assign) unsigned long oid;
24 |
25 | @property(nonatomic, copy) NSString *memoryAddress;
26 |
27 | /**
28 | 比如有一个 UILabel 对象,则它的 classChainList 为 @[@"UILabel", @"UIView", @"UIResponder", @"NSObject"],而它的 ivarList 长度为 4,idx 从小到大分别是 UILabel 层级的 ivars, UIView 层级的 ivars.....
29 | */
30 | @property(nonatomic, copy) NSArray *classChainList;
31 |
32 | @property(nonatomic, copy) NSString *specialTrace;
33 |
34 | @property(nonatomic, copy) NSArray *ivarTraces;
35 |
36 | /// 没有 demangle,会包含 Swift Module Name
37 | /// 在 Lookin 的展示中,绝大多数情况下应该使用 lk_demangledSwiftName
38 | - (NSString *)rawClassName;
39 |
40 | @end
41 |
42 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
43 |
--------------------------------------------------------------------------------
/Src/Main/Shared/LookinObject.m:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LookinObject.m
5 | // Lookin
6 | //
7 | // Created by Li Kai on 2019/4/20.
8 | // https://lookin.work
9 | //
10 |
11 | #import "LookinObject.h"
12 | #import "LookinIvarTrace.h"
13 | #import "NSArray+Lookin.h"
14 | #import "NSString+Lookin.h"
15 |
16 | #if TARGET_OS_IPHONE
17 | #import "NSObject+LookinServer.h"
18 | #endif
19 |
20 | @implementation LookinObject
21 |
22 | #if TARGET_OS_IPHONE
23 | + (instancetype)instanceWithObject:(NSObject *)object {
24 | LookinObject *lookinObj = [LookinObject new];
25 | lookinObj.oid = [object lks_registerOid];
26 |
27 | lookinObj.memoryAddress = [NSString stringWithFormat:@"%p", object];
28 | lookinObj.classChainList = [object lks_classChainList];
29 |
30 | lookinObj.specialTrace = object.lks_specialTrace;
31 | lookinObj.ivarTraces = object.lks_ivarTraces;
32 |
33 | return lookinObj;
34 | }
35 | #endif
36 |
37 | #pragma mark -
38 |
39 | - (id)copyWithZone:(NSZone *)zone {
40 | LookinObject *newObject = [[LookinObject allocWithZone:zone] init];
41 | newObject.oid = self.oid;
42 | newObject.memoryAddress = self.memoryAddress;
43 | newObject.classChainList = self.classChainList;
44 | newObject.specialTrace = self.specialTrace;
45 | newObject.ivarTraces = [self.ivarTraces lookin_map:^id(NSUInteger idx, LookinIvarTrace *value) {
46 | return value.copy;
47 | }];
48 | return newObject;
49 | }
50 |
51 | #pragma mark -
52 |
53 | - (void)encodeWithCoder:(NSCoder *)aCoder {
54 | [aCoder encodeObject:@(self.oid) forKey:@"oid"];
55 | [aCoder encodeObject:self.memoryAddress forKey:@"memoryAddress"];
56 | [aCoder encodeObject:self.classChainList forKey:@"classChainList"];
57 | [aCoder encodeObject:self.specialTrace forKey:@"specialTrace"];
58 | [aCoder encodeObject:self.ivarTraces forKey:@"ivarTraces"];
59 | }
60 |
61 | - (instancetype)initWithCoder:(NSCoder *)aDecoder {
62 | if (self = [super init]) {
63 | self.oid = [(NSNumber *)[aDecoder decodeObjectForKey:@"oid"] unsignedLongValue];
64 | self.memoryAddress = [aDecoder decodeObjectForKey:@"memoryAddress"];
65 | self.classChainList = [aDecoder decodeObjectForKey:@"classChainList"];
66 | self.specialTrace = [aDecoder decodeObjectForKey:@"specialTrace"];
67 | self.ivarTraces = [aDecoder decodeObjectForKey:@"ivarTraces"];
68 | }
69 | return self;
70 | }
71 |
72 | + (BOOL)supportsSecureCoding {
73 | return YES;
74 | }
75 |
76 | - (NSString *)rawClassName {
77 | return self.classChainList.firstObject;
78 | }
79 |
80 | @end
81 |
82 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
83 |
--------------------------------------------------------------------------------
/Src/Main/Shared/LookinStaticAsyncUpdateTask.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LookinStaticAsyncUpdateTask.h
5 | // Lookin
6 | //
7 | // Created by Li Kai on 2019/6/21.
8 | // https://lookin.work
9 | //
10 |
11 |
12 |
13 | #import "LookinDefines.h"
14 |
15 | typedef NS_ENUM(NSInteger, LookinStaticAsyncUpdateTaskType) {
16 | LookinStaticAsyncUpdateTaskTypeNoScreenshot,
17 | LookinStaticAsyncUpdateTaskTypeSoloScreenshot,
18 | LookinStaticAsyncUpdateTaskTypeGroupScreenshot
19 | };
20 |
21 | typedef NS_ENUM(NSInteger, LookinDetailUpdateTaskAttrRequest) {
22 | /// 由 Server 端自己决定:同一批 task 里,server 端会保证同一个 layer 只会构造一次 attr
23 | /// 在 Lookin turbo 模式下,由于同一个 layer 的 task 可能位于不同批的 task 里,因此这会导致冗余的 attr 构造行为、浪费一定时间
24 | LookinDetailUpdateTaskAttrRequest_Automatic,
25 | /// 需要返回 attr
26 | LookinDetailUpdateTaskAttrRequest_Need,
27 | /// 不需要返回 attr
28 | LookinDetailUpdateTaskAttrRequest_NotNeed
29 | };
30 |
31 | /// 业务重写了 isEqual
32 | @interface LookinStaticAsyncUpdateTask : NSObject
33 |
34 | @property(nonatomic, assign) unsigned long oid;
35 |
36 | @property(nonatomic, assign) LookinStaticAsyncUpdateTaskType taskType;
37 |
38 | /// 是否需要返回 attr 数据,默认为 Automatic
39 | /// Client 1.0.7 & Server 1.2.7 开始支持这个参数
40 | @property(nonatomic, assign) LookinDetailUpdateTaskAttrRequest attrRequest;
41 |
42 | /// 如果置为 YES,则 server 侧会返回这些基础信息:frameValue, boundsValue, hiddenValue, alphaValue
43 | /// 默认为 NO
44 | /// Client 1.0.7 & Server 1.2.7 开始支持这个参数
45 | @property(nonatomic, assign) BOOL needBasisVisualInfo;
46 |
47 | /// 如果置为 YES,则 server 侧会返回 subitems
48 | /// 默认为 NO
49 | /// Client 1.0.7 & Server 1.2.7 开始支持这个参数
50 | @property(nonatomic, assign) BOOL needSubitems;
51 |
52 | /// Client 1.0.4 开始加入这个参数
53 | @property(nonatomic, copy) NSString *clientReadableVersion;
54 |
55 | #pragma mark - Non Coding
56 |
57 | @property(nonatomic, assign) CGSize frameSize;
58 |
59 | @end
60 |
61 | @interface LookinStaticAsyncUpdateTasksPackage : NSObject
62 |
63 | @property(nonatomic, copy) NSArray *tasks;
64 |
65 | @end
66 |
67 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
68 |
--------------------------------------------------------------------------------
/Src/Main/Shared/LookinTuple.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LookinTuples.h
5 | // Lookin
6 | //
7 | // Created by Li Kai on 2019/8/14.
8 | // https://lookin.work
9 | //
10 |
11 |
12 |
13 | #import
14 |
15 | @interface LookinTwoTuple : NSObject
16 |
17 | @property(nonatomic, strong) NSObject *first;
18 | @property(nonatomic, strong) NSObject *second;
19 |
20 | @end
21 |
22 | @interface LookinStringTwoTuple : NSObject
23 |
24 | + (instancetype)tupleWithFirst:(NSString *)firstString second:(NSString *)secondString;
25 |
26 | @property(nonatomic, copy) NSString *first;
27 | @property(nonatomic, copy) NSString *second;
28 |
29 | @end
30 |
31 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
32 |
--------------------------------------------------------------------------------
/Src/Main/Shared/LookinTuple.m:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LookinTuples.m
5 | // Lookin
6 | //
7 | // Created by Li Kai on 2019/8/14.
8 | // https://lookin.work
9 | //
10 |
11 |
12 |
13 | #import "LookinTuple.h"
14 |
15 | @implementation LookinTwoTuple
16 |
17 | - (void)encodeWithCoder:(NSCoder *)aCoder {
18 | [aCoder encodeObject:self.first forKey:@"first"];
19 | [aCoder encodeObject:self.second forKey:@"second"];
20 | }
21 |
22 | - (instancetype)initWithCoder:(NSCoder *)aDecoder {
23 | if (self = [super init]) {
24 | self.first = [aDecoder decodeObjectForKey:@"first"];
25 | self.second = [aDecoder decodeObjectForKey:@"second"];
26 | }
27 | return self;
28 | }
29 |
30 | + (BOOL)supportsSecureCoding {
31 | return YES;
32 | }
33 |
34 | - (NSUInteger)hash {
35 | return self.first.hash ^ self.second.hash;
36 | }
37 |
38 | - (BOOL)isEqual:(id)object {
39 | if (self == object) {
40 | return YES;
41 | }
42 | if (![object isKindOfClass:[LookinTwoTuple class]]) {
43 | return NO;
44 | }
45 | LookinTwoTuple *comparedObj = object;
46 | if ([self.first isEqual:comparedObj.first] && [self.second isEqual:comparedObj.second]) {
47 | return YES;
48 | }
49 | return NO;
50 | }
51 |
52 | @end
53 |
54 | @implementation LookinStringTwoTuple
55 |
56 | + (instancetype)tupleWithFirst:(NSString *)firstString second:(NSString *)secondString {
57 | LookinStringTwoTuple *tuple = [LookinStringTwoTuple new];
58 | tuple.first = firstString;
59 | tuple.second = secondString;
60 | return tuple;
61 | }
62 |
63 | #pragma mark -
64 |
65 | - (id)copyWithZone:(NSZone *)zone {
66 | LookinStringTwoTuple *newTuple = [[LookinStringTwoTuple allocWithZone:zone] init];
67 | newTuple.first = self.first;
68 | newTuple.second = self.second;
69 | return newTuple;
70 | }
71 |
72 | #pragma mark -
73 |
74 | - (void)encodeWithCoder:(NSCoder *)aCoder {
75 | [aCoder encodeObject:self.first forKey:@"first"];
76 | [aCoder encodeObject:self.second forKey:@"second"];
77 | }
78 |
79 | - (instancetype)initWithCoder:(NSCoder *)aDecoder {
80 | if (self = [super init]) {
81 | self.first = [aDecoder decodeObjectForKey:@"first"];
82 | self.second = [aDecoder decodeObjectForKey:@"second"];
83 | }
84 | return self;
85 | }
86 |
87 | + (BOOL)supportsSecureCoding {
88 | return YES;
89 | }
90 |
91 | @end
92 |
93 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
94 |
--------------------------------------------------------------------------------
/Src/Main/Shared/LookinWeakContainer.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LookinWeakContainer.h
5 | // Lookin
6 | //
7 | // Created by Li Kai on 2019/8/14.
8 | // https://lookin.work
9 | //
10 |
11 |
12 |
13 | #import
14 |
15 | @interface LookinWeakContainer : NSObject
16 |
17 | + (instancetype)containerWithObject:(id)object;
18 |
19 | @property (nonatomic, weak) id object;
20 |
21 | @end
22 |
23 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
24 |
--------------------------------------------------------------------------------
/Src/Main/Shared/LookinWeakContainer.m:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // LookinWeakContainer.m
5 | // Lookin
6 | //
7 | // Created by Li Kai on 2019/8/14.
8 | // https://lookin.work
9 | //
10 |
11 |
12 |
13 | #import "LookinWeakContainer.h"
14 |
15 | @implementation LookinWeakContainer
16 |
17 | + (instancetype)containerWithObject:(id)object {
18 | LookinWeakContainer *container = [LookinWeakContainer new];
19 | container.object = object;
20 | return container;
21 | }
22 |
23 | - (NSUInteger)hash {
24 | return [self.object hash];
25 | }
26 |
27 | - (BOOL)isEqual:(id)object {
28 | if (self == object) {
29 | return YES;
30 | }
31 | if (![object isKindOfClass:[LookinWeakContainer class]]) {
32 | return NO;
33 | }
34 | LookinWeakContainer *comparedObj = object;
35 | if ([self.object isEqual:comparedObj.object]) {
36 | return YES;
37 | }
38 | return NO;
39 | }
40 |
41 | @end
42 |
43 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
44 |
--------------------------------------------------------------------------------
/Src/Main/Shared/Peertalk/Lookin_PTPrivate.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 |
4 |
5 | #if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && (!defined(__IPHONE_6_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_6_0)) || \
6 | (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && (!defined(__MAC_10_8) || __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_8))
7 | #define PT_DISPATCH_RETAIN_RELEASE 1
8 | #else
9 | #define PT_DISPATCH_RETAIN_RELEASE 0
10 | #endif
11 |
12 | #if PT_DISPATCH_RETAIN_RELEASE
13 | #define PT_PRECISE_LIFETIME
14 | #define PT_PRECISE_LIFETIME_UNUSED
15 | #else
16 | #define PT_PRECISE_LIFETIME __attribute__((objc_precise_lifetime))
17 | #define PT_PRECISE_LIFETIME_UNUSED __attribute__((objc_precise_lifetime, unused))
18 | #endif
19 |
20 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
21 |
--------------------------------------------------------------------------------
/Src/Main/Shared/Peertalk/Lookin_PTUSBHub.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 |
4 |
5 | #include
6 | #import
7 |
8 | // Lookin_PTUSBDeviceDidAttachNotification
9 | // Posted when a device has been attached. Also posted for each device that is
10 | // already attached when the Lookin_PTUSBHub starts listening.
11 | //
12 | // .userInfo = {
13 | // DeviceID = 3;
14 | // MessageType = Attached;
15 | // Properties = {
16 | // ConnectionSpeed = 480000000;
17 | // ConnectionType = USB;
18 | // DeviceID = 3;
19 | // LocationID = 1234567890;
20 | // ProductID = 1234;
21 | // SerialNumber = 0123456789abcdef0123456789abcdef01234567;
22 | // };
23 | // }
24 | //
25 | FOUNDATION_EXPORT NSString * const Lookin_PTUSBDeviceDidAttachNotification;
26 |
27 | // Lookin_PTUSBDeviceDidDetachNotification
28 | // Posted when a device has been detached.
29 | //
30 | // .userInfo = {
31 | // DeviceID = 3;
32 | // MessageType = Detached;
33 | // }
34 | //
35 | FOUNDATION_EXPORT NSString * const Lookin_PTUSBDeviceDidDetachNotification;
36 |
37 | // NSError domain
38 | FOUNDATION_EXPORT NSString * const Lookin_PTUSBHubErrorDomain;
39 |
40 | // Error codes returned with NSError.code for NSError domain Lookin_PTUSBHubErrorDomain
41 | typedef enum {
42 | PTUSBHubErrorBadDevice = 2,
43 | PTUSBHubErrorConnectionRefused = 3,
44 | } PTUSBHubError;
45 |
46 | @interface Lookin_PTUSBHub : NSObject
47 |
48 | // Shared, implicitly opened hub.
49 | + (Lookin_PTUSBHub*)sharedHub;
50 |
51 | // Connect to a TCP *port* on a device, while the actual transport is over USB.
52 | // Upon success, *error* is nil and *channel* is a duplex I/O channel.
53 | // You can retrieve the underlying file descriptor using
54 | // dispatch_io_get_descriptor(channel). The dispatch_io_t channel behaves just
55 | // like any stream type dispatch_io_t, making it possible to use the same logic
56 | // for both USB bridged connections and e.g. ethernet-based connections.
57 | //
58 | // *onStart* is called either when a connection failed, in which case the error
59 | // argument is non-nil, or when the connection was successfully established (the
60 | // error argument is nil). Must not be NULL.
61 | //
62 | // *onEnd* is called when a connection was open and just did close. If the error
63 | // argument is non-nil, the channel closed because of an error. Pass NULL for no
64 | // callback.
65 | //
66 | - (void)connectToDevice:(NSNumber*)deviceID
67 | port:(int)port
68 | onStart:(void(^)(NSError *error, dispatch_io_t channel))onStart
69 | onEnd:(void(^)(NSError *error))onEnd;
70 |
71 | // Start listening for devices. You only need to invoke this method on custom
72 | // instances to start receiving notifications. The shared instance returned from
73 | // +sharedHub is always in listening mode.
74 | //
75 | // *onStart* is called either when the system failed to start listening, in
76 | // which case the error argument is non-nil, or when the receiver is listening.
77 | // Pass NULL for no callback.
78 | //
79 | // *onEnd* is called when listening stopped. If the error argument is non-nil,
80 | // listening stopped because of an error. Pass NULL for no callback.
81 | //
82 | - (void)listenOnQueue:(dispatch_queue_t)queue
83 | onStart:(void(^)(NSError*))onStart
84 | onEnd:(void(^)(NSError*))onEnd;
85 |
86 | @end
87 |
88 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
89 |
--------------------------------------------------------------------------------
/Src/Main/Shared/Peertalk/Peertalk.h:
--------------------------------------------------------------------------------
1 | #ifdef SHOULD_COMPILE_LOOKIN_SERVER
2 |
3 | //
4 | // Peertalk.h
5 | // Peertalk
6 | //
7 | // Created by Marek Cirkos on 12/04/2016.
8 | //
9 | //
10 |
11 |
12 |
13 | #import
14 |
15 | //! Project version number for Peertalk.
16 | FOUNDATION_EXPORT double PeertalkVersionNumber;
17 |
18 | //! Project version string for Peertalk.
19 | FOUNDATION_EXPORT const unsigned char PeertalkVersionString[];
20 |
21 | // In this header, you should import all the public headers of your framework using statements like #import
22 |
23 |
24 | #import "Lookin_PTChannel.h"
25 | #import "Lookin_PTProtocol.h"
26 | #import "Lookin_PTUSBHub.h"
27 |
28 | #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
29 |
--------------------------------------------------------------------------------