Der*_*key 6 objective-c objective-c++ protocol-buffers
我想在iOS项目中使用Protocol Buffers.我试图避免将整个项目变成Objective-C++惨败,所以我想将C++ protobuf类包装成Objective-C类.我有几十个protobuf消息,虽然我一次成功地完成了一个类,但理想情况下我想使用继承来最小化重复的代码.我是Objective-C的新手,我在10年内没有使用过我对C++的了解,所以这主要是一种令人沮丧的练习.下面是我如何包装单个邮件的示例.
码
.proto:
message MessageA {
optional string value = 1;
}
Run Code Online (Sandbox Code Playgroud)
MessageAWrapper.h:
#import <Foundation/Foundation.h>
@interface MessageAWrapper : NSObject
@property (nonatomic) NSString *value;
+ (id)fromString:(NSString *)string;
- (NSString *)serialize;
@end
Run Code Online (Sandbox Code Playgroud)
MessageAWrapper.mm:
#import "MessageA.h"
#import "message.pb.h"
@interface MessageAWrapper ()
@property (nonatomic) MessageA *message;
@end
@implementation MessageAWrapper
- (id)init
{
self = [super init];
if (self) {
self.message = new MessageA();
}
return self;
}
- (void)dealloc {
delete self.message;
self.message = NULL;
}
- (NSString *)value {
return [NSString stringWithUTF8String:self.message->value().c_str()];
}
- (void)setValue:(NSString *)value {
self.message->set_value([value UTF8String]);
}
- (NSString *)serialize {
std::string output;
self.message->SerializeToString(&output);
return [NSString stringWithUTF8String:output.c_str()];
}
+ (id)fromString:(NSString *)string {
MessageA *message = new MessageA();
message->ParseFromString([string UTF8String]);
MessageAWrapper *wrapper = [[MessageAWrapper alloc] init];
wrapper.message = message;
return wrapper;
}
@end
Run Code Online (Sandbox Code Playgroud)
目标
有很多在这里的代码将被重复数十次,其中唯一的变化是包装类类型(init,dealloc,serialize,fromString),所以我非常希望把它放在一个父ProtobufMesssage类代替.不幸的是,我没有成功完成这项工作,因为我无法找到父类知道其子节点正在使用的类的方法,例如在init和中fromString.
我试过的事情
我遇到过的障碍
Message或MessageLite)的引用,因为它们是抽象的正如我所说,我对C++或Objective-C的理解很少; 我的大部分经验都是使用更高级的语言,如Python和Java(虽然我主要理解像指针这样的基本C语言).
这可能甚至不可能吗?我接近错误或遗漏了一些明显的东西吗?任何帮助将非常感激.谢谢.
我对 C++ 不太了解,但是你不能将 Objective-C 属性声明为 a 吗Message *?
您已经通过在 .mm 文件中声明属性将 C++ 代码与标头分离,您将遇到的问题是由编译器命名的实例方法(value()和set_value()),并且仅是子类的有效方法。使用Reflection该类按字段名称获取和设置字段可能会有所帮助。以下是 Google 的摘录,message.h显示了这一点:
Message* foo = new Foo;
const Descriptor* descriptor = foo->GetDescriptor();
const FieldDescriptor* text_field = descriptor->FindFieldByName("text");
assert(text_field != NULL);
assert(text_field->type() == FieldDescriptor::TYPE_STRING);
assert(text_field->label() == FieldDescriptor::LABEL_OPTIONAL);
const Reflection* reflection = foo->GetReflection();
assert(reflection->GetString(foo, text_field) == "Hello World!");
Run Code Online (Sandbox Code Playgroud)
您可以创建 Objective-C-objectForKey:和-setObject:forKey:实例方法来进行类型检查并获取或设置值(令人困惑的是,在 的情况下的键MessageAWrapper是@"value")。您的子类甚至不需要了解 C++ 代码。
您还可以将创建者函数-init和+fromString:方法分离为类似+_createNewInstance;
+(Message*)_createNewInstance{ return new MessageA(); }
Run Code Online (Sandbox Code Playgroud)
允许您的子类MessageWrapper重用除创建 C++ 对象之外的所有代码。
| 归档时间: |
|
| 查看次数: |
890 次 |
| 最近记录: |