Skip to content

Commit 0ffaff8

Browse files
dheerajkoppumeta-codesync[bot]
authored andcommitted
Avoid unnecessary AttributedString copies on iOS (#59018)
Summary: Measuring `<Text>` on iOS makes a bunch of unnecessary copies of `AttributedString`. There are a few places where this happens: - `ParagraphShadowNode` copies a local string into `AttributedStringBox` even though the local is about to be destroyed. - `TextLayoutManager::measure` uses `auto` instead of a reference, which makes another copy. - `ensurePlaceholderIfEmpty_DO_NOT_USE` copies the string even when it's not empty. - The `RCTTextLayoutManager` methods take the string by value, which also copies it. This PR avoids those extra copies by using `std::move`, passing references where possible, and only creating a placeholder when the string is actually empty. Nothing changes in how text is rendered. With these changes, a cache hit goes from **5 copies to 2**, and a cache miss goes from **11 to 6**. Draw, hit-testing, and frame updates go from **2 copies to 0**. The remaining copies mostly come from cache keys, which I left alone. It's a pretty small cleanup, but it removes some unnecessary work. I also ran a quick benchmark on an M4 Pro using clang `-O2`, taking the median of 7 runs: | Fragments | Deep copy | Box creation (before → after) | measure() entry (before → after) | |---|---|---|---| | 1 | 41 ns | 87 → 52 ns | 77 → 1 ns | | 3 | 76 ns | 160 → 89 ns | 150 → 1 ns | | 10 | 211 ns | 436 → 227 ns | 427 → 1 ns | <details> <summary>Benchmark code</summary> ```cpp #include <react/renderer/attributedstring/AttributedString.h> #include <react/renderer/attributedstring/AttributedStringBox.h> #include <react/renderer/attributedstring/PlaceholderAttributedString.h> #include <algorithm> #include <chrono> #include <cstdio> #include <memory> #include <optional> #include <vector> using namespace facebook::react; static AttributedString makeString(int fragmentCount) { AttributedString attributedString; auto owner = std::make_shared<int>(0); for (int i = 0; i < fragmentCount; i++) { AttributedString::Fragment fragment; fragment.string = "This is a typical row label in a list"; fragment.textAttributes.fontSize = 16; fragment.parentShadowView.tag = i + 1; // Aliasing shared_ptrs: real refcount traffic without constructing Props/EventEmitter/State. fragment.parentShadowView.props = std::shared_ptr<const Props>(owner, nullptr); fragment.parentShadowView.eventEmitter = std::shared_ptr<EventEmitter>(owner, nullptr); fragment.parentShadowView.state = std::shared_ptr<const State>(owner, nullptr); attributedString.appendFragment(std::move(fragment)); } return attributedString; } template <typename F> static double nsPerIteration(F&& body, int iterations) { std::vector<double> samples; for (int run = 0; run < 7; run++) { auto start = std::chrono::steady_clock::now(); for (int i = 0; i < iterations; i++) body(); auto end = std::chrono::steady_clock::now(); samples.push_back(std::chrono::duration<double, std::nano>(end - start).count() / iterations); } std::sort(samples.begin(), samples.end()); return samples[3]; } #define ESCAPE(x) asm volatile("" : : "r"(&(x)) : "memory") int main() { const int iterations = 200000; std::printf("| Fragments | Deep copy | Box from lvalue (before) | Box from rvalue (after) | measure() entry before | measure() entry after |\n"); std::printf("|---|---|---|---|---|---|\n"); for (int n : {1, 3, 10}) { const auto source = makeString(n); AttributedStringBox box{source}; double copy = nsPerIteration([&] { AttributedString c = source; ESCAPE(c); }, iterations); // The three ParagraphShadowNode sites: a dying local handed to the box. double boxBefore = nsPerIteration([&] { auto local = source; AttributedStringBox b{local}; ESCAPE(b); }, iterations); double boxAfter = nsPerIteration([&] { auto local = source; AttributedStringBox b{std::move(local)}; ESCAPE(b); }, iterations); // The iOS TextLayoutManager::measure entry, before and after. double entryBefore = nsPerIteration([&] { auto original = box.getValue(); auto attributedString = ensurePlaceholderIfEmpty_DO_NOT_USE(original); ESCAPE(attributedString); }, iterations); double entryAfter = nsPerIteration([&] { const auto& original = box.getValue(); auto placeholder = original.isEmpty() ? std::optional<AttributedString>{ensurePlaceholderIfEmpty_DO_NOT_USE(original)} : std::nullopt; const auto& attributedString = placeholder ? *placeholder : original; ESCAPE(attributedString); }, iterations); std::printf("| %d | %.0f ns | %.0f ns | %.0f ns | %.0f ns | %.0f ns |\n", n, copy, boxBefore, boxAfter, entryBefore, entryAfter); } } ``` </details> ## Changelog: [IOS] [CHANGED] - Pass `AttributedString` by const reference in `RCTTextLayoutManager` and add a move constructor for `AttributedStringBox`. Pull Request resolved: #59018 Test Plan: - Added `testValueMoveConstructor` to `AttributedStringBoxTest`. - `yarn fantom Text`: all 223 tests pass. - RNTester builds and runs on the iPhone 18 Pro simulator, and all 172 `RNTesterUnitTests` pass. - `yarn format-check-cpp` passes. - Updated API snapshots. - Haven't benchmarked this on a physical device yet. Reviewed By: cipolleschi Differential Revision: D124965503 Pulled By: javache fbshipit-source-id: e7e0add9aeb1dc90768ad852b0446f9804bcc83c
1 parent 51c4ef2 commit 0ffaff8

11 files changed

Lines changed: 69 additions & 29 deletions

File tree

‎packages/react-native/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727

2828
@interface RCTTextLayoutManager (RCTParagraphComponentViewPrivate)
2929

30-
- (CGRect)drawingFrameForAttributedString:(facebook::react::AttributedString)attributedString
30+
- (CGRect)drawingFrameForAttributedString:(const facebook::react::AttributedString &)attributedString
3131
paragraphAttributes:(facebook::react::ParagraphAttributes)paragraphAttributes
3232
frame:(CGRect)frame
3333
containerFrame:(CGRect *)containerFrame;

‎packages/react-native/ReactCommon/react/renderer/attributedstring/AttributedStringBox.cpp‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ AttributedStringBox::AttributedStringBox(const AttributedString& value)
2323
value_(std::make_shared<const AttributedString>(value)),
2424
opaquePointer_({}) {};
2525

26+
AttributedStringBox::AttributedStringBox(AttributedString&& value)
27+
: mode_(Mode::Value),
28+
value_(std::make_shared<const AttributedString>(std::move(value))),
29+
opaquePointer_({}) {};
30+
2631
AttributedStringBox::AttributedStringBox(std::shared_ptr<void> opaquePointer)
2732
: mode_(Mode::OpaquePointer),
2833
value_({}),

‎packages/react-native/ReactCommon/react/renderer/attributedstring/AttributedStringBox.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class AttributedStringBox final {
3737
* Custom explicit constructors.
3838
*/
3939
explicit AttributedStringBox(const AttributedString &value);
40+
explicit AttributedStringBox(AttributedString &&value);
4041
explicit AttributedStringBox(std::shared_ptr<void> opaquePointer);
4142

4243
/*

‎packages/react-native/ReactCommon/react/renderer/attributedstring/tests/AttributedStringBoxTest.cpp‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,18 @@ TEST(AttributedStringBoxTest, testValueConstructor) {
3030
EXPECT_EQ(attributedStringBox.getValue(), attributedString);
3131
}
3232

33+
TEST(AttributedStringBoxTest, testValueMoveConstructor) {
34+
auto attributedString = AttributedString{};
35+
auto fragment = AttributedString::Fragment{};
36+
fragment.string = "test string";
37+
attributedString.appendFragment(std::move(fragment));
38+
auto expectedAttributedString = attributedString;
39+
auto attributedStringBox = AttributedStringBox{std::move(attributedString)};
40+
41+
EXPECT_EQ(attributedStringBox.getMode(), AttributedStringBox::Mode::Value);
42+
EXPECT_EQ(attributedStringBox.getValue(), expectedAttributedString);
43+
}
44+
3345
TEST(AttributedStringBoxTest, testOpaquePointerConstructor) {
3446
auto string = std::make_shared<std::string>("test string");
3547
auto attributedStringBox = AttributedStringBox{string};

‎packages/react-native/ReactCommon/react/renderer/components/text/ParagraphShadowNode.cpp‎

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,9 @@ const Content& ParagraphShadowNode::getContent(
8888
attributedString.setBaseTextAttributes(textAttributes);
8989

9090
content_ = Content{
91-
attributedString, getConcreteProps().paragraphAttributes, attachments};
91+
.attributedString = std::move(attributedString),
92+
.paragraphAttributes = getConcreteProps().paragraphAttributes,
93+
.attachments = std::move(attachments)};
9294

9395
return content_.value();
9496
}
@@ -264,7 +266,7 @@ Size ParagraphShadowNode::measureContent(
264266

265267
auto size = textLayoutManager_
266268
->measure(
267-
AttributedStringBox{content.attributedString},
269+
AttributedStringBox{std::move(content.attributedString)},
268270
content.paragraphAttributes,
269271
textLayoutContext,
270272
layoutConstraints)
@@ -282,7 +284,7 @@ Float ParagraphShadowNode::baseline(
282284
auto content =
283285
getContentWithMeasuredAttachments(layoutContext, layoutConstraints);
284286

285-
AttributedStringBox attributedStringBox{content.attributedString};
287+
AttributedStringBox attributedStringBox{std::move(content.attributedString)};
286288

287289
if constexpr (TextLayoutManagerExtended::supportsLineMeasurement()) {
288290
auto lines =
@@ -346,7 +348,9 @@ void ParagraphShadowNode::layout(LayoutContext layoutContext) {
346348
.pointScaleFactor = layoutContext.pointScaleFactor,
347349
.surfaceId = getSurfaceId(),
348350
};
349-
AttributedStringBox attributedStringBox{content.attributedString};
351+
// The state update above already captured the attributed string and
352+
// nothing below reads it, so the box can take it instead of copying it.
353+
AttributedStringBox attributedStringBox{std::move(content.attributedString)};
350354

351355
if (getConcreteProps().onTextLayout) {
352356
if constexpr (TextLayoutManagerExtended::supportsLineMeasurement()) {

‎packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.h‎

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ using RCTTextLayoutFragmentEnumerationBlock =
2929
*/
3030
@interface RCTTextLayoutManager : NSObject
3131

32-
- (facebook::react::TextMeasurement)measureAttributedString:(facebook::react::AttributedString)attributedString
32+
- (facebook::react::TextMeasurement)measureAttributedString:(const facebook::react::AttributedString &)attributedString
3333
paragraphAttributes:(facebook::react::ParagraphAttributes)paragraphAttributes
3434
layoutContext:(facebook::react::TextLayoutContext)layoutContext
3535
layoutConstraints:(facebook::react::LayoutConstraints)layoutConstraints;
@@ -39,23 +39,23 @@ using RCTTextLayoutFragmentEnumerationBlock =
3939
layoutContext:(facebook::react::TextLayoutContext)layoutContext
4040
layoutConstraints:(facebook::react::LayoutConstraints)layoutConstraints;
4141

42-
- (void)drawAttributedString:(facebook::react::AttributedString)attributedString
42+
- (void)drawAttributedString:(const facebook::react::AttributedString &)attributedString
4343
paragraphAttributes:(facebook::react::ParagraphAttributes)paragraphAttributes
4444
frame:(CGRect)frame
4545
drawHighlightPath:(void (^_Nullable)(UIBezierPath *highlightPath))block;
4646

47-
- (facebook::react::LinesMeasurements)getLinesForAttributedString:(facebook::react::AttributedString)attributedString
48-
paragraphAttributes:
49-
(facebook::react::ParagraphAttributes)paragraphAttributes
50-
size:(CGSize)size;
47+
- (facebook::react::LinesMeasurements)
48+
getLinesForAttributedString:(const facebook::react::AttributedString &)attributedString
49+
paragraphAttributes:(facebook::react::ParagraphAttributes)paragraphAttributes
50+
size:(CGSize)size;
5151

5252
- (std::shared_ptr<const facebook::react::EventEmitter>)
53-
getEventEmitterWithAttributeString:(facebook::react::AttributedString)attributedString
53+
getEventEmitterWithAttributeString:(const facebook::react::AttributedString &)attributedString
5454
paragraphAttributes:(facebook::react::ParagraphAttributes)paragraphAttributes
5555
frame:(CGRect)frame
5656
atPoint:(CGPoint)point;
5757

58-
- (void)getRectWithAttributedString:(facebook::react::AttributedString)attributedString
58+
- (void)getRectWithAttributedString:(const facebook::react::AttributedString &)attributedString
5959
paragraphAttributes:(facebook::react::ParagraphAttributes)paragraphAttributes
6060
enumerateAttribute:(NSString *)enumerateAttribute
6161
frame:(CGRect)frame

‎packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ - (TextMeasurement)measureNSAttributedString:(NSAttributedString *)attributedStr
5959
return [self _measureTextStorage:textStorage paragraphAttributes:paragraphAttributes layoutContext:layoutContext];
6060
}
6161

62-
- (TextMeasurement)measureAttributedString:(AttributedString)attributedString
62+
- (TextMeasurement)measureAttributedString:(const AttributedString &)attributedString
6363
paragraphAttributes:(ParagraphAttributes)paragraphAttributes
6464
layoutContext:(TextLayoutContext)layoutContext
6565
layoutConstraints:(LayoutConstraints)layoutConstraints
@@ -70,7 +70,7 @@ - (TextMeasurement)measureAttributedString:(AttributedString)attributedString
7070
layoutConstraints:layoutConstraints];
7171
}
7272

