title: Initializing a Unit from String
body: <p>I'm looking for a <code>Unit(symbol: String)</code> kind of initializer that would <strong>recognize</strong>, not define a symbol.</p>
  
  <p>Here's a code snippet to illustrate my problem by providing <strong>a limited solution</strong> to it.</p>
  
  <p>Although the solution below works, explicitly listing all units predefined in the <em>Foundation framework</em> is tedious and does not have implicit forward compatibility should Apple release new units in upcoming iOS updates.</p>
  
  <pre><code>func matchedUnit&lt;S: Sequence&gt;(symbol: String, valid sequence: S) -&gt; 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);
  }
  </code></pre>
  
  <p>Perhaps I'm missing an obvious piece of the puzzle in the SDK - an initializer that recognizes a symbol rather than defines one?</p>
  
  <p><strong>UPDATE:</strong></p>
  
  <p>It has been confirmed that there is no Apple provided API to do that. I ended up using <em>Objective-C runtime</em> to find all classes that inherit from <code>NSDimension</code> and iterate over all of their class properties that begin with <code>NSUnit</code> in their names. I mapped all the symbols, class and property names and can create <code>NSUnit</code> instance at runtime based on a user provided symbol. </p>
  
  <p>Granted, it is not at the same level with <code>NSMeasurementFormatter</code> when it comes to language support. <strong>BUT</strong> I automatically gain access to any new units and symbols that are introduced by Apple with future releases.</p>
  
  <p>Below is a sample client code:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>And here's what the core part of the implementation side looks like.</p>
  
  <pre><code>// Count receives its value from objc_copyClassList().
  unsigned int classCount;
  Class *classes = objc_copyClassList(&amp;classCount);
  // Inspect all available classes.
  for (int classIterator = 0; classIterator &lt; 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) &amp;&amp; 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, &amp;propertyCount);
          // Inspect all available class properties.
          for (int propertyIterator = 0; propertyIterator &lt; propertyCount; propertyIterator++) {
              char const *propertyName = property_getName(properties[propertyIterator]);
          // ...
      }
      // ...
  }
  // ...
  </code></pre>