@Nullable
 public static String getEncodingName(long nsStringEncoding) {
   long cfEncoding =
       myFoundationLibrary.CFStringConvertNSStringEncodingToEncoding(nsStringEncoding);
   ID pointer = myFoundationLibrary.CFStringConvertEncodingToIANACharSetName(cfEncoding);
   String name = toStringViaUTF8(pointer);
   if ("macintosh".equals(name))
     name = "MacRoman"; // JDK8 does not recognize IANA's "macintosh" alias
   return name;
 }
  public static long getEncodingCode(@Nullable String encodingName) {
    if (StringUtil.isEmptyOrSpaces(encodingName)) return -1;

    ID converted = nsString(encodingName);
    long cfEncoding = myFoundationLibrary.CFStringConvertIANACharSetNameToEncoding(converted);

    ID restored = myFoundationLibrary.CFStringConvertEncodingToIANACharSetName(cfEncoding);
    if (ID.NIL.equals(restored)) return -1;

    return convertCFEncodingToNS(cfEncoding);
  }
  @Nullable
  public static String toStringViaUTF8(ID cfString) {
    if (cfString.intValue() == 0) return null;

    int lengthInChars = myFoundationLibrary.CFStringGetLength(cfString);
    int potentialLengthInBytes = 3 * lengthInChars + 1; // UTF8 fully escaped 16 bit chars, plus nul

    byte[] buffer = new byte[potentialLengthInBytes];
    byte ok =
        myFoundationLibrary.CFStringGetCString(
            cfString, buffer, buffer.length, FoundationLibrary.kCFStringEncodingUTF8);
    if (ok == 0) throw new RuntimeException("Could not convert string");
    return Native.toString(buffer);
  }
 public static void cfRelease(ID... ids) {
   for (ID id : ids) {
     if (id != null) {
       myFoundationLibrary.CFRelease(id);
     }
   }
 }
  @Nullable
  public static String stringFromSelector(Pointer selector) {
    ID id = myFoundationLibrary.NSStringFromSelector(selector);
    if (id.intValue() > 0) {
      return toStringViaUTF8(id);
    }

    return null;
  }
 public static Pointer createSelector(String s) {
   return myFoundationLibrary.sel_registerName(s);
 }
 public static ID getProtocol(String name) {
   return myFoundationLibrary.objc_getProtocol(name);
 }
 /** Get the ID of the NSClass with className */
 public static ID getObjcClass(String className) {
   return myFoundationLibrary.objc_getClass(className);
 }
 public static void cfRetain(ID id) {
   myFoundationLibrary.CFRetain(id);
 }
 public static boolean addMethodByID(ID cls, Pointer selectorName, ID impl, String types) {
   return myFoundationLibrary.class_addMethod(cls, selectorName, impl, types);
 }
 public static void registerObjcClassPair(ID cls) {
   myFoundationLibrary.objc_registerClassPair(cls);
 }
 public static ID class_replaceMethod(ID cls, Pointer selector, Callback impl, String types) {
   return myFoundationLibrary.class_replaceMethod(cls, selector, impl, types);
 }
 public static String fullUserName() {
   return toStringViaUTF8(myFoundationLibrary.NSFullUserName());
 }
 public static Pointer getClass(Pointer clazz) {
   return myFoundationLibrary.objc_getClass(clazz);
 }
 public static boolean isMetaClass(ID cls) {
   return myFoundationLibrary.class_isMetaClass(cls);
 }
 public static ID invoke(final ID id, final Pointer selector, Object... args) {
   return myFoundationLibrary.objc_msgSend(id, selector, args);
 }
 public static ID allocateObjcClassPair(ID superCls, String name) {
   return myFoundationLibrary.objc_allocateClassPair(superCls, name, 0);
 }
 private static long convertCFEncodingToNS(long cfEncoding) {
   return myFoundationLibrary.CFStringConvertEncodingToNSStringEncoding(cfEncoding)
       & 0xffffffffffl; // trim to C-type limits
 }
 public static boolean isClassRespondsToSelector(ID cls, Pointer selectorName) {
   return myFoundationLibrary.class_respondsToSelector(cls, selectorName);
 }
 public static boolean addProtocol(ID aClass, ID protocol) {
   return myFoundationLibrary.class_addProtocol(aClass, protocol);
 }