I am trying to use _CDBatterySaver to turn on low power mode simply using
[[_CDBatterySaver batterySaver] setMode:1];
I know there isn't the same type of directory as previous Xcode so those methods don't work.
I have also tried just importing the ".h" file but that doesn't work.
It is part of the CoreDuet framework (downloaded from GitHub)
Thanks
You will need a .tbd
file to link against.
Apple stopped shipping these for private frameworks starting with the iOS 9.3 SDK, but you can generate them yourself with a bit of effort:
- Get an IPSW for some recent iOS version (ipsw.me or the iPhone wiki have nice lists).
- Unzip the IPSW and mount the root file system (the
.dmg
that is multiple GB).
- Find the shared library cache for your architecture in
/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm*
.
Using one of various tools (I prefer jtool), extract CoreDuet
from it, with e.g.:
jtool -e CoreDuet /path/to/dyld_shared_cache
Optional: Do step 4 for multiple architectures, then combine the extracted files to a fat binary:
lipo -output CoreDuet dyld_shared_cache_*.CoreDuet
Using either machotbd or my own tool, tbdumpnotes, create a .tbd
file from the library/framework you just extracted, e.g.:
tbdump CoreDuet > CoreDuet.tbd
notes 1. I wrote it, so I'm obviously affiliated.
2. It's a beta, and it's currently a bit over-zealous with symbols, printing even
the ones it shouldn't - but so far it has always worked fine for me.
Create a folder structure like so:
some_path/
CoreDuet.framework/
CoreDuet.tbd
Either add CoreDuet.framework to your frameworks in XCode, or use these compiler flags:
-Fsome_path -framework CoreDuet
Profit.
Also, if steps 1-6 are too troublesome for you and you merely need the _CDBatterySaver
symbol, then you can just use this for your CoreDuet.tbd
and be done with it:
---
archs: [ armv7, armv7s, arm64 ]
platform: ios
install-name: /System/Library/PrivateFrameworks/CoreDuet.framework/CoreDuet
exports:
- archs: [ armv7, armv7s, arm64 ]
objc-classes: [ __CDBatterySaver ]
...
Based on Siguza answer
Newer versions of Xcode uses the tbd v2
format. Here is a .tbd
stub file that will compile with the latest version of Xcode.
--- !tapi-tbd-v2
archs: [ armv7, armv7s, arm64 ]
uuids: [ 'armv7: CBD84526-2D11-4CF3-83A7-4408DA532D3E', 'armv7s: 37ACF720-FA66-4B2D-8411-09D0B607E1A0',
'arm64: 19F91B79-9FA2-4944-9E68-3E632C938AE3' ]
platform: ios
install-name: /System/Library/PrivateFrameworks/CoreDuet.framework/CoreDuet
objc-constraint: none
exports:
- archs: [ armv7, armv7s, arm64 ]
objc-classes: [ __CDBatterySaver ]
objc-ivars: [ __CDBatterySaver._connection ]
...
There's an official tool to generate .tbd
files these days, tapi
(Text-based API). Not sure when it was released exactly, but it's been around at least as long as Xcode 9.
To generate a .tbd
for a binary, you do something like the following. Here I'm using the private SafariShared.framework on OSX. If you need a .tbd
for an iOS framework, you'll have to follow the beginning of Siguza's answer to get ahold of a binary, but otherwise, the rest of this process will work.
Make an empty directory for the framework stub named, e.g., "SafariShared.framework":
$ md SafariShared.framework
Run a command like the following to generate the stub:
$ xcrun tapi stubify -o SafariShared.framework/SafariShared.tbd /System/Library/PrivateFrameworks/SafariShared.framework/SafariShared
The -o
argument is the output file and the final argument is the path to the binary (note that it is not the path to the .framework
itself; you'll get an error if you do that). Replace both as needed.
There's one potential pitfall. Stub files can contain a list of the programs that are allowed to link with that binary, and if your program isn't listed in that list, the linker will fail. Open up the .tbd
in your favourite text editor and look for lines like the following:
allowable-clients: [ <a bunch of bundle IDs>, ... ]
Delete all of those (there may not be any) and save the file.
Now you're good to go! The stub .framework
directory you made in step 1 will work just like a real framework in Xcode. In your Xcode project's general settings, you can click the plus in "Linked Frameworks and Libraries" and add the stub directory.
(You may also have to add the directory containing the stub .framework
to the "Framework Search Paths" project setting. It seems flaky as to whether or not that will happen automatically.)