Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 1c941ac

Browse files
committed
Removed superfluous copy operations in iOS flutter platform messages.
1 parent 1539c48 commit 1c941ac

File tree

5 files changed

+93
-21
lines changed

5 files changed

+93
-21
lines changed

shell/platform/darwin/common/buffer_conversions.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,9 @@
1313

1414
namespace flutter {
1515

16-
std::vector<uint8_t> GetVectorFromNSData(NSData* data);
16+
std::vector<uint8_t> CopyNSDataToVector(NSData* data);
1717

18-
NSData* GetNSDataFromVector(const std::vector<uint8_t>& buffer);
19-
20-
std::unique_ptr<fml::Mapping> GetMappingFromNSData(NSData* data);
21-
22-
NSData* GetNSDataFromMapping(std::unique_ptr<fml::Mapping> mapping);
18+
std::unique_ptr<fml::Mapping> CopyNSDataToMapping(NSData* data);
2319

2420
} // namespace flutter
2521

shell/platform/darwin/common/buffer_conversions.mm

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,13 @@
66

77
namespace flutter {
88

9-
std::vector<uint8_t> GetVectorFromNSData(NSData* data) {
9+
std::vector<uint8_t> CopyNSDataToVector(NSData* data) {
1010
const uint8_t* bytes = reinterpret_cast<const uint8_t*>(data.bytes);
1111
return std::vector<uint8_t>(bytes, bytes + data.length);
1212
}
1313

14-
NSData* GetNSDataFromVector(const std::vector<uint8_t>& buffer) {
15-
return [NSData dataWithBytes:buffer.data() length:buffer.size()];
16-
}
17-
18-
std::unique_ptr<fml::Mapping> GetMappingFromNSData(NSData* data) {
19-
return std::make_unique<fml::DataMapping>(GetVectorFromNSData(data));
20-
}
21-
22-
NSData* GetNSDataFromMapping(std::unique_ptr<fml::Mapping> mapping) {
23-
return [NSData dataWithBytes:mapping->GetMapping() length:mapping->GetSize()];
14+
std::unique_ptr<fml::Mapping> CopyNSDataToMapping(NSData* data) {
15+
return std::make_unique<fml::DataMapping>(CopyNSDataToVector(data));
2416
}
2517

2618
} // namespace flutter

shell/platform/darwin/ios/framework/Source/FlutterEngine.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -807,7 +807,7 @@ - (void)sendOnChannel:(NSString*)channel
807807
fml::RefPtr<flutter::PlatformMessage> platformMessage =
808808
(message == nil) ? fml::MakeRefCounted<flutter::PlatformMessage>(channel.UTF8String, response)
809809
: fml::MakeRefCounted<flutter::PlatformMessage>(
810-
channel.UTF8String, flutter::GetVectorFromNSData(message), response);
810+
channel.UTF8String, flutter::CopyNSDataToVector(message), response);
811811

812812
_shell->GetPlatformView()->DispatchPlatformMessage(platformMessage);
813813
}

shell/platform/darwin/ios/framework/Source/platform_message_response_darwin.mm

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,47 @@
44

55
#import "flutter/shell/platform/darwin/ios/framework/Source/platform_message_response_darwin.h"
66

7+
/// A proxy object that behaves like NSData represented in a Mapping.
8+
/// This isn't a subclass of NSData because NSData is in a class cluster.
9+
@interface FlutterMappingData : NSObject
10+
@end
11+
12+
@implementation FlutterMappingData {
13+
NSData* _data;
14+
std::unique_ptr<fml::Mapping> _mapping;
15+
}
16+
17+
+ (NSData*)dataWithMapping:(std::unique_ptr<fml::Mapping>)mapping {
18+
return (NSData*)[[[FlutterMappingData alloc] initWithMapping:std::move(mapping)] autorelease];
19+
}
20+
21+
- (instancetype)initWithMapping:(std::unique_ptr<fml::Mapping>)mapping {
22+
self = [super init];
23+
if (self) {
24+
const void* rawData = mapping->GetMapping();
25+
26+
// Const cast is required because the NSData API requires it despite
27+
// guarentees that the buffer won't be deleted or modified.
28+
_data = [[NSData alloc] initWithBytesNoCopy:const_cast<void*>(rawData)
29+
length:mapping->GetSize()
30+
freeWhenDone:NO];
31+
32+
_mapping = std::move(mapping);
33+
}
34+
return self;
35+
}
36+
37+
- (void)dealloc {
38+
[_data release];
39+
[super dealloc];
40+
}
41+
42+
- (id)forwardingTargetForSelector:(SEL)aSelector {
43+
return _data;
44+
}
45+
46+
@end
47+
748
namespace flutter {
849

950
PlatformMessageResponseDarwin::PlatformMessageResponseDarwin(
@@ -17,7 +58,8 @@
1758
void PlatformMessageResponseDarwin::Complete(std::unique_ptr<fml::Mapping> data) {
1859
fml::RefPtr<PlatformMessageResponseDarwin> self(this);
1960
platform_task_runner_->PostTask(fml::MakeCopyable([self, data = std::move(data)]() mutable {
20-
self->callback_.get()(GetNSDataFromMapping(std::move(data)));
61+
NSData* callbackData = [FlutterMappingData dataWithMapping:std::move(data)];
62+
self->callback_.get()(callbackData);
2163
}));
2264
}
2365

shell/platform/darwin/ios/framework/Source/platform_message_router.mm

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,48 @@
88

99
#import "flutter/shell/platform/darwin/common/buffer_conversions.h"
1010

11+
/// A proxy object that behaves like NSData represented in a PlatformMessage.
12+
/// This isn't a subclass of NSData because NSData is in a class cluster.
13+
@interface FlutterMessageData : NSObject
14+
@end
15+
16+
@implementation FlutterMessageData {
17+
NSData* _data;
18+
fml::RefPtr<flutter::PlatformMessage> _platformMessage;
19+
}
20+
21+
+ (NSData*)dataWithMessage:(fml::RefPtr<flutter::PlatformMessage>)platformMessage {
22+
return (NSData*)[[[FlutterMessageData alloc] initWithMessage:std::move(platformMessage)]
23+
autorelease];
24+
}
25+
26+
- (instancetype)initWithMessage:(fml::RefPtr<flutter::PlatformMessage>)platformMessage {
27+
self = [super init];
28+
if (self) {
29+
const void* rawData = platformMessage->data().data();
30+
31+
// Const cast is required because the NSData API requires it despite
32+
// guarentees that the buffer won't be deleted or modified.
33+
_data = [[NSData alloc] initWithBytesNoCopy:const_cast<void*>(rawData)
34+
length:platformMessage->data().size()
35+
freeWhenDone:NO];
36+
37+
_platformMessage = std::move(platformMessage);
38+
}
39+
return self;
40+
}
41+
42+
- (void)dealloc {
43+
[_data release];
44+
[super dealloc];
45+
}
46+
47+
- (id)forwardingTargetForSelector:(SEL)aSelector {
48+
return _data;
49+
}
50+
51+
@end
52+
1153
namespace flutter {
1254

1355
PlatformMessageRouter::PlatformMessageRouter() = default;
@@ -22,12 +64,12 @@
2264
FlutterBinaryMessageHandler handler = it->second;
2365
NSData* data = nil;
2466
if (message->hasData()) {
25-
data = GetNSDataFromVector(message->data());
67+
data = [FlutterMessageData dataWithMessage:std::move(message)];
2668
}
2769
handler(data, ^(NSData* reply) {
2870
if (completer) {
2971
if (reply) {
30-
completer->Complete(GetMappingFromNSData(reply));
72+
completer->Complete(CopyNSDataToMapping(reply));
3173
} else {
3274
completer->CompleteEmpty();
3375
}

0 commit comments

Comments
 (0)