0

首先:这是一个问题,很抱歉,但我希望有人能帮助我!

我正在 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,带有一个 View 和一个带有文本“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>

如您所见,我需要 maps-to 和 d-param 来调用该方法。但是有一个问题:在第一个文档中,我们有:

<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 文档(词汇表)。这是从中调用 this 的方法:

-(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];
}

对不起这个困难的问题,但我希望有人能帮助我!

4

1 回答 1

0

您可能希望为所有不是 NSObject 子类的类型构建包装类。一个例子是 NSNumber 作为浮点数、整数等的对象包装器。

于 2010-03-24T22:22:17.673 回答