Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ Temporary Items
### SwiftPackageManager ###
Packages
.build/
Package.resolved
xcuserdata
DerivedData/
#*.xcodeproj
Expand Down
3 changes: 3 additions & 0 deletions LookinDemo/OC_Pod/LookinDemoOC/AppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ @implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
#if !TARGET_OS_SIMULATOR
[NSNotificationCenter.defaultCenter postNotificationName:@"Lookin_startWirelessConnection" object:nil];
#endif
return YES;
}

Expand Down
4 changes: 4 additions & 0 deletions LookinDemo/OC_Pod/LookinDemoOC/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSBonjourServices</key>
<array>
<string>_Lookin._tcp</string>
</array>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
Expand Down
21 changes: 19 additions & 2 deletions LookinServer.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ Pod::Spec.new do |spec|
spec.source = { :git => "https://github.com/QMUI/LookinServer.git", :tag => "1.2.8"}
spec.framework = "UIKit"
spec.requires_arc = true

spec.subspec 'Core' do |ss|
ss.source_files = ['Src/Main/**/*', 'Src/Base/**/*']
ss.exclude_files = 'Src/Main/Shared/Channel/**/*'
ss.pod_target_xcconfig = {
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) SHOULD_COMPILE_LOOKIN_SERVER=1',
'SWIFT_ACTIVE_COMPILATION_CONDITIONS' => '$(inherited) SHOULD_COMPILE_LOOKIN_SERVER'
Expand All @@ -37,7 +38,7 @@ Pod::Spec.new do |spec|
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) LOOKIN_SERVER_DISABLE_HOOK=1',
}
end

# CocoaPods 不支持多个 subspecs 和 configurations 并列
# "pod 'LookinServer', :subspecs => ['Swift', 'NoHook'], :configurations => ['Debug']" is not supported by CocoaPods
# https://github.com/QMUI/LookinServer/issues/134
Expand All @@ -50,4 +51,20 @@ Pod::Spec.new do |spec|
}
end

spec.subspec 'SwiftAndWireless' do |ss|
ss.dependency 'LookinServer/Swift'
ss.dependency 'LookinShared/Wireless'
ss.pod_target_xcconfig = {
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) LOOKIN_SERVER_WIRELESS=1'
}
end

spec.subspec 'Wireless' do |ss|
ss.dependency 'LookinServer/Core'
ss.dependency 'LookinShared/Wireless'
ss.pod_target_xcconfig = {
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) LOOKIN_SERVER_WIRELESS=1'
}
end

end
17 changes: 17 additions & 0 deletions LookinShared.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,24 @@ Pod::Spec.new do |spec|
'Src/Main/Shared/**/*',
'Src/Base/**/*'
]
spec.exclude_files = 'Src/Main/Shared/Channel/**/*'
spec.default_subspec = :none

spec.pod_target_xcconfig = {
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) SHOULD_COMPILE_LOOKIN_SERVER=1'
}

spec.subspec 'Wireless' do |ss|
# The channel implementation imports shared protocol and Peertalk headers.
# A consumer may select this subspec directly (the macOS client does), so it
# must be self-contained instead of relying on LookinServer/Core.
ss.source_files = [
'Src/Main/Shared/**/*',
'Src/Base/**/*'
]
ss.dependency 'CocoaAsyncSocket'
ss.pod_target_xcconfig = {
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) SHOULD_COMPILE_LOOKIN_SERVER=1 LOOKIN_SERVER_WIRELESS=1'
}
end
end
15 changes: 13 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,20 @@ let package = Package(
url: "https://github.com/swiftlang/swift-syntax.git",
exact: "603.0.2"
),
.package(
url: "https://github.com/robbiehanson/CocoaAsyncSocket.git",
exact: "7.6.5"
),
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages this package depends on.
.target(
name: "LookinServer",
dependencies: [.target(name: "LookinServerSwift")],
dependencies: [
.target(name: "LookinServerSwift"),
.product(name: "CocoaAsyncSocket", package: "CocoaAsyncSocket"),
],
path: "Src/Main",
publicHeadersPath: "",
cSettings: [
Expand All @@ -42,10 +49,14 @@ let package = Package(
.headerSearchPath("Shared/Category"),
.headerSearchPath("Shared/Message"),
.headerSearchPath("Shared/Peertalk"),
.define("SHOULD_COMPILE_LOOKIN_SERVER", to: "1", .when(configuration: .debug)),
.define("SPM_LOOKIN_SERVER_ENABLED", to: "1", .when(configuration: .debug)),
.define("LOOKIN_SERVER_WIRELESS", to: "1", .when(configuration: .debug)),
],
cxxSettings: [
.define("SHOULD_COMPILE_LOOKIN_SERVER", to: "1", .when(configuration: .debug)),
.define("SPM_LOOKIN_SERVER_ENABLED", to: "1", .when(configuration: .debug))
.define("SPM_LOOKIN_SERVER_ENABLED", to: "1", .when(configuration: .debug)),
.define("LOOKIN_SERVER_WIRELESS", to: "1", .when(configuration: .debug))
]
),
.target(
Expand Down
48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,46 @@ To use Lookin macOS app, you need to integrate LookinServer (iOS Framework of Lo
## via Swift Package Manager:
`https://github.com/QMUI/LookinServer/`

## Experimental wireless connection

Wireless inspection is opt-in, CocoaPods-only, and intended for Debug builds on a trusted local network. The transport is not encrypted or cryptographically authenticated. The iOS app asks for confirmation before accepting a new Mac, and remembered device identifiers are checked independently on both sides. One Mac may inspect an app over wireless at a time.

```ruby
# Swift + wireless inspection
pod 'LookinServer',
:git => 'https://github.com/nova286/LookinServer.git',
:subspecs => ['SwiftAndWireless'],
:configurations => ['Debug']

# Objective-C + wireless inspection
# pod 'LookinServer', :git => 'https://github.com/nova286/LookinServer.git',
# :subspecs => ['Wireless'], :configurations => ['Debug']
```

Add the following declarations to the inspected app's `Info.plist`:

```xml
<key>NSLocalNetworkUsageDescription</key>
<string>Connect to Lookin on your Mac for local UI inspection.</string>
<key>NSBonjourServices</key>
<array>
<string>_Lookin._tcp</string>
</array>
```

Start discovery explicitly after the app is active. This is intentionally not automatic, so merely linking the subspec does not request local-network permission:

```swift
#if DEBUG
NotificationCenter.default.post(
name: Notification.Name("Lookin_startWirelessConnection"),
object: nil
)
#endif
```

Post `Lookin_endWirelessConnection` to stop discovery, close active wireless transports, and forget the current session. The default `Core`/`Swift` subspecs and the default Swift Package Manager product do not compile the wireless transport or CocoaAsyncSocket.

## Experimental SwiftUI semantic hierarchy

The `codex/swiftui-attached-macro` branch can expose opt-in SwiftUI semantic nodes through Lookin's existing hierarchy and custom-attribute protocol. The matching macOS client fork adds a dedicated hierarchy mode and automatic refresh after edits.
Expand Down Expand Up @@ -103,6 +143,14 @@ Lookin 可以查看与修改 iOS App 里的 UI 对象,类似于 Xcode 自带
## 通过 Swift Package Manager:
`https://github.com/QMUI/LookinServer/`

## 实验性无线连接

无线检查能力是显式可选的,目前仅支持 CocoaPods,且只应在可信局域网的 Debug 构建中启用。传输内容没有加密,设备标识也不是密码学身份证明;首次连接新 Mac 时 iOS App 会要求用户确认,“始终允许”会在两端分别校验已记住的设备标识。同一时刻仅允许一台 Mac 通过无线方式检查当前 App。

Swift 项目使用 `SwiftAndWireless` subspec,Objective-C 项目使用 `Wireless` subspec,并继续通过 `:configurations => ['Debug']` 限制构建配置。示例见上方英文文档。

被检查 App 的 `Info.plist` 必须声明 `NSLocalNetworkUsageDescription`,并在 `NSBonjourServices` 中加入 `_Lookin._tcp`。App 启动并进入 active 状态后,发送 `Lookin_startWirelessConnection` 通知才会开始发现设备;发送 `Lookin_endWirelessConnection` 会停止发现、关闭当前无线通道并清理本次会话。该能力不会自动启动,默认 `Core`/`Swift` subspec 与默认 SPM product 都不会编译无线通道或引入 CocoaAsyncSocket。

## 实验性 SwiftUI 语义层级

`codex/swiftui-attached-macro` 分支支持把 SwiftUI 语义节点接入 Lookin 现有层级与自定义属性协议;配套的 macOS 客户端 fork 提供独立的 SwiftUI 层级模式,并在修改属性后自动刷新。使用 `@LookinInspectable` 标记 View 类型后,Debug 构建以及显式定义 `STAGING` 的 Staging 构建会自动包装 `body`、为每个渲染实例生成唯一 ID,并从最近的标记父节点继承语义层级。每棵层级只需在根部保留一次 `lookinSwiftUIInspector()`;只有需要自定义 ID 或可编辑 Binding 时才继续使用显式 `lookinInspectable` modifier。其他构建仍需让编译器解析宏,但展开结果是原始 body,不会调用运行时 Probe。
Expand Down
16 changes: 14 additions & 2 deletions Src/Main/Server/Connection/LKS_ConnectionManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,21 @@ extern NSString *const LKS_ConnectionDidEndNotificationName;

@property(nonatomic, assign) BOOL applicationIsActive;

- (void)respond:(LookinConnectionResponseAttachment *)data requestType:(uint32_t)requestType tag:(uint32_t)tag;
#if LOOKIN_SERVER_WIRELESS
- (void)startWirelessConnection;

- (void)pushData:(NSObject *)data type:(uint32_t)type;
- (void)endWirelessConnection;
#endif

- (BOOL)isConnected;

#if LOOKIN_SERVER_WIRELESS
- (BOOL)isWirelessConnnect;
#endif

- (void)respond:(LookinConnectionResponseAttachment *)data requestType:(uint32_t)requestType tag:(uint32_t)tag isWireless:(BOOL)isWireless;

- (void)pushData:(NSObject *)data type:(uint32_t)type isWireless:(BOOL)isWireless;

@end

Expand Down
Loading