There is an app in the Apple App Store that downloads custom dictionaries and programmatically adds them to the iOS\'s built-in Dictionary.app without user intervention. It work
Dictionary.appender app uses private framework MobileAsset.framework
. There are several selectors that the app use:
setQueriesLocalAssetInformationOnly:
runQueryAndReturnError:
initWithAssetType:attributes:
. Asset types are com.apple.MobileAsset.DictionaryServices.dictionary
for iOS < 7 and com.apple.MobileAsset.DictionaryServices.dictionary2
for iOS >= 7. They are saved in /var/mobile/Library/Assets/
.
And here's class-dump of the framework https://github.com/nst/iOS-Runtime-Headers/tree/master/PrivateFrameworks/MobileAsset.framework where you can find methods with those selectors.
In order to call them the app uses very simple technique - NSClassFromString
to obtain class object in runtime. In our case, ASAsset
and ASAssetQuery
classes. I don't know how this got approved in App Store but that's how it works. Very simple technique , selectors and class names are not even encrypted.
UPDATE
The app doesn't explicitly link private MobileAsset.framework
. It doesn't use any of the usual techniques to dynamically load a framework - no dlopen
or NSBundle
calls. Import table doesn't contain private MobileAsset.framework
either. But it linked by UIKit.framework
which obviously is linked by the app. I did a simple test. Wrote a stripped out console application that links only needed frameworks by turning off all the project settings that may automatically link the frameworks. Without UIKit.framework
executing NSClassFromString(@"ASAsset")
returns nil. With UIKit.framework
it returns ASAsset
class object.