expo-widgets 56.0.8 → 56.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/ios/LiveActivity.swift +1 -1
- package/ios/Widgets/AppIntent.swift +11 -5
- package/ios/Widgets/Utils.swift +12 -26
- package/ios/Widgets/WidgetLiveActivity.swift +21 -21
- package/ios/Widgets/WidgetsJSRuntime.swift +142 -0
- package/package.json +4 -4
- package/plugin/tsconfig.tsbuildinfo +1 -0
- package/spm.config.json +2 -0
- package/ios/Widgets/WidgetContext.swift +0 -23
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,21 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
+
## 56.0.9 — 2026-05-15
|
|
14
|
+
|
|
15
|
+
### 🎉 New features
|
|
16
|
+
|
|
17
|
+
- Use shared JS runtime. ([#45781](https://github.com/expo/expo/pull/45781) by [@jakex7](https://github.com/jakex7))
|
|
18
|
+
|
|
19
|
+
### 🐛 Bug fixes
|
|
20
|
+
|
|
21
|
+
- Fix Live Activity multiple evaluations. ([#45675](https://github.com/expo/expo/pull/45675) by [@nkopylov](https://github.com/nkopylov))
|
|
22
|
+
- Fix module precompile. ([#45715](https://github.com/expo/expo/pull/45715) by [@jakex7](https://github.com/jakex7))
|
|
23
|
+
|
|
24
|
+
### 💡 Others
|
|
25
|
+
|
|
26
|
+
- Migrated to the single-payload `SharedObject.emit` API. ([#45596](https://github.com/expo/expo/pull/45596) by [@tsapeta](https://github.com/tsapeta))
|
|
27
|
+
|
|
13
28
|
## 56.0.8 — 2026-05-13
|
|
14
29
|
|
|
15
30
|
### 🎉 New features
|
package/ios/LiveActivity.swift
CHANGED
|
@@ -66,7 +66,7 @@ final class LiveActivity: SharedObject {
|
|
|
66
66
|
pushTokenObserverTask = Task {
|
|
67
67
|
for await data in activity.pushTokenUpdates {
|
|
68
68
|
let token = data.reduce("") { $0 + String(format: "%02x", $1) }
|
|
69
|
-
emit(event: onTokenReceived,
|
|
69
|
+
emit(event: onTokenReceived, payload: [
|
|
70
70
|
"activityId": activity.id,
|
|
71
71
|
"pushToken": token
|
|
72
72
|
])
|
|
@@ -58,19 +58,25 @@ struct WidgetUserInteraction: AppIntent {
|
|
|
58
58
|
|
|
59
59
|
guard let timeline,
|
|
60
60
|
let entryIndex,
|
|
61
|
+
timeline.indices.contains(entryIndex),
|
|
61
62
|
let entry = timeline[entryIndex] as? [String: Any],
|
|
62
63
|
let props = entry["props"] as? [String: Any],
|
|
63
|
-
let context = createWidgetContext(layout: layout),
|
|
64
64
|
let environmentData = environmentString?.data(using: .utf8),
|
|
65
65
|
var environment = try? JSONSerialization.jsonObject(with: environmentData) as? [String: Any] else {
|
|
66
66
|
return .result()
|
|
67
67
|
}
|
|
68
68
|
environment["target"] = target
|
|
69
69
|
|
|
70
|
-
let
|
|
71
|
-
|
|
72
|
-
)
|
|
73
|
-
|
|
70
|
+
let newProps: [String: Any]?
|
|
71
|
+
switch evaluateWidgetButtonPress(layout: layout, props: props, environment: environment) {
|
|
72
|
+
case .success(let result):
|
|
73
|
+
newProps = result
|
|
74
|
+
case .failure(let error):
|
|
75
|
+
print("[ExpoWidgets] Button press evaluation failed: \(error.message)")
|
|
76
|
+
newProps = nil
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if let newProps {
|
|
74
80
|
var newEntry = entry
|
|
75
81
|
if let originalProps = entry["props"] as? [String: Any] {
|
|
76
82
|
newEntry["props"] = originalProps.merging(newProps) { _, new in new }
|
package/ios/Widgets/Utils.swift
CHANGED
|
@@ -33,41 +33,27 @@ public func evaluateLayout(
|
|
|
33
33
|
props: [String: Any],
|
|
34
34
|
environment: [String: Any]
|
|
35
35
|
) -> [String: Any] {
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
switch evaluateWidgetLayout(layout: layout, props: props, environment: environment) {
|
|
37
|
+
case .success(let result):
|
|
38
|
+
return result
|
|
39
|
+
case .failure(let error):
|
|
40
|
+
print("[ExpoWidgets] Layout evaluation failed: \(error.message)")
|
|
41
|
+
return createRedBox(message: error.message)
|
|
38
42
|
}
|
|
39
|
-
|
|
40
|
-
let result = context.objectForKeyedSubscript("__expoWidgetRender")?.call(
|
|
41
|
-
withArguments: [props, environment]
|
|
42
|
-
)
|
|
43
|
-
if let exception = context.exception {
|
|
44
|
-
print("[ExpoWidgets] Layout evaluation failed: \(exception)")
|
|
45
|
-
return createRedBox(message: exception.toString())
|
|
46
|
-
}
|
|
47
|
-
return result?.toObject() as? [String: Any] ?? createRedBox(message: "Expo widget render did not produce any results.")
|
|
48
43
|
}
|
|
49
44
|
|
|
50
45
|
func getLiveActivityNodes(forName name: String, props: String = "{}", environment: [String: Any]) -> [String: Any] {
|
|
51
46
|
let layout = WidgetsStorage.getString(forKey: "__expo_widgets_live_activity_\(name)_layout") ?? ""
|
|
52
47
|
let propsData = props.data(using: .utf8)
|
|
53
48
|
let propsDict = propsData.flatMap { try? JSONSerialization.jsonObject(with: $0, options: []) as? [String: Any] } ?? [:]
|
|
54
|
-
guard let context = createWidgetContext(layout: layout) else {
|
|
55
|
-
return ["banner": createRedBox(message: "Could not create context for layout evaluation.")]
|
|
56
|
-
}
|
|
57
49
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
if let exception = context.exception {
|
|
66
|
-
print("[ExpoWidgets] Layout evaluation failed: \(exception)")
|
|
67
|
-
return ["banner": createRedBox(message: exception.toString())]
|
|
50
|
+
switch evaluateWidgetLayout(layout: layout, props: propsDict, environment: environment) {
|
|
51
|
+
case .success(let result):
|
|
52
|
+
return result
|
|
53
|
+
case .failure(let error):
|
|
54
|
+
print("[ExpoWidgets] Layout evaluation failed: \(error.message)")
|
|
55
|
+
return ["banner": createRedBox(message: error.message)]
|
|
68
56
|
}
|
|
69
|
-
|
|
70
|
-
return result?.toObject() as? [String: Any] ?? ["banner": createRedBox(message: "Expo widget render did not produce any results.")]
|
|
71
57
|
}
|
|
72
58
|
|
|
73
59
|
func getLiveActivityUrl(forName name: String) -> URL? {
|
|
@@ -24,27 +24,37 @@ public struct WidgetLiveActivity: Widget {
|
|
|
24
24
|
|
|
25
25
|
public var body: some WidgetConfiguration {
|
|
26
26
|
ActivityConfiguration(for: LiveActivityAttributes.self) { context in
|
|
27
|
-
|
|
27
|
+
let nodes = getLiveActivityNodes(
|
|
28
|
+
forName: context.state.name,
|
|
29
|
+
props: context.state.props,
|
|
30
|
+
environment: environment
|
|
31
|
+
)
|
|
32
|
+
LiveActivityBannerView(context: context, nodes: nodes)
|
|
28
33
|
} dynamicIsland: { context in
|
|
29
|
-
|
|
34
|
+
let nodes = getLiveActivityNodes(
|
|
35
|
+
forName: context.state.name,
|
|
36
|
+
props: context.state.props,
|
|
37
|
+
environment: environment
|
|
38
|
+
)
|
|
39
|
+
return DynamicIsland {
|
|
30
40
|
DynamicIslandExpandedRegion(.center) {
|
|
31
|
-
LiveActivitySectionView(context: context,
|
|
41
|
+
LiveActivitySectionView(context: context, nodes: nodes, sectionName: "expandedCenter")
|
|
32
42
|
}
|
|
33
43
|
DynamicIslandExpandedRegion(.leading) {
|
|
34
|
-
LiveActivitySectionView(context: context,
|
|
44
|
+
LiveActivitySectionView(context: context, nodes: nodes, sectionName: "expandedLeading")
|
|
35
45
|
}
|
|
36
46
|
DynamicIslandExpandedRegion(.trailing) {
|
|
37
|
-
LiveActivitySectionView(context: context,
|
|
47
|
+
LiveActivitySectionView(context: context, nodes: nodes, sectionName: "expandedTrailing")
|
|
38
48
|
}
|
|
39
49
|
DynamicIslandExpandedRegion(.bottom) {
|
|
40
|
-
LiveActivitySectionView(context: context,
|
|
50
|
+
LiveActivitySectionView(context: context, nodes: nodes, sectionName: "expandedBottom")
|
|
41
51
|
}
|
|
42
52
|
} compactLeading: {
|
|
43
|
-
LiveActivitySectionView(context: context,
|
|
53
|
+
LiveActivitySectionView(context: context, nodes: nodes, sectionName: "compactLeading")
|
|
44
54
|
} compactTrailing: {
|
|
45
|
-
LiveActivitySectionView(context: context,
|
|
55
|
+
LiveActivitySectionView(context: context, nodes: nodes, sectionName: "compactTrailing")
|
|
46
56
|
} minimal: {
|
|
47
|
-
LiveActivitySectionView(context: context,
|
|
57
|
+
LiveActivitySectionView(context: context, nodes: nodes, sectionName: "minimal")
|
|
48
58
|
}
|
|
49
59
|
.widgetURL(getLiveActivityUrl(forName: context.state.name))
|
|
50
60
|
}
|
|
@@ -55,15 +65,10 @@ public struct WidgetLiveActivity: Widget {
|
|
|
55
65
|
@available(iOS 16.1, *)
|
|
56
66
|
private struct LiveActivitySectionView: View {
|
|
57
67
|
let context: ActivityViewContext<LiveActivityAttributes>
|
|
58
|
-
let
|
|
68
|
+
let nodes: [String: Any]
|
|
59
69
|
let sectionName: String
|
|
60
70
|
|
|
61
71
|
var body: some View {
|
|
62
|
-
let nodes = getLiveActivityNodes(
|
|
63
|
-
forName: context.state.name,
|
|
64
|
-
props: context.state.props,
|
|
65
|
-
environment: environment
|
|
66
|
-
)
|
|
67
72
|
if let node = nodes[sectionName] as? [String: Any] {
|
|
68
73
|
WidgetsDynamicView(name: context.activityID, kind: .liveActivity, node: node)
|
|
69
74
|
} else {
|
|
@@ -75,14 +80,9 @@ private struct LiveActivitySectionView: View {
|
|
|
75
80
|
@available(iOS 16.1, *)
|
|
76
81
|
private struct LiveActivityBannerView: View {
|
|
77
82
|
var context: ActivityViewContext<LiveActivityAttributes>
|
|
78
|
-
let
|
|
83
|
+
let nodes: [String: Any]
|
|
79
84
|
|
|
80
85
|
var body: some View {
|
|
81
|
-
let nodes = getLiveActivityNodes(
|
|
82
|
-
forName: context.state.name,
|
|
83
|
-
props: context.state.props,
|
|
84
|
-
environment: environment
|
|
85
|
-
)
|
|
86
86
|
if #available(iOS 18.0, *) {
|
|
87
87
|
LiveActivityBanner(context: context, nodes: nodes)
|
|
88
88
|
} else if let node = nodes["banner"] as? [String: Any] {
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import JavaScriptCore
|
|
3
|
+
|
|
4
|
+
struct WidgetJavaScriptError: Error {
|
|
5
|
+
let message: String
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
typealias WidgetJavaScriptResult<Value> = Result<Value, WidgetJavaScriptError>
|
|
9
|
+
|
|
10
|
+
private final class WidgetsJSRuntime {
|
|
11
|
+
static let shared = WidgetsJSRuntime()
|
|
12
|
+
|
|
13
|
+
private let lock = NSRecursiveLock()
|
|
14
|
+
private var context: JSContext?
|
|
15
|
+
private var bundleScript: String?
|
|
16
|
+
private var layoutCache: [String: JSValue] = [:]
|
|
17
|
+
|
|
18
|
+
private init() {}
|
|
19
|
+
|
|
20
|
+
func render(layout: String, props: [String: Any], environment: [String: Any]) -> WidgetJavaScriptResult<[String: Any]> {
|
|
21
|
+
call(layout: layout, functionName: "__expoWidgetRender", arguments: [props, environment]).flatMap { result in
|
|
22
|
+
guard let renderedNode = result?.toObject() as? [String: Any] else {
|
|
23
|
+
return .failure(WidgetJavaScriptError(message: "Expo widget render did not produce any results."))
|
|
24
|
+
}
|
|
25
|
+
return .success(renderedNode)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
func handlePress(layout: String, props: [String: Any], environment: [String: Any]) -> WidgetJavaScriptResult<[String: Any]?> {
|
|
30
|
+
call(layout: layout, functionName: "__expoWidgetHandlePress", arguments: [props, environment])
|
|
31
|
+
.map { $0?.toObject() as? [String: Any] }
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
private func call(layout: String, functionName: String, arguments: [Any]) -> WidgetJavaScriptResult<JSValue?> {
|
|
35
|
+
lock.lock()
|
|
36
|
+
defer { lock.unlock() }
|
|
37
|
+
|
|
38
|
+
guard let context = getContext() else {
|
|
39
|
+
return .failure(WidgetJavaScriptError(message: "Could not create context for layout evaluation."))
|
|
40
|
+
}
|
|
41
|
+
guard let layoutValue = getLayoutValue(layout, in: context) else {
|
|
42
|
+
return .failure(WidgetJavaScriptError(message: contextExceptionMessage(context) ?? "Could not evaluate layout."))
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
context.exception = nil
|
|
46
|
+
context.setObject(layoutValue, forKeyedSubscript: "__expoWidgetLayout" as NSString)
|
|
47
|
+
|
|
48
|
+
let function = context.objectForKeyedSubscript(functionName)
|
|
49
|
+
guard let function, function.isObject else {
|
|
50
|
+
return .failure(WidgetJavaScriptError(message: "Expo widget runtime function \(functionName) is unavailable."))
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
let result = function.call(withArguments: arguments)
|
|
54
|
+
if let exceptionMessage = contextExceptionMessage(context) {
|
|
55
|
+
return .failure(WidgetJavaScriptError(message: exceptionMessage))
|
|
56
|
+
}
|
|
57
|
+
return .success(result)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
private func getContext() -> JSContext? {
|
|
61
|
+
if let context {
|
|
62
|
+
return context
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
guard let context = JSContext() else {
|
|
66
|
+
return nil
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
guard let script = getBundleScript() else {
|
|
70
|
+
print("[ExpoWidgets] Missing ExpoWidgets.bundle")
|
|
71
|
+
return nil
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
context.evaluateScript(script)
|
|
75
|
+
if let exceptionMessage = contextExceptionMessage(context) {
|
|
76
|
+
print("[ExpoWidgets] Bundle evaluation failed: \(exceptionMessage)")
|
|
77
|
+
return nil
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
self.context = context
|
|
81
|
+
return context
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
private func getBundleScript() -> String? {
|
|
85
|
+
if let bundleScript {
|
|
86
|
+
return bundleScript
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
guard let bundleURL = Bundle.main.url(forResource: "ExpoWidgets", withExtension: "bundle"),
|
|
90
|
+
let bundle = Bundle(url: bundleURL),
|
|
91
|
+
let url = bundle.url(forResource: "ExpoWidgets", withExtension: "bundle"),
|
|
92
|
+
let script = try? String(contentsOf: url, encoding: .utf8) else {
|
|
93
|
+
return nil
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
bundleScript = script
|
|
97
|
+
return script
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
private func getLayoutValue(_ layout: String, in context: JSContext) -> JSValue? {
|
|
101
|
+
if let layoutValue = layoutCache[layout] {
|
|
102
|
+
return layoutValue
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
context.exception = nil
|
|
106
|
+
guard let layoutValue = context.evaluateScript("(\(layout))"),
|
|
107
|
+
!layoutValue.isUndefined else {
|
|
108
|
+
return nil
|
|
109
|
+
}
|
|
110
|
+
guard context.exception == nil else {
|
|
111
|
+
return nil
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
layoutCache[layout] = layoutValue
|
|
115
|
+
return layoutValue
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
private func contextExceptionMessage(_ context: JSContext) -> String? {
|
|
119
|
+
guard let exception = context.exception else {
|
|
120
|
+
return nil
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
context.exception = nil
|
|
124
|
+
return exception.toString() ?? "Unknown JavaScript exception."
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
func evaluateWidgetLayout(
|
|
129
|
+
layout: String,
|
|
130
|
+
props: [String: Any],
|
|
131
|
+
environment: [String: Any]
|
|
132
|
+
) -> WidgetJavaScriptResult<[String: Any]> {
|
|
133
|
+
WidgetsJSRuntime.shared.render(layout: layout, props: props, environment: environment)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
func evaluateWidgetButtonPress(
|
|
137
|
+
layout: String,
|
|
138
|
+
props: [String: Any],
|
|
139
|
+
environment: [String: Any]
|
|
140
|
+
) -> WidgetJavaScriptResult<[String: Any]?> {
|
|
141
|
+
WidgetsJSRuntime.shared.handlePress(layout: layout, props: props, environment: environment)
|
|
142
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-widgets",
|
|
3
|
-
"version": "56.0.
|
|
3
|
+
"version": "56.0.9",
|
|
4
4
|
"description": "Widgets.",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"homepage": "https://docs.expo.dev/versions/latest/sdk/widgets/",
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@expo/plist": "^0.6.0",
|
|
25
|
-
"@expo/ui": "~56.0.
|
|
25
|
+
"@expo/ui": "~56.0.8"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@expo/spawn-async": "^1.7.2",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"@types/react": "~19.2.0",
|
|
31
31
|
"react-native": "0.85.3",
|
|
32
32
|
"resolve-workspace-root": "^2.0.0",
|
|
33
|
-
"expo": "56.0.0-preview.
|
|
33
|
+
"expo": "56.0.0-preview.12",
|
|
34
34
|
"expo-module-scripts": "56.0.2"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"./scripts/xcode-build-bundle.sh"
|
|
45
45
|
]
|
|
46
46
|
},
|
|
47
|
-
"gitHead": "
|
|
47
|
+
"gitHead": "f26be3dd9396bf7c399a1d607865d0fabdbc0d64",
|
|
48
48
|
"scripts": {
|
|
49
49
|
"build": "expo-module build",
|
|
50
50
|
"build:plugin": "expo-module build plugin",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"root":["./src/index.ts","./src/withappgroupentitlements.ts","./src/withappinfoplist.ts","./src/witheasconfig.ts","./src/withioswarning.ts","./src/withpodslinking.ts","./src/withpushnotifications.ts","./src/withwidgetsourcefiles.ts","./src/types/widgetconfig.type.ts","./src/types/widgetfamily.type.ts","./src/xcode/addbuildphases.ts","./src/xcode/addpbxgroup.ts","./src/xcode/addproductfile.ts","./src/xcode/addtargetdependency.ts","./src/xcode/addtopbxnativetargetsection.ts","./src/xcode/addtopbxprojectsection.ts","./src/xcode/addxcconfigurationlist.ts","./src/xcode/withtargetxcodeproject.ts"],"version":"5.9.2"}
|
package/spm.config.json
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"React",
|
|
13
13
|
"Hermes",
|
|
14
14
|
"expo-modules-core/ExpoModulesCore",
|
|
15
|
+
"expo-modules-core/ExpoModulesWorklets",
|
|
15
16
|
"@expo/ui/ExpoUI"
|
|
16
17
|
],
|
|
17
18
|
"targets": [
|
|
@@ -25,6 +26,7 @@
|
|
|
25
26
|
"React",
|
|
26
27
|
"Hermes",
|
|
27
28
|
"expo-modules-core/ExpoModulesCore",
|
|
29
|
+
"expo-modules-core/ExpoModulesWorklets",
|
|
28
30
|
"@expo/ui/ExpoUI"
|
|
29
31
|
],
|
|
30
32
|
"linkedFrameworks": [
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import Foundation
|
|
2
|
-
import JavaScriptCore
|
|
3
|
-
|
|
4
|
-
func createWidgetContext(layout: String) -> JSContext? {
|
|
5
|
-
guard let context = JSContext() else {
|
|
6
|
-
return nil
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
// Inject ExpoUI bundle
|
|
10
|
-
guard let bundleURL = Bundle.main.url(forResource: "ExpoWidgets", withExtension: "bundle"),
|
|
11
|
-
let bundle = Bundle(url: bundleURL),
|
|
12
|
-
let url = bundle.url(forResource: "ExpoWidgets", withExtension: "bundle"),
|
|
13
|
-
let bundleJS = try? String(contentsOf: url, encoding: .utf8) else {
|
|
14
|
-
print("[ExpoWidgets] Missing ExpoWidgets.bundle")
|
|
15
|
-
return nil
|
|
16
|
-
}
|
|
17
|
-
context.evaluateScript(bundleJS)
|
|
18
|
-
|
|
19
|
-
// Inject layout
|
|
20
|
-
let layoutValue = context.evaluateScript("(\(layout))")
|
|
21
|
-
context.setObject(layoutValue, forKeyedSubscript: "__expoWidgetLayout" as NSString)
|
|
22
|
-
return context
|
|
23
|
-
}
|