Updating extensions for iOS 8: Difference between revisions

From iPhone Development Wiki
m (Formatting changes.)
 
(86 intermediate revisions by 21 users not shown)
Line 3: Line 3:
'''Hey developer, you can add your knowledge here! Yes, you! [http://iphonedevwiki.net/index.php?title=Special:UserLogin&returnto=Updating+extensions+for+iOS+8&type=signup Make an account and edit this page!]'''
'''Hey developer, you can add your knowledge here! Yes, you! [http://iphonedevwiki.net/index.php?title=Special:UserLogin&returnto=Updating+extensions+for+iOS+8&type=signup Make an account and edit this page!]'''


== What has changed in iOS 8? (Classes, frameworks, etc.) ==
It's also helpful to double-check the statements here and add more info! These are notes and drafts from early research - feel free to update them.


* The term 'Display Identifier' has been removed when referring to SBApplication. Methods that used the term usually have a 'Bundle Identifier' equivalent; e.g. <code> -[SBApplicationController applicationWithDisplayIdentifier:]</code> and <code>-[SBApplication displayIdentifier]</code> are now <code>-[SBApplicationController applicationWithBundleIdentifier]</code>  (as opposed to <code>-[SBApplicationController applicationsWithBundleIdentifier]</code>) and <code>-[SBApplication bundleIdentifier]</code>. Since applications are now found using their bundle identifier, <code>-[SBIconModel applicationIconForDisplayIdentifier:]</code> is now <code>-[SBIconModel applicationIconForBundleIdentifier:]</code>. A catch-all way of getting *any* icon is, <code>-[SBIconModel expectedIconForDisplayIdentifier:]</code>.
If you want to see what's been recently updated on this page, you can use the wiki's [http://iphonedevwiki.net/index.php?title=Updating_extensions_for_iOS_8&action=history history feature] to compare the revisions (to look at the diff) since the last time you visited this page.


* "Has anyone looked into granting entitlements in iOS 8? It would appear the popular method of hooking "_XPCConnectionHasEntitlement" no longer works." "I haven't had a whole lot of time to do testing or look for better methods but I found "_BSAuditTokenTaskHasEntitlement" which appears to have a similar function to "_XPCConnectionHasEntitlement", its part of the "assertiond" process which must be hooked in order to access it, so far it's worked. More specifically, part of the "BaseBoard" private framework within "assertiond"."
= What has changed in iOS 8? (Classes, frameworks, etc.) =
 
== Preference saving ==
 
In iOS 8 (and above), the preferences daemon cfprefsd is handling all preferences in memory and writes them to the corresponding .plist file lately (it synchronizes data every 10 seconds, as specified in <code>-[_CFPrefsSynchronizer init]</code> in CoreFoundation framework). Therefore when the notification for a change is posted, the change is usually not yet written to the file. Reading preferences directly from the .plist has become problematic. The notification from the [[Preferences specifier plist]] is now posted '''before''' the plist is updated on disk — as opposed to '''after''' the plist was updated on disk, which was the case on iOS < 8.
 
Writing directly to a plist in Preferences is also a problem because then the daemon will not know about your "manual" changes, and will overwrite those changes when it writes its in-memory settings. So either you read or write everything yourself (for example by overriding setPreferenceValue:specifier and readPreferenceValue:) or use [https://developer.apple.com/library/mac/documentation/CoreFoundation/Reference/CFPreferencesUtils/ CFPreferencesUtils].
 
=== Solution 1: Use CFPreferences (does not work in sandboxed processes) ===
 
'''See [[PreferenceBundles#Loading_Preferences_into_unsandboxed_processes_.28using_CFPreferences.29|Loading Preferences into unsandboxed processes (using CFPreferences)]] for what to do.''' (As that page says: this was tested back to iOS 6, it seemed to work without problems. This solution does not work if you are in third party apps or other apps that have sandboxed preferences.) Another viable option could be using GCD and using a descriptor source for that file.
 
=== Solution 2: Override setPreferenceValue:specifier and readPreferenceValue: in preference bundle to restore old behaviour (Karen (angelXwind)'s method) ===
 
'''See [[PreferenceBundles#Loading_Preferences_into_sandboxed.2Funsandboxed_processes_in_iOS_8|Loading Preferences into sandboxed/unsandboxed processes in iOS 8]] for instructions and code on how to achieve this.'''
 
I've tested this on iOS 5, 6, 7, and 8, and can confirm that it works without any issues.
 
=== Solution 3: Use CFPreferencesAppSynchronize (apparently works in sandboxed processes for some people) (iMokhles/ichitaso's method) ===
 
'''See [https://gist.github.com/iMokhles/23061acdffbfeaa875db How to use CFPreferencesAppSynchronize with ARC and non ARC (iOS8 Tweaks) + CFNotificationCallback] for some example code.'''
 
Above example tested with Sandbox Apps "WhatsApp" and "Tweetbot 3" and seems to work perfectly.
 
=== Solution 4: Use NSUserDefaults (Public API) ===
 
<source lang="objc">[[[[NSUserDefaults standardUserDefaults] persistentDomainForName:@"com.malcolmhall.StealthCam"] objectForKey:@"lock"] boolValue];</source>
 
=== Solution 5: Use NSUserDefaults (Private API) ===
 
[http://sharedinstance.net/2014/11/settings-the-right-way/ Another way on the sharedInstance blog.]
 
Note on previous iOS versions the preference wasn't always up to date but on iOS 8 it appears to be. Using this in my StealthCam SpringBoard tweak. Doesn't work within a sandbox.
 
'''Thanks to xTM3x, Yllier, and others for their research on this.'''
 
== Application related ==
 
* The term 'Display Identifier' has been removed when referring to SBApplication. Methods that used the term usually have a 'Bundle Identifier' equivalent; e.g. <code> -[SBApplicationController applicationWithDisplayIdentifier:]</code> and <code>-[SBApplication displayIdentifier]</code> are now <code>-[SBApplicationController applicationWithBundleIdentifier]</code> (as opposed to <code>-[SBApplicationController applicationsWithBundleIdentifier]</code>) and <code>-[SBApplication bundleIdentifier]</code>. Since applications are now found using their bundle identifier, <code>-[SBIconModel applicationIconForDisplayIdentifier:]</code> is now <code>-[SBIconModel applicationIconForBundleIdentifier:]</code>. A catch-all way of getting *any* icon is, <code>-[SBIconModel expectedIconForDisplayIdentifier:]</code>.
 
* MISValidateSignatureAndCopyInfo appears to perform additional code-signing checks during app installation.
 
* Mobile application containers are at <code>/var/mobile/Containers/Bundle/Application</code> and their data are located at <code>/var/mobile/Containers/Data/Application</code>. Using [[AppList]] you can get the path to the bundle and data of an app from its bundle id with the following code:
 
<source lang="objc">
NSString * findAppBundlePath(NSString *bundleID) {
return [ALApplicationList.sharedApplicationList valueForKey:@"path" forDisplayIdentifier:bundleID];
}
 
NSString * findAppDataPath(NSString *bundleID) {
if ([NSProcessInfo instancesRespondToSelector:@selector(isOperatingSystemAtLeastVersion:)]) {
return [ALApplicationList.sharedApplicationList valueForKey:@"dataContainerPath" forDisplayIdentifier:bundleID];
} else {
NSString *bundlePath = findAppBundlePath(bundleID);
 
if([bundlePath hasPrefix:@"/Applications/"]) {
return @"/private/var/mobile/";
} else {
return [bundlePath stringByAppendingPathComponent:@".."];
}
}
}
</source>
 
See [https://developer.apple.com/library/ios/technotes/tn2406/_index.html TM2406].
 
* Looks like certain apps don't have privileges for IORegistryEntryCreateCFProperty anymore (Safari, Mail).
 
* If an app is using WKWebViews, processes named com.apple.WebContent and com.apple.WebNetworking are being spawned and they each create only one NSURLCache. If you want to know the bundleIdentifier of the app they were spawned for, just hook <code>-[NSURLCache _initWithMemoryCapacity:diskCapacity:relativePath:]</code> in those processes. relativePath will be that bundleIdentifier. It's not perfect but a quick and neat trick.
 
* com.apple.mobileinstallation.plist is gone on iOS 8. You can use [[AppList]] to get a list of installed apps. If you need to do this without Substrate for some reason, [http://www.reddit.com/r/jailbreakdevelopers/comments/2k6gft/list_installed_apps_on_ios_8/ this post and thread] has some discussion of alternatives.
 
* SBAppSlider* classes have been renamed to SBAppSwitcher*
 
== Daemons ==
 
* launchctl appears to be slightly broken. launchctl start and stop work perfectly, but launchctl load/unload no longer works with [[daemons]] in /System/Library/LaunchDaemons/ (aborts with the cryptic error message <code>/System/Library/LaunchDaemons/com.apple.mobile.installd.plist: The specified service path was not in the service cache</code>). But you can load/unload daemons based in /Library/LaunchDaemons/ (that's where you are supposed to launch your daemons from anyway).
** Use the new params e.g. <code>launchctl kickstart -k system/com.apple.locationd</code>
 
* installd cannot be reloaded via launchctl.
 
* [http://newosxbook.com/articles/8-10.10.html Notes from iOS 8 and the OS X 10.10 Preview, by Jonathan Levin] - more about frameworks, daemons, and launchd.
 
== Everything else ==
 
* "Has anyone looked into granting entitlements in iOS 8? It would appear the popular method of hooking "_XPCConnectionHasEntitlement" no longer works." "I haven't had a whole lot of time to do testing or look for better methods but I found "_BSAuditTokenTaskHasEntitlement" which appears to have a similar function to "_XPCConnectionHasEntitlement", it's part of the "assertiond" process which must be hooked in order to access it, so far it's worked. More specifically, part of the "BaseBoard" private framework within "assertiond"."


* PLBatteryPropertiesEntry no longer seems to exist for getting current battery info such as: <code>[PLBatteryPropertiesEntry batteryPropertiesEntry].currentCapacity</code>. You can still use:
* PLBatteryPropertiesEntry no longer seems to exist for getting current battery info such as: <code>[PLBatteryPropertiesEntry batteryPropertiesEntry].currentCapacity</code>. You can still use:
Line 15: Line 100:
</source>
</source>


* launchctl appears to be slightly broken. launchctl start and stop work perfectly, but launchctl load and unload break with the cryptic error message <code>/System/Library/LaunchDaemons/com.apple.mobile.installd.plist: The specified service path was not in the service cache</code>
* PrivateFrameworks (and possibly others) in the iOS 8 SDK are missing the __TEXT section. Frameworks must be extracted from a device's dyld_shared_cache using a tool like [http://www.newosxbook.com/index.php?page=downloads JTool] or IDA before they can be (statically) reverse engineered. See [[dyld_shared_cache]] for more info.
 
* Many functions from SBMediaController have been removed, and it is now useless for accessing now playing information. <code>-[MPUNowPlayingController currentElapsed]</code> and <code>-[MPUNowPlayingController currentDuration]</code> can be utilized for displaying track time. Use [https://github.com/Cykey/ios-reversed-headers/blob/master/MediaRemote/MediaRemote.h MediaRemotes] <code>kMRMediaRemoteNowPlayingInfoDidChangeNotification</code> on the local notification center for updates when now playing info changes. You can also use <code>kMRMediaRemoteNowPlayingApplicationIsPlayingDidChangeNotification</code> for updates on the playback state. Use <code>MRMediaRemoteGetNowPlayingInfo(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^(CFDictionaryRef result);</code> to access now playing info. This code works fine on iOS 7 and 8.
 
* You can no longer mount FAT-formatted storage devices via the CCK, only HFS.
 
* "Has anyone figured out how to add subviews to UIAlertView in iOS 8 yet?" "I found a workaround so I can at least add to the content view (which is not the size of the full alert view though). Within a subclass of UIAlertView do <code>[[[[self _alertController] contentViewController] view] addSubview:theSubview];</code>. When not subclassing, <code>[[[[alertView _alertController] contentViewController] view] addSubview:theSubview];</code> should work, although one has to figure out the right time to do that."


* MISValidateSignatureAndCopyInfo appears to perform additional code-signing checks during app installation.
* system() is now deprecated. Apple recommends using [https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man2/posix_spawn.2.html posix_spawn()] instead.
Using using posix_spawn() to kill the camera app would work like that:


* installd cannot be reloaded via launchctl.
<source lang="objc">
#include <spawn.h>


* Mobile application containers are at /var/mobile/Containers/Application
pid_t pid;
int status;
const char* args[] = {"killall", "-9", "Camera", NULL};
posix_spawn(&pid, "/usr/bin/killall", NULL, NULL, (char* const*)args, NULL);
waitpid(pid, &status, WEXITED);//wait untill the process completes (only if you need to do that)
</source>


* Looks like certain apps dont have privileges for IORegistryEntryCreateCFProperty anymore (Safari, Mail)
Technically you can allow the use of system() by wrapping it like so:


* xTM3x has been doing some research into preference saving ([https://ghostbin.com/paste/mcgu3 log], file atomicity takes long enough to see the auxiliary files). It seems that the PostNotification from the [[Preferences specifier plist]] is now posted '''before''' the plist is updated on disk — as opposed to '''after''' the plist was updated on disk which was the case on iOS < 8 (unless I'm doing something terribly wrong!). These facts could mean that writing to file with <code>atomicity:YES</code> (as is custom) is slower than on previous iOS versions. This could be a bug on Apple's code and not an issue with developer's code. Either a patch should be made or wait for Apple to notice and fix it. Consider setting up an NSTimer for a short period and update your values then. '''See [[PreferenceBundles#Loading_Preferences_.28a_better_way.29|Loading Preferences (a better way)]] for what to do instead.''' Another viable option could be using GCD and using a descriptor source for that file.
<source lang="objc">
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
system(...);
#pragma GCC diagnostic pop
</source>


* PrivateFrameworks (and possibly others) in the iOS 8 SDK are missing the __TEXT section. Frameworks must be extracted from a device's [[dyld_shared_cache]] using a tool like [http://www.newosxbook.com/index.php?page=downloads JTool] or IDA before they can be (statically) reverse engineered.
Alternatively you can make a wrapper function if you use system a lot in your code:


* Many functions from SBMediaController have been removed, and it is now useless for accessing now playing information. The best alternative seems to be the MediaRemote framework.
<source lang="objc">
int system_no_deprecation(const char *command) {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
return system(command);
#pragma GCC diagnostic pop
}
</source>


* You can no longer mount FAT-formatted storage devices via the CCK, only HFS.
However that is not recommended. Instead of just replacing system("kill ..."), you should find the pid of the process you are trying to kill and send it a kill signal.


* "Has anyone figured out how to add subviews to UIAlertView in iOS 8 yet?" "I found a workaround so I can at least add to the content view (which is not the size of the full alert view though). Within a subclass of UIAlertView do <code>[[[[self _alertController] contentViewController] view] addSubview:theSubview];</code>. When not subclassing, <code>[[[[alertView _alertController] contentViewController] view] addSubview:theSubview];</code> should work, although one has to figure out the right time to do that."
* When a passcode is set, normal UIWindows are not rendered when on the lockscreen, although touch events are still received. You can make your own UIWindows show up over the lockscreen by calling <code>-(void)_setSecure:(BOOL)secure</code>, or you can override <code>- (bool)_shouldCreateContextAsSecure;</code> in UIWindow to always return YES for all new UIWindows. (CAContext has a new property <code>bool isSecure</code> which controls this behaviour.)


* system() is now deprecated. Apple recommends using posix_spawn() instead.
* CoreMedia's FigVibratorPlayVibrationWithDictionary in iOS8 requires new parameters. Research of limneos and moeseth found out this
<code>void FigVibratorPlayVibrationWithDictionary(CFDictionaryRef dict, int a, int b, void *c, CFDictionaryRef d); </code>


* If an app is using WKWebViews, processes named com.apple.WebContent and com.apple.WebNetworking are being spawned and they each create only one NSURLCache. If you want to know the bundleIdentifier of the app they were spawned for, just hook -[NSURLCache _initWithMemoryCapacity:diskCapacity:relativePath:] in those processes. relativePath will be that bundleIdentifier. It's not perfect but a quick and neat trick.
where d is a dictionary of ID which includes ClientPID, ClientPort, SSID and UserID.


== What is new in iOS 8, and how does it work? ==
= What is new in iOS 8, and how does it work? =


* The view Reachability invokes is in the new framework FrontBoard - you can hook it. It is a FBWindowContextHostView. To toggle it: <code>[[%c(SBReachabilityManager) sharedInstance] _handleReachabilityActivated];</code>
* The view Reachability invokes is in the new framework FrontBoard - you can hook it. It is a FBWindowContextHostView. To toggle it: <code>[[%c(SBReachabilityManager) sharedInstance] _handleReachabilityActivated];</code>
* To support Reachability on smaller devices, hook SBReachabilityManager class's <code>+(BOOL)reachabilitySupported;</code>


* FrontBoard is a new framework that takes up a few of BackBoardServices' responsibilities. SpringBoard now inherits from FBSystemApp, which in turn is a UIApplication subclass.
* FrontBoard is a new framework that takes up a few of BackBoardServices' responsibilities. SpringBoard now inherits from FBSystemApp, which in turn is a UIApplication subclass.
Line 49: Line 162:
* Apple seems to call the iOS side Octavia and the OS X side Nero
* Apple seems to call the iOS side Octavia and the OS X side Nero


== Which tools and other preexisting things are still working on iOS 8? Which ones don't work? ==
= Which tools and other preexisting things are still working on iOS 8? Which ones don't work? =


* Activator, Flipswitch and AppList betas with support for iOS 8 are on rpetrich's repository ([http://rpetri.ch/repo/ http://rpetri.ch/repo/])
* Activator, Flipswitch and AppList updates compatible with iOS 8 are live on BigBoss repository ([https://twitter.com/rpetrich/status/527244599820288003 verified by rpetrich]).


* The package <code>syslogd to /var/log/syslog</code> seems to not be working. [http://www.reddit.com/r/jailbreakdevelopers/comments/2k3b29/syslog_on_ios_8/ An alternative] - also as listed [http://theiphonewiki.com/wiki/System_Log on TheiPhoneWiki]. In other words: while the syslogd package doesn't work, installing socat and running <code>socat - UNIX-CONNECT:/var/run/lockdown/syslog.sock</code> still works on iOS 8. You can pipe it to a file if you want.
* The package <code>syslogd to /var/log/syslog</code> '''has been updated for iOS 8''', as of November 9. There are alternatives listed at [http://theiphonewiki.com/wiki/System_Log on TheiPhoneWiki] if you want to use a different method of accessing syslog though.


* "Does Theos work on iOS 8?" [http://www.reddit.com/r/jailbreakdevelopers/comments/2k2eat/question_theos_and_ios_8/ uroboro responds here]
* "Does Theos work on iOS 8?" [http://www.reddit.com/r/jailbreakdevelopers/comments/2k2eat/question_theos_and_ios_8/ uroboro responds here]
** However, theos may spit out a lot of errors about "Unsupported architecture", when using the iOS 8.1 SDK. These can safely be ignored.
* libstatusbar is compatible with iOS 8 as of version 0.9.8.


* libstatusbar seems to not be compatible yet, UIImage kitImageNamed returns null. While waiting for an official fix, if you need a version for testing, you could compile from [http://github.com/tateu/libstatusbar/tree/iOS8_Temp_Hack Tateu's patched source], but it's a horrible hack that is just a temporary solution (it doesn't appear to have identical behaviour if run on older iOS versions).
* libsymbolicate is compatible with iOS 8 as of version 1.8.0.


* libsymbolicate doesn't work on 8. (VMUHeader is gone from Symbolication.framework)
* "RocketBootstrap seems to work." - it works perfectly with my tweak [Simon Selg]. Maybe not [https://twitter.com/punksomething/status/527878336081842176 working as well with Flex though]?


* "RocketBootstrap seems to work." - it works perfectly with my tweak [Simon Selg].
* "What works for dumping classes on iOS 8? classdumpz doesn't seem to work. I'm trying to dump them directly on an iPhone 6." "You could use class-dump for i386 and the iOS 8 simulator" "[http://stevenygard.com/projects/class-dump/ This class-dump works for me.]" "If you want to dump on your iPhone then just compile its source to ARM; IIRC its distributed binary is x86/64 only."


* "What works for dumping classes on iOS 8? I've tried using classdumpdyld and classdumpz but none of them seem to work. I'm trying to dump them directly on an iPhone 6." "You could use class-dump for i386 and the iOS 8 simulator" "[http://stevenygard.com/projects/class-dump/ This class-dump works for me.]" "If you want to dump on your iPhone then just compile its source to ARM; IIRC its distributed binary is x86/64 only."
* "Does weak_classdump_bundle fail for anyone else on SpringBoard?" "It fails in general, it needs to be updated. You can dump SpringBoard with classdump-dyld." An updated classdump-dyld (that supports 64bit executables dumping) is available [https://github.com/limneos/classdump-dyld on GitHub] and on BigBoss ([https://ghostbin.com/paste/3r86u changelog]).


== Random assorted other notes ==
= Random assorted other notes =


* [http://developer.limneos.net/index.php?ios=8.0 iOS 8.0 Headers], [https://github.com/coolstar/iOS-8.1-SpringBoard-Headers another set of SpringBoard headers], [https://github.com/iMokhles/iPhone5S-iOS8.1-SBHeaders another set of SpringBoard headers Part-1] and [https://github.com/iMokhles/iPhone5S-iOS8.1-SBHeaders-2 another set of SpringBoard headers Part-2] (made with two different [[Reverse_Engineering_Tools#class-dump.2C_class_dump_z.2C_classdump-dyld|class dumping tools]]).
* [http://developer.limneos.net/index.php?ios=8.0 iOS 8.0 Headers], [https://github.com/coolstar/iOS-8.1-SpringBoard-Headers another set of SpringBoard headers], [https://github.com/iMokhles/iPhone5S-iOS8.1-SBHeaders another set of SpringBoard headers Part-1] and [https://github.com/iMokhles/iPhone5S-iOS8.1-SBHeaders-2 another set of SpringBoard headers Part-2] (made with different [[Reverse_Engineering_Tools#class-dump.2C_class_dump_z.2C_classdump-dyld|class dumping tools]]).


* In things like SBStarkBanner* classes, Stark is the codename for the blur-heavy UI since iOS 7
* In things like SBStarkBanner* classes, Stark is the codename for CarPlay™ since iOS 7

Latest revision as of 16:19, 8 September 2019

Let's collect knowledge like we did with Updating extensions for iOS 7 - paste in your notes and share what you've learned, and somebody else will organize it later. :) If you want to ask questions and share tips over chat with other developers, see How to use IRC for how to connect to #theos and #iphonedev.

Hey developer, you can add your knowledge here! Yes, you! Make an account and edit this page!

It's also helpful to double-check the statements here and add more info! These are notes and drafts from early research - feel free to update them.

If you want to see what's been recently updated on this page, you can use the wiki's history feature to compare the revisions (to look at the diff) since the last time you visited this page.

What has changed in iOS 8? (Classes, frameworks, etc.)

Preference saving

In iOS 8 (and above), the preferences daemon cfprefsd is handling all preferences in memory and writes them to the corresponding .plist file lately (it synchronizes data every 10 seconds, as specified in -[_CFPrefsSynchronizer init] in CoreFoundation framework). Therefore when the notification for a change is posted, the change is usually not yet written to the file. Reading preferences directly from the .plist has become problematic. The notification from the Preferences specifier plist is now posted before the plist is updated on disk — as opposed to after the plist was updated on disk, which was the case on iOS < 8.

Writing directly to a plist in Preferences is also a problem because then the daemon will not know about your "manual" changes, and will overwrite those changes when it writes its in-memory settings. So either you read or write everything yourself (for example by overriding setPreferenceValue:specifier and readPreferenceValue:) or use CFPreferencesUtils.

Solution 1: Use CFPreferences (does not work in sandboxed processes)

See Loading Preferences into unsandboxed processes (using CFPreferences) for what to do. (As that page says: this was tested back to iOS 6, it seemed to work without problems. This solution does not work if you are in third party apps or other apps that have sandboxed preferences.) Another viable option could be using GCD and using a descriptor source for that file.

Solution 2: Override setPreferenceValue:specifier and readPreferenceValue: in preference bundle to restore old behaviour (Karen (angelXwind)'s method)

See Loading Preferences into sandboxed/unsandboxed processes in iOS 8 for instructions and code on how to achieve this.

I've tested this on iOS 5, 6, 7, and 8, and can confirm that it works without any issues.

Solution 3: Use CFPreferencesAppSynchronize (apparently works in sandboxed processes for some people) (iMokhles/ichitaso's method)

See How to use CFPreferencesAppSynchronize with ARC and non ARC (iOS8 Tweaks) + CFNotificationCallback for some example code.

Above example tested with Sandbox Apps "WhatsApp" and "Tweetbot 3" and seems to work perfectly.

Solution 4: Use NSUserDefaults (Public API)

[[[[NSUserDefaults standardUserDefaults] persistentDomainForName:@"com.malcolmhall.StealthCam"] objectForKey:@"lock"] boolValue];

Solution 5: Use NSUserDefaults (Private API)

Another way on the sharedInstance blog.

Note on previous iOS versions the preference wasn't always up to date but on iOS 8 it appears to be. Using this in my StealthCam SpringBoard tweak. Doesn't work within a sandbox.

Thanks to xTM3x, Yllier, and others for their research on this.

Application related

  • The term 'Display Identifier' has been removed when referring to SBApplication. Methods that used the term usually have a 'Bundle Identifier' equivalent; e.g. -[SBApplicationController applicationWithDisplayIdentifier:] and -[SBApplication displayIdentifier] are now -[SBApplicationController applicationWithBundleIdentifier] (as opposed to -[SBApplicationController applicationsWithBundleIdentifier]) and -[SBApplication bundleIdentifier]. Since applications are now found using their bundle identifier, -[SBIconModel applicationIconForDisplayIdentifier:] is now -[SBIconModel applicationIconForBundleIdentifier:]. A catch-all way of getting *any* icon is, -[SBIconModel expectedIconForDisplayIdentifier:].
  • MISValidateSignatureAndCopyInfo appears to perform additional code-signing checks during app installation.
  • Mobile application containers are at /var/mobile/Containers/Bundle/Application and their data are located at /var/mobile/Containers/Data/Application. Using AppList you can get the path to the bundle and data of an app from its bundle id with the following code:
NSString * findAppBundlePath(NSString *bundleID) {
	return [ALApplicationList.sharedApplicationList valueForKey:@"path" forDisplayIdentifier:bundleID];
}

NSString * findAppDataPath(NSString *bundleID) {
	if ([NSProcessInfo instancesRespondToSelector:@selector(isOperatingSystemAtLeastVersion:)]) {
		return [ALApplicationList.sharedApplicationList valueForKey:@"dataContainerPath" forDisplayIdentifier:bundleID];
	} else {
		NSString *bundlePath = findAppBundlePath(bundleID);

		if([bundlePath hasPrefix:@"/Applications/"]) {
			return @"/private/var/mobile/";
		} else {
			return [bundlePath stringByAppendingPathComponent:@".."];
		}
	}
}

See TM2406.

  • Looks like certain apps don't have privileges for IORegistryEntryCreateCFProperty anymore (Safari, Mail).
  • If an app is using WKWebViews, processes named com.apple.WebContent and com.apple.WebNetworking are being spawned and they each create only one NSURLCache. If you want to know the bundleIdentifier of the app they were spawned for, just hook -[NSURLCache _initWithMemoryCapacity:diskCapacity:relativePath:] in those processes. relativePath will be that bundleIdentifier. It's not perfect but a quick and neat trick.
  • com.apple.mobileinstallation.plist is gone on iOS 8. You can use AppList to get a list of installed apps. If you need to do this without Substrate for some reason, this post and thread has some discussion of alternatives.
  • SBAppSlider* classes have been renamed to SBAppSwitcher*

Daemons

  • launchctl appears to be slightly broken. launchctl start and stop work perfectly, but launchctl load/unload no longer works with daemons in /System/Library/LaunchDaemons/ (aborts with the cryptic error message /System/Library/LaunchDaemons/com.apple.mobile.installd.plist: The specified service path was not in the service cache). But you can load/unload daemons based in /Library/LaunchDaemons/ (that's where you are supposed to launch your daemons from anyway).
    • Use the new params e.g. launchctl kickstart -k system/com.apple.locationd
  • installd cannot be reloaded via launchctl.

Everything else

  • "Has anyone looked into granting entitlements in iOS 8? It would appear the popular method of hooking "_XPCConnectionHasEntitlement" no longer works." "I haven't had a whole lot of time to do testing or look for better methods but I found "_BSAuditTokenTaskHasEntitlement" which appears to have a similar function to "_XPCConnectionHasEntitlement", it's part of the "assertiond" process which must be hooked in order to access it, so far it's worked. More specifically, part of the "BaseBoard" private framework within "assertiond"."
  • PLBatteryPropertiesEntry no longer seems to exist for getting current battery info such as: [PLBatteryPropertiesEntry batteryPropertiesEntry].currentCapacity. You can still use:
io_service_t powerSource = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOPMPowerSource"));
CFNumberRef currentCapacityNum = (CFNumberRef)IORegistryEntryCreateCFProperty(powerSource, CFSTR(kIOPMPSCurrentCapacityKey), kCFAllocatorDefault, 0);
  • PrivateFrameworks (and possibly others) in the iOS 8 SDK are missing the __TEXT section. Frameworks must be extracted from a device's dyld_shared_cache using a tool like JTool or IDA before they can be (statically) reverse engineered. See dyld_shared_cache for more info.
  • Many functions from SBMediaController have been removed, and it is now useless for accessing now playing information. -[MPUNowPlayingController currentElapsed] and -[MPUNowPlayingController currentDuration] can be utilized for displaying track time. Use MediaRemotes kMRMediaRemoteNowPlayingInfoDidChangeNotification on the local notification center for updates when now playing info changes. You can also use kMRMediaRemoteNowPlayingApplicationIsPlayingDidChangeNotification for updates on the playback state. Use MRMediaRemoteGetNowPlayingInfo(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^(CFDictionaryRef result); to access now playing info. This code works fine on iOS 7 and 8.
  • You can no longer mount FAT-formatted storage devices via the CCK, only HFS.
  • "Has anyone figured out how to add subviews to UIAlertView in iOS 8 yet?" "I found a workaround so I can at least add to the content view (which is not the size of the full alert view though). Within a subclass of UIAlertView do [[[[self _alertController] contentViewController] view] addSubview:theSubview];. When not subclassing, [[[[alertView _alertController] contentViewController] view] addSubview:theSubview]; should work, although one has to figure out the right time to do that."
  • system() is now deprecated. Apple recommends using posix_spawn() instead.

Using using posix_spawn() to kill the camera app would work like that:

#include <spawn.h>

pid_t pid;
int status;
const char* args[] = {"killall", "-9", "Camera", NULL};
posix_spawn(&pid, "/usr/bin/killall", NULL, NULL, (char* const*)args, NULL);
waitpid(pid, &status, WEXITED);//wait untill the process completes (only if you need to do that)

Technically you can allow the use of system() by wrapping it like so:

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
system(...);
#pragma GCC diagnostic pop

Alternatively you can make a wrapper function if you use system a lot in your code:

int system_no_deprecation(const char *command) {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
	return system(command);
#pragma GCC diagnostic pop
}

However that is not recommended. Instead of just replacing system("kill ..."), you should find the pid of the process you are trying to kill and send it a kill signal.

  • When a passcode is set, normal UIWindows are not rendered when on the lockscreen, although touch events are still received. You can make your own UIWindows show up over the lockscreen by calling -(void)_setSecure:(BOOL)secure, or you can override - (bool)_shouldCreateContextAsSecure; in UIWindow to always return YES for all new UIWindows. (CAContext has a new property bool isSecure which controls this behaviour.)
  • CoreMedia's FigVibratorPlayVibrationWithDictionary in iOS8 requires new parameters. Research of limneos and moeseth found out this

void FigVibratorPlayVibrationWithDictionary(CFDictionaryRef dict, int a, int b, void *c, CFDictionaryRef d);

where d is a dictionary of ID which includes ClientPID, ClientPort, SSID and UserID.

What is new in iOS 8, and how does it work?

  • The view Reachability invokes is in the new framework FrontBoard - you can hook it. It is a FBWindowContextHostView. To toggle it: [[%c(SBReachabilityManager) sharedInstance] _handleReachabilityActivated];
  • To support Reachability on smaller devices, hook SBReachabilityManager class's +(BOOL)reachabilitySupported;
  • FrontBoard is a new framework that takes up a few of BackBoardServices' responsibilities. SpringBoard now inherits from FBSystemApp, which in turn is a UIApplication subclass.
  • CameraKit is a new framework that takes everything related to the camera out of PhotoLibrary.framework. PLCameraController is now the humungous CAMCaptureController.
  • Apple seems to call the iOS side Octavia and the OS X side Nero

Which tools and other preexisting things are still working on iOS 8? Which ones don't work?

  • Activator, Flipswitch and AppList updates compatible with iOS 8 are live on BigBoss repository (verified by rpetrich).
  • The package syslogd to /var/log/syslog has been updated for iOS 8, as of November 9. There are alternatives listed at on TheiPhoneWiki if you want to use a different method of accessing syslog though.
  • "Does Theos work on iOS 8?" uroboro responds here
    • However, theos may spit out a lot of errors about "Unsupported architecture", when using the iOS 8.1 SDK. These can safely be ignored.
  • libstatusbar is compatible with iOS 8 as of version 0.9.8.
  • libsymbolicate is compatible with iOS 8 as of version 1.8.0.
  • "What works for dumping classes on iOS 8? classdumpz doesn't seem to work. I'm trying to dump them directly on an iPhone 6." "You could use class-dump for i386 and the iOS 8 simulator" "This class-dump works for me." "If you want to dump on your iPhone then just compile its source to ARM; IIRC its distributed binary is x86/64 only."
  • "Does weak_classdump_bundle fail for anyone else on SpringBoard?" "It fails in general, it needs to be updated. You can dump SpringBoard with classdump-dyld." An updated classdump-dyld (that supports 64bit executables dumping) is available on GitHub and on BigBoss (changelog).

Random assorted other notes

  • In things like SBStarkBanner* classes, Stark is the codename for CarPlay™ since iOS 7