11

I want to detect in my custom keyboard extension app which application is using my extension. Can we detect any information in keyboard extension about application which is using my extension.I dont think it is possible .if any body have have knowledge about this kindly share it.

Thanks

Abeer Iqbal
  • 1,256
  • 10
  • 10

4 Answers4

15

You can try this code in your UIInputViewController

override public func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)
    if let parentViewController = self.parentViewController {
        var hostBundleID = parentViewController.valueForKey("_hostBundleID")
        println(hostBundleID)
    }
}

But I'm not sure that Apple will approved when you release to App Store

1

for iOS 16+

#import <dlfcn.h>

+ (nullable NSString *)hostBundleIDWithInputVC:(UIInputViewController *)vc {
    
    NSString *bundleID = nil;
    
    @try {
        bundleID = [vc.parentViewController valueForKey:@"_hostBundleID"];
    } @catch (NSException *exception) {
        NSLog(@"hostBundleID Get Failure 1 %@", exception);
    } @finally {
        
    }
    
    if(XMUtils.validString(bundleID) && ![bundleID isEqual:@"<null>"]) {
        return bundleID;
    }
    
    // 云控禁止xpc取法

    // xpc取法 逆向自xx输入法 主要解决iOS16上获取不到的问题
    @try {
        id hostPid = [vc.parentViewController valueForKey:@"_hostPID"];
        
        if (hostPid) {
            
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
            
            id serverIns = [NSClassFromString(@"PKService") performSelector:NSSelectorFromString(@"defaultService")];
            id lities = [serverIns performSelector:NSSelectorFromString(@"personalities")];

            id infos = [lities objectForKey:[NSBundle mainBundle].bundleIdentifier];
            
            id info = [infos objectForKey:hostPid];
            id con = [info performSelector:NSSelectorFromString(@"connection")];
            id xpcCon = [con performSelector:NSSelectorFromString(@"_xpcConnection")];
            
    #pragma clang diagnostic pop
            
            const char * (* cfunc)(id) = dlsym(RTLD_DEFAULT, "xpc_connection_copy_bundle_id");
            
            if (cfunc != nil && xpcCon != nil) {
                const char *res = cfunc(xpcCon);
                bundleID = [NSString stringWithUTF8String:res];
                return  bundleID;
            }
        }
    } @catch (NSException *exception) {
        NSLog(@"hostBundleID Get Failure 2 %@", exception);
    } @finally {
        
    }
   
    return nil;
}

from blog

  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Mar 10 '23 at 10:48
0

ios 16+, "_hostBundleID" the value is nil

  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Sep 09 '22 at 07:15
0

Swift 5 Version

This works for iOS 16 and older

import Foundation
import UIKit

extension UIInputViewController {
    
    func hostBundleId() -> String? {
        if let parentViewController = parent {
            if let hostBundleId = parentViewController.value(forKey: "_hostBundleID") as? String,
               hostBundleId != "<null>" {
                return hostBundleId
            } else if let hostPID = parentViewController.value(forKey: "_hostPID") {
                let selector = NSSelectorFromString("defaultService")
                if let anyClass: AnyObject = NSClassFromString("PKService"),
                   let pkService = anyClass as? NSObjectProtocol,
                   pkService.responds(to: selector),
                   let serverInis = pkService.perform(selector).takeUnretainedValue() as? NSObjectProtocol {
                    let lities = serverInis.perform(NSSelectorFromString("personalities")).takeUnretainedValue()
                    let bundleId = Bundle.main.bundleIdentifier ?? ""
                    if let infos = lities.object(forKey: bundleId) as? AnyObject,
                       let info = infos.object(forKey: hostPID) as? AnyObject,
                       let con = info.perform(NSSelectorFromString("connection")).takeUnretainedValue() as? NSObjectProtocol {
                        let xpcCon = con.perform(NSSelectorFromString("_xpcConnection")).takeUnretainedValue()
                        let handle = dlopen("/usr/lib/libc.dylib", RTLD_NOW)
                        let sym = dlsym(handle, "xpc_connection_copy_bundle_id")
                        typealias xpcFunc = @convention(c) (AnyObject) -> UnsafePointer<CChar>
                        let cFunc = unsafeBitCast(sym, to: xpcFunc.self)
                        let response = cFunc(xpcCon)
                        let hostBundleId = NSString(utf8String: response)
                        return hostBundleId as String?
                    }
                }
            }
        }
        return nil
    }
    
}
zeiteisen
  • 7,078
  • 5
  • 50
  • 68