73-
- (CGRect)drawingFrameForAttributedString:(AttributedString)attributedString
73+
- (CGRect)drawingFrameForAttributedString:(const AttributedString &)attributedString
7474
paragraphAttributes:(ParagraphAttributes)paragraphAttributes
7575
frame:(CGRect)frame
7676
containerFrame:(CGRect *)containerFrame
@@ -128,7 +128,7 @@ - (CGRect)drawingFrameForAttributedString:(AttributedString)attributedString
128128
return drawingFrame;
129129
}
130130

131-
- (void)drawAttributedString:(AttributedString)attributedString
131+
- (void)drawAttributedString:(const AttributedString &)attributedString
132132
paragraphAttributes:(ParagraphAttributes)paragraphAttributes
133133
frame:(CGRect)frame
134134
drawHighlightPath:(void (^_Nullable)(UIBezierPath *highlightPath))block
@@ -363,7 +363,7 @@ - (void)processTruncatedAttributedText:(NSTextStorage *)textStorage
363363
}
364364
}
365365

366-
- (LinesMeasurements)getLinesForAttributedString:(facebook::react::AttributedString)attributedString
366+
- (LinesMeasurements)getLinesForAttributedString:(const facebook::react::AttributedString &)attributedString
367367
paragraphAttributes:(facebook::react::ParagraphAttributes)paragraphAttributes
368368
size:(CGSize)size
369369
{
@@ -467,7 +467,7 @@ - (NSTextStorage *)_textStorageAndLayoutManagerWithAttributesString:(NSAttribute
467467
return textStorage;
468468
}
469469

470-
- (std::shared_ptr<const EventEmitter>)getEventEmitterWithAttributeString:(AttributedString)attributedString
470+
- (std::shared_ptr<const EventEmitter>)getEventEmitterWithAttributeString:(const AttributedString &)attributedString
471471
paragraphAttributes:(ParagraphAttributes)paragraphAttributes
472472
frame:(CGRect)frame
473473
atPoint:(CGPoint)point
@@ -497,7 +497,7 @@ - (NSTextStorage *)_textStorageAndLayoutManagerWithAttributesString:(NSAttribute
497497
return nil;
498498
}
499499

500-
- (void)getRectWithAttributedString:(AttributedString)attributedString
500+
- (void)getRectWithAttributedString:(const AttributedString &)attributedString
501501
paragraphAttributes:(ParagraphAttributes)paragraphAttributes
502502
enumerateAttribute:(NSString *)enumerateAttribute
503503
frame:(CGRect)frame
@@ -539,7 +539,7 @@ - (void)getRectWithAttributedString:(AttributedString)attributedString
539539

540540
#pragma mark - Private
541541

542-
- (NSAttributedString *)_nsAttributedStringFromAttributedString:(AttributedString)attributedString
542+
- (NSAttributedString *)_nsAttributedStringFromAttributedString:(const AttributedString &)attributedString
543543
{
544544
auto sharedNSAttributedString = _cache.get(attributedString, [&]() {
545545
return wrapManagedObject(RCTNSAttributedStringFromAttributedString(attributedString));

‎packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/TextLayoutManager.mm‎

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,23 @@
88
#import "TextLayoutManager.h"
99
#import "RCTTextLayoutManager.h"
1010

11+
#import <optional>
12+
1113
#import <react/renderer/attributedstring/PlaceholderAttributedString.h>
1214
#import <react/renderer/telemetry/TransactionTelemetry.h>
1315
#import <react/utils/ManagedObjectWrapper.h>
1416

1517
namespace facebook::react {
1618

19+
// `ensurePlaceholderIfEmpty_DO_NOT_USE` returns a copy, so only call it for an empty string that needs one.
20+
static std::optional<AttributedString> placeholderIfEmpty(const AttributedString &attributedString)
21+
{
22+
if (attributedString.isEmpty()) {
23+
return ensurePlaceholderIfEmpty_DO_NOT_USE(attributedString);
24+
}
25+
return std::nullopt;
26+
}
27+
1728
TextLayoutManager::TextLayoutManager(const std::shared_ptr<const ContextContainer> & /*contextContainer*/)
1829
{
1930
nativeTextLayoutManager_ = wrapManagedObject([RCTTextLayoutManager new]);
@@ -37,8 +48,10 @@
3748

3849
switch (attributedStringBox.getMode()) {
3950
case AttributedStringBox::Mode::Value: {
40-
auto originalAtributedString = attributedStringBox.getValue();
41-
auto attributedString = ensurePlaceholderIfEmpty_DO_NOT_USE(originalAtributedString);
51+
const auto &originalAttributedString = attributedStringBox.getValue();
52+
auto placeholderAttributedString = placeholderIfEmpty(originalAttributedString);
53+
const auto &attributedString =
54+
placeholderAttributedString ? *placeholderAttributedString : originalAttributedString;
4255

4356
measurement = textMeasureCache_.get(
4457
{.attributedString = attributedString,
@@ -60,7 +73,7 @@
6073
// being used to represent empty string. iOS TextLayoutManager
6174
// should instead measure using `baseTextAttributes` of the
6275
// `AttributedString`.
63-
if (originalAtributedString.isEmpty()) {
76+
if (originalAttributedString.isEmpty()) {
6477
measurement.size.width = 0;
6578
}
6679

@@ -106,7 +119,9 @@
106119
const Size &size) const
107120
{
108121
react_native_assert(attributedStringBox.getMode() == AttributedStringBox::Mode::Value);
109-
auto attributedString = ensurePlaceholderIfEmpty_DO_NOT_USE(attributedStringBox.getValue());
122+
const auto &originalAttributedString = attributedStringBox.getValue();
123+
auto placeholderAttributedString = placeholderIfEmpty(originalAttributedString);
124+
const auto &attributedString = placeholderAttributedString ? *placeholderAttributedString : originalAttributedString;
110125

111126
RCTTextLayoutManager *textLayoutManager = (RCTTextLayoutManager *)unwrapManagedObject(nativeTextLayoutManager_);
112127

‎scripts/cxx-api/api-snapshots/ReactAndroidFrameworksCxx.api‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1366,6 +1366,7 @@ class facebook::react::AttributedStringBox {
13661366
public AttributedStringBox();
13671367
public AttributedStringBox(const facebook::react::AttributedString& value);
13681368
public AttributedStringBox(const facebook::react::AttributedStringBox& other) = default;
1369+
public AttributedStringBox(facebook::react::AttributedString&& value);
13691370
public AttributedStringBox(facebook::react::AttributedStringBox&& other) noexcept;
13701371
public AttributedStringBox(std::shared_ptr<void> opaquePointer);
13711372
public const facebook::react::AttributedString& getValue() const;

‎scripts/cxx-api/api-snapshots/ReactAppleFrameworksCxx.api‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1939,12 +1939,12 @@ interface RCTTextInputComponentView : public RCTViewComponentView {
19391939
}
19401940

19411941
interface RCTTextLayoutManager : public NSObject {
1942-
public virtual facebook::react::LinesMeasurements getLinesForAttributedString:paragraphAttributes:size:(facebook::react::AttributedString attributedString, facebook::react::ParagraphAttributes paragraphAttributes, CGSize size);
1943-
public virtual facebook::react::TextMeasurement measureAttributedString:paragraphAttributes:layoutContext:layoutConstraints:(facebook::react::AttributedString attributedString, facebook::react::ParagraphAttributes paragraphAttributes, facebook::react::TextLayoutContext layoutContext, facebook::react::LayoutConstraints layoutConstraints);
1942+
public virtual facebook::react::LinesMeasurements getLinesForAttributedString:paragraphAttributes:size:(const facebook::react::AttributedString& attributedString, facebook::react::ParagraphAttributes paragraphAttributes, CGSize size);
1943+
public virtual facebook::react::TextMeasurement measureAttributedString:paragraphAttributes:layoutContext:layoutConstraints:(const facebook::react::AttributedString& attributedString, facebook::react::ParagraphAttributes paragraphAttributes, facebook::react::TextLayoutContext layoutContext, facebook::react::LayoutConstraints layoutConstraints);
19441944
public virtual facebook::react::TextMeasurement measureNSAttributedString:paragraphAttributes:layoutContext:layoutConstraints:(NSAttributedString* attributedString, facebook::react::ParagraphAttributes paragraphAttributes, facebook::react::TextLayoutContext layoutContext, facebook::react::LayoutConstraints layoutConstraints);
1945-
public virtual std::shared_ptr<const facebook::react::EventEmitter> getEventEmitterWithAttributeString:paragraphAttributes:frame:atPoint:(facebook::react::AttributedString attributedString, facebook::react::ParagraphAttributes paragraphAttributes, CGRect frame, CGPoint point);
1946-
public virtual void drawAttributedString:paragraphAttributes:frame:drawHighlightPath:(facebook::react::AttributedString attributedString, facebook::react::ParagraphAttributes paragraphAttributes, CGRect frame, void(^)(UIBezierPath* highlightPath) block);
1947-
public virtual void getRectWithAttributedString:paragraphAttributes:enumerateAttribute:frame:usingBlock:(facebook::react::AttributedString attributedString, facebook::react::ParagraphAttributes paragraphAttributes, NSString* enumerateAttribute, CGRect frame, RCTTextLayoutFragmentEnumerationBlock block);
1945+
public virtual std::shared_ptr<const facebook::react::EventEmitter> getEventEmitterWithAttributeString:paragraphAttributes:frame:atPoint:(const facebook::react::AttributedString& attributedString, facebook::react::ParagraphAttributes paragraphAttributes, CGRect frame, CGPoint point);
1946+
public virtual void drawAttributedString:paragraphAttributes:frame:drawHighlightPath:(const facebook::react::AttributedString& attributedString, facebook::react::ParagraphAttributes paragraphAttributes, CGRect frame, void(^)(UIBezierPath* highlightPath) block);
1947+
public virtual void getRectWithAttributedString:paragraphAttributes:enumerateAttribute:frame:usingBlock:(const facebook::react::AttributedString& attributedString, facebook::react::ParagraphAttributes paragraphAttributes, NSString* enumerateAttribute, CGRect frame, RCTTextLayoutFragmentEnumerationBlock block);
19481948
}
19491949

19501950
interface RCTTextSelection : public NSObject {
@@ -3963,6 +3963,7 @@ class facebook::react::AttributedStringBox {
39633963
public AttributedStringBox();
39643964
public AttributedStringBox(const facebook::react::AttributedString& value);
39653965
public AttributedStringBox(const facebook::react::AttributedStringBox& other) = default;
3966+
public AttributedStringBox(facebook::react::AttributedString&& value);
39663967
public AttributedStringBox(facebook::react::AttributedStringBox&& other) noexcept;
39673968
public AttributedStringBox(std::shared_ptr<void> opaquePointer);
39683969
public const facebook::react::AttributedString& getValue() const;

0 commit comments

Comments
 (0)