Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access iOS private APIs in Swift?

How can I call non-public iOS functions and acces non public properies from Swift? Specifically, I would like to use one non-public class in QuartzCore framework.

One solution that came to my mind is to create "bridging" Objective-C project that would wrap this non-public APIs into public ones and than call this Objective-C functions from Swift. However, my solution is pure Swift now and I would prefer to keep it that way. Is there any more staitforward way? (for example adding something to Objective-C bridging header file)

Note: I know what you are thinking, private APIs are private because they should not be used. I know the risks, I am aware of all the donwsides, app store restrictions etc. After all that carefully considered and lot of research, it unfortunatelly still seems the best way to go in this particular case.

like image 300
Rasto Avatar asked Jan 27 '15 15:01

Rasto


People also ask

How do I call a private method in Swift?

You can't call private methods with selectors. That is the whole point of making the methods private, so they are not accessible from the outside. You are also sending an instance of self as target to class method which is why it will not work. You need to either send a class or remove class from method.

What is private API in iOS?

by definition, your own classes and whatnot in your own app are your own, and private. They mean private api as in using functionality provided by iOS for internal-use only. e.g. as a hacked up example, you're allowed to use a SystemClock api, which under the hood uses a private HardwareClock API.

What is a private API?

A private API is an application programming interface that has its application hosted with in-house developers. Private APIs act as front end interfaces to back end data and application functions. The interface provides a point of entry for developers or contractors that are working to develop those functions.

When should I use private API?

Essentially then, the goal of a private API program is to enable internal developers who are building new applications that leverage existing systems. Therefore, the needs and preferences of these devs should drive the decisions made by business managers and interface developers who are implementing the program.


1 Answers

You can do the very same trick that you would do if your project was in Objective-C.

Create a header file and put the declaration of a category on the class, along with the declaration of the private methods you wish to expose. Then, tell the Swift compiler to import this bridging header.

For demonstration purposes, I'm going to poke around in the internals of NSBigMutableString, a private subclass of NSMutableString, and I will call its _isMarkedAsImmutable method.

Note that here, the entire class itself is private, hence I have to declare it as a subclass of its real superclass first. Because of this, I could have as well declared the method right in the declaration of the class itself; that, however, wouldn't have demonstrated the usage of the (Private) trick-category.

If your class is public, then obviously you will only need the category, and you won't need to (re-)declare the class itself.

Bridge.h:

#import <Foundation/Foundation.h>

@interface NSMutableString (Private)
- (BOOL)_isMarkedAsImmutable; // this is a lie
@end

@interface NSBigMutableString : NSMutableString
@end

s.swift:

let s = NSBigMutableString()
println(s._isMarkedAsImmutable())

Compile and run:

$ xcrun -sdk macosx swiftc -o foo -import-objc-header Bridge.h s.swift
$ ./foo
false
$
like image 121
The Paramagnetic Croissant Avatar answered Sep 25 '22 03:09

The Paramagnetic Croissant