2016-12-16 84 views
1

我在尋找Unit(symbol: String)類型的初始化程序,它會識別,未定義符號。從字符串初始化單元

下面是一個代碼片段,通過向其提供有限解決方案來說明我的問題。

雖然下面的工作方案,明確列出在Foundation框架預定義了所有單位是乏味的,沒有隱含的向前兼容性應該在蘋果的iOS即將更新推出新單位。

func matchedUnit<S: Sequence>(symbol: String, valid sequence: S) -> S.Iterator.Element? where S.Iterator.Element: Unit { 
    let symbols = sequence.map { $0.symbol }; 
    let candidate = zip(sequence, symbols).first { 
     return $0.1 == symbol; 
     }?.0 
    return candidate; 
} 

let knownUnitsOfLength = [UnitLength.meters, UnitLength.centimeters, UnitLength.kilometers, UnitLength.decimeters]; 

if let aUnit = matchedUnit(symbol: "dm", valid: knownUnitsOfLength) { 
    let measurement = Measurement(value: 1, unit: aUnit); 
} 

也許我錯過了SDK中一個明顯的難題 - 識別符號而不是定義一個符號的初始化工具?

UPDATE:

已經證實,有沒有蘋果提供的API來做到這一點。我最終使用了Objective-C運行時來查找從NSDimension繼承的所有類,並遍歷其名稱中以NSUnit開頭的所有類屬性。我映射了所有符號,類和屬性名稱,並且可以在運行時基於用戶提供的符號創建NSUnit實例。

當然,在語言支持方面,它與NSMeasurementFormatter不在同一水平。 但是我會自動獲得Apple推出的任何新單位和符號的未來版本。

下面是一個示例客戶端代碼:

NSUnit *kg = [NSUnit unitRecognizingSymbol:@"kg"]; 
NSMeasurement *mkg = [[NSMeasurement alloc] initWithDoubleValue:3.0 unit:kg]; 

NSUnit *g = [NSUnit unitRecognizingSymbol:@"g"]; 
NSMeasurement *mg = [[NSMeasurement alloc] initWithDoubleValue:200 unit:g]; 

NSMeasurement *total = [mkg measurementByAddingMeasurement:mg]; 

NSMeasurementFormatter *formatter = [[NSMeasurementFormatter alloc] init]; 
[formatter setUnitOptions:NSMeasurementFormatterUnitOptionsProvidedUnit]; 

NSLog(@"%@", [formatter stringFromMeasurement:total]); 
// 3.2 kg 

而且這裏是實施方的核心部分是什麼樣子。

// Count receives its value from objc_copyClassList(). 
unsigned int classCount; 
Class *classes = objc_copyClassList(&classCount); 
// Inspect all available classes. 
for (int classIterator = 0; classIterator < classCount; classIterator++) { 
    char const *className = class_getName(classes[classIterator]); 

    // Classes we are looking for are derived from NSDimension or NSUnit. 
    Class superClass = class_getSuperclass(classes[classIterator]); 
    char const *superClassName = class_getName(superClass); 

    // Single out NSDimension exception because NSDimension itself inherits from NSUnit. 
    if ((strcmp(superClassName, "NSDimension") == 0 || strcmp(superClassName, "NSUnit") == 0) && strcmp(className, "NSDimension") != 0) { 
     // To access available class properties, gain access to meta class. 
     Class meta = objc_getMetaClass(class_getName(classes[classIterator])); 

     // Count receives its value from class_copyPropertyList() 
     unsigned int propertyCount = 0; 
     objc_property_t *properties = class_copyPropertyList(meta, &propertyCount); 
     // Inspect all available class properties. 
     for (int propertyIterator = 0; propertyIterator < propertyCount; propertyIterator++) { 
      char const *propertyName = property_getName(properties[propertyIterator]); 
     // ... 
    } 
    // ... 
} 
// ... 

回答

0

有沒有比你在做什麼更好的辦法,因爲NSMeasurementFormatter只運行一個方法 - 它使一個字符串,從測量,而不是周圍的其他方式。你的方法可能有很大的缺陷,因爲你沒有考慮到測量格式器知道如何去做的區域設置(對於它的一個方向)。如果您希望看到內置的內容,則可以向Apple提交增強請求。