C 结构体、NSObjects、float、int、double、
首先:这是一个虽然很抱歉的问题,但我希望有人能帮助我!
我正在 iPhone 上制作 UIML 渲染器。 UIML是一种描述界面的语言。 我想渲染 XML 并在 iPhone 上显示界面。
为了更好地告诉您,我首先解释一下我在做什么:
<?xml version="1.0"?>
<uiml>
<interface>
<structure>
<part id="hoofdView" class="ViewController">
<part id="viewVoorHoofdview" class="View">
<part id="label1" class="Label"/>
</part>
</part>
</structure>
<style>
<property part-name="label1" name="text">Dit is een label</property>
<property part-name="label1" name="position">50,50,100,150</property>
</style>
</interface>
<peers>
<presentation base="cocoa.uiml"/>
</peers>
</uiml>
这是一个 UIML 文档(一个界面)。这是一个简单的 ViewController,带有一个视图和一个带有文本“Dit is een label”的标签。 我正在做一些非常抽象的东西。
当我解析文档时,我发现 class="ViewController"
然后我们必须查看词汇表:
<d-class id="Label" used-in-tag="part" maps-type="class" maps-to="UILabel">
<d-property id="text" return-type="NSString*" maps-type="getMethod" maps-to="text"/>
<d-property id="text" maps-type="setMethod" maps-to="setText:">
<d-param type="NSString*"/>
</d-property>
<d-property id="position" maps-type="setMethod" maps-to="setFrame:">
<d-param type="CGRect"/>
</d-property>
</d-class>
为了方便大家,我简单地粘贴了部分词汇表。
在这个词汇表中,我们发现:
<d-class id="Label" used-in-tag="part" maps-type="class" maps-to="UILabel">
我正在运行时创建一个 UILabel:
NSObject * createdObject = [[NSClassFromString(className) alloc] init];
然后我必须将属性应用到createdObject。 我们有 2 个属性:文本和位置。
我们在词汇表中查找它们(让我们以位置为例)
<d-property id="position" maps-type="setMethod" maps-to="setFrame:">
<d-param type="CGRect"/>
</d-property>
如您所见,我需要映射到和 d 参数来调用该方法。 但有一个问题:在第一个文档中,我们有:
<property part-name="label1" name="position">50,50,100,150</property>
首先,我必须将字符串 50,50,100,150 “解码”为 CGRect,因为 setFrame: 需要 CGRect 作为参数。但有一个大问题。我必须使它非常抽象,但 CGRect 不是从 NSObject 继承的,因此我无法创建函数,
-(NSObject*)convert:(NSString*)stringToConvert;
因为 CGRect 不是 NSObject*。
当我必须传递一个浮点数(例如传递给 UISlider)时,也会出现同样的问题,
<d-property id="minimumValue" maps-type="setMethod" maps-to="setMinimumValue:">
<d-param type="float"/>
</d-property>
我无法返回浮点数,因为 NSObject 不是它的超类。
我的转换方法如下所示:
-(NSObject *)convert:(NSString *)data parameterType:(NSString *)paramType {
NSObject * result;
if ( [paramType isEqualToString:@"NSString*"] ) {
result = data;
} else if ([paramType isEqualToString:@"float"]) {
//HOW TO DO THIS?
} else if ([paramType isEqualToString:@"CGRect"]) {
//HOW TO DO THIS?
} else {
NSLog(@"TypeDecoder: No decoding method found for the given parameter Type: %@", paramType);
}
return result;
}
我调用它的方法非常抽象,并且必须是抽象的,因为我们希望扩展 UIML 文档(词汇)而不添加代码。 这是调用它的方法:
-(void)invokeMethod:(Uproperty*)property dProperty:(DProperty *)dProperty guiElement:(NSObject *)object {
//Prepare the invocation
SEL selector = NSSelectorFromString(dProperty.m_mapsTo);
NSMethodSignature * signature = [ [object class] instanceMethodSignatureForSelector:selector];
NSInvocation * invocation = [NSInvocation invocationWithMethodSignature:signature];
//target, selector, arguments
[invocation setTarget:object];
[invocation setSelector:selector];
//Convert the argument to the correct type with the type decoder
DParam *dParam = [dProperty.m_dParams lastObject];
NSObject * argument = [m_decoder convert:property.m_data parameterType:dParam.m_type]; //only 1 d-param
//Then we can set the argument
[invocation setArgument:&argument atIndex:2]; //2 is the first parameter (0 = self, 1 = _cmd)
//Invoke the method
[invocation invoke];
}
抱歉这个难题,但我希望有人可以帮助我!
First of all: this is a though question, sorry for that, but I hope someone can help me!
I'm making a UIML renderer on the iPhone. UIML is a language to describe interfaces.
I want to render the XML and show the Interface on the iPhone.
To inform you bettter, i first explain what I'm doing:
<?xml version="1.0"?>
<uiml>
<interface>
<structure>
<part id="hoofdView" class="ViewController">
<part id="viewVoorHoofdview" class="View">
<part id="label1" class="Label"/>
</part>
</part>
</structure>
<style>
<property part-name="label1" name="text">Dit is een label</property>
<property part-name="label1" name="position">50,50,100,150</property>
</style>
</interface>
<peers>
<presentation base="cocoa.uiml"/>
</peers>
</uiml>
This is a UIML document (an interface). It's a simple ViewController with a View and a Label with text "Dit is een label".
I'm making something very abstract.
When I parse the document, I find class="ViewController"
Then we have to look into the vocabulary:
<d-class id="Label" used-in-tag="part" maps-type="class" maps-to="UILabel">
<d-property id="text" return-type="NSString*" maps-type="getMethod" maps-to="text"/>
<d-property id="text" maps-type="setMethod" maps-to="setText:">
<d-param type="NSString*"/>
</d-property>
<d-property id="position" maps-type="setMethod" maps-to="setFrame:">
<d-param type="CGRect"/>
</d-property>
</d-class>
To make it easy for you guys, I simply paste a part of the vocabulary.
In this vocabulary, we find:
<d-class id="Label" used-in-tag="part" maps-type="class" maps-to="UILabel">
And I'm making at run-time a UILabel:
NSObject * createdObject = [[NSClassFromString(className) alloc] init];
Then I have to apply the properties to the createdObject.
We have 2 properties: text and position.
We look for them in the vocabulary (let's take position for example)
<d-property id="position" maps-type="setMethod" maps-to="setFrame:">
<d-param type="CGRect"/>
</d-property>
As you can see, I need the maps-to and the d-param for invoking the method.
But there's one problem: In the first document we have:
<property part-name="label1" name="position">50,50,100,150</property>
First of all, I have to "decode" the string 50,50,100,150 to a CGRect because setFrame: needs a CGRect as parameter. But there's one big problem. I have to make this very abstract, but CGRect is not inherited from NSObject, and therefore I cannot make a function
-(NSObject*)convert:(NSString*)stringToConvert;
Because CGRect is not a NSObject*.
The same problem occurs when I have to pass a float (for example to a UISlider)
<d-property id="minimumValue" maps-type="setMethod" maps-to="setMinimumValue:">
<d-param type="float"/>
</d-property>
I cannot return a float because NSObject is not its superclass.
My convert-method looks like this:
-(NSObject *)convert:(NSString *)data parameterType:(NSString *)paramType {
NSObject * result;
if ( [paramType isEqualToString:@"NSString*"] ) {
result = data;
} else if ([paramType isEqualToString:@"float"]) {
//HOW TO DO THIS?
} else if ([paramType isEqualToString:@"CGRect"]) {
//HOW TO DO THIS?
} else {
NSLog(@"TypeDecoder: No decoding method found for the given parameter Type: %@", paramType);
}
return result;
}
And the method where I'm calling this from is very abstract, and has to be abstract, because we want to extend the UIML document (vocabulary) without adding code.
This is the method where this is invoked from:
-(void)invokeMethod:(Uproperty*)property dProperty:(DProperty *)dProperty guiElement:(NSObject *)object {
//Prepare the invocation
SEL selector = NSSelectorFromString(dProperty.m_mapsTo);
NSMethodSignature * signature = [ [object class] instanceMethodSignatureForSelector:selector];
NSInvocation * invocation = [NSInvocation invocationWithMethodSignature:signature];
//target, selector, arguments
[invocation setTarget:object];
[invocation setSelector:selector];
//Convert the argument to the correct type with the type decoder
DParam *dParam = [dProperty.m_dParams lastObject];
NSObject * argument = [m_decoder convert:property.m_data parameterType:dParam.m_type]; //only 1 d-param
//Then we can set the argument
[invocation setArgument:&argument atIndex:2]; //2 is the first parameter (0 = self, 1 = _cmd)
//Invoke the method
[invocation invoke];
}
Sorry for this difficult question, but I hope someone can help me!!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您可能想要为所有不是 NSObject 子类的类型构建包装类。
一个例子是 NSNumber 作为浮点数、整数等的对象包装器。
You may want to build wrapper classes for all the types that are not a subclass of NSObject.
An example is NSNumber as an object wrapper for floats, ints etc.