How can I use a private method in MapKit on iOS? [duplicate] - ios

I'm searching through the whole internet since a few hours now, and I just can't find the informations I'm looking for.
I would like to mess around with the private apis, see whats possible, etc., but I can't even compile something.
So I've got a few pretty basic questions:
Do I have to dump the headers? Because I downloaded a sample, where the API is loaded with
char *framework = "/System/Library/PrivateFrameworks/...";
dlopen(...);
I would like to use the objc-syntax (if possible) rather than using C (as mentioned above), if there are any opportunities.
How do I make Xcode compile, if I import the private APIs? Do I have to add other link flags? (because I read about two different opinions)
I added a private framework and created a new Folder "Headers" and put all the headers files in there, so the framework shows up correctly in Xcode. Do I have to import the whole .framework, or only the headers from the framework I would like to use? After I imported the framework, I get 20+ errors, unknown type names, and many more.
And, finally, I've read about entitlements (which seem to be new in iOS 7). How do I use these entitlements and when do I use them?
Could someone please just type a few lines as an example?

Background
In order to use methods in any framework, you can choose to either reference those frameworks statically or dynamically. I haven't seen anything in your question that suggests you need to use dynamic linking, so I'm going to avoid that (it's slightly more complicated for a beginner). (‡)
To statically reference APIs in a framework, you would import the relevant headers, and then configure your Xcode project to link to the framework. These two steps only change slightly for Private APIs.
Private APIs usually don't provide you with the headers (*.h) that describe the APIs. I say "usually", because sometimes, an API that's private on iOS is actually public on Mac OS X, so to use it, you simply copy the OS X version of the header into your project.
Generating Headers
Probably more common, though, is that you have to generate the header yourself. If you know which header you need, often you can find it posted online under someone's github account. If not, you need a tool like class-dump, or class-dump-z. Run the class dump tool on the private framework, by finding it on your Mac:
cd /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.0.sdk/System/Library/PrivateFrameworks/
class-dump -H -o ~/Headers/7.0/MusicLibrary/ MusicLibrary
Then, go into ~/Headers/7.0/MusicLibrary/ and find lots of dumped header files. Copy (only) the header(s) you need into your Xcode iOS project directory. Then, from inside Xcode, right click on a source folder in your Project Navigator view, select "Add files to <Project Name> ...". Pick the dumped header file you need to include in your project.
Linking
In order to successfully link against the API, you also need to add the framework to your Xcode Build Phases. From your project Target settings, select Build Phases then Link Binary with Libraries. You normally choose a public framework from the default list that the iOS SDK provides you. However, you can choose to browse your Mac for 3rd-party frameworks, or private frameworks, too. For private frameworks, you're just going to have to navigate to a folder location like this
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.0.sdk/System/Library/PrivateFrameworks/
and then pick the *.framework directory.
Then, simply use the APIs like you would use any public/private API. #import the header file, call the APIs, instantiate the classes, etc.
The use of this code:
char *framework = "/System/Library/PrivateFrameworks/...";
dlopen(...);
is an attempt to dynamically open a private framework. That's not necessary, if you know at compile time which framework you want to use, and have it present on your Mac to let Xcode link against.
Entitlements
Entitlements are not new to iOS 7. They have existed for quite some time, and are one technique iOS uses to prevent unauthorized usage of some private APIs. iOS will check to see if your app has been granted a particular entitlement (by name), and if it does not have that entitlement, calling the protected API will fail (usually silently, although sometimes you'll see a message in the Console log).
See here for an example of granting your (jailbreak) app an entitlement.
(&ddagger;) Update: iOS 9.3 has brought some changes with respect to Private APIs, and static vs dynamic linking. Please see this Stack Overflow question here for more.

Related

I would like to use a UNIX command-line program (Berkeleys SPICE) in an iOS app. What is the process to compile it into a usable library?

I am trying to use Berkeley's SPICE tool in an iOS app, but am having trouble compiling it for iOS.
It is a command-line program that I can call from a terminal like:
./spice3f5 <arguments>
Which works well, and I would like this functionality in my iOS app, but I don't think I can just copy the executable over to Xcode and call it from Swift.
I've done some research and found the following:
There is an updated version of SPICE called ngspice, which is relatively new (2014 release)
I'm fairly sure there are apps out there than have used either SPICE or ngspice, so I'm sure it can be done somehow.
I have read an article about a guy who says that ngspice has been compiled as a shared library(ctrl+f "ngspice"), and he made an app with it. I have emailed him but he unfortunately he has not responded.
The reason I am asking here is because when googling for "ngspice iOS", I came across this thread which has a lot of smart people trying to compile a static library, which seems way out of my scope. I learned that dynamic libraries are allowed as of iOS8. So would it be easier to compile a *.dylib than it is a static library?
How would I goabout using ngspice or SPICE in an iOS app?
Thanks
The difference between a static and a dynamic library is essentially where they live, a static library will live inside the binary of your app, and an dynamic library will live on the system (iPhone) that runs your app. there isn't much difference as far as difficulty goes. If you wanted to go the dynamic route on os x for example, you might compile a .dylib file in a separate project first. Then copy your new .dylib file into /usr/lib or a similar location that is part of your system's path. Then you would need to copy the associated header files that know how to talk to your new .dylib file into your /usr/include folder. At this point you could import said header files in xcode using angle brackets like so:
#import <my_dylib_header_file.h>
in static world however, you would simply drag your .dylib file into xcode then copy the associated header files into your source folder and then import using quotes like so:
#import "my_dylib_header_file.h"
the advantage of doing the import statically is that the library becomes baked into your final product, as opposed to a dynamic link, which will require that the dylib is installed on the system prior to the binary being able to run properly (think DLL's on windows). The disadvantage of a static import is that the final binary is larger, as it contains more code.
The advantage of a dynamic import is that the binary is smaller, and dylib can be updated without updating the binary itself.
However based on your questions I don't think any of this matters for your project. You have the source code. Which means creating a dylib is entirely unnecessary for your purpose, you can treat the source code like a static library by simply adding it to your xcode project. If I were you I would add the spice source code to my xcode project and forget about creating a dylib. From there I would import the files and make calls to them from swift. There are lots of threads out there that explain how call c functions or objective-c classes from swift so I wont go into that here, instead I'll refer you to another answer: Swift: How to call a C function loaded from a dylib

Xcode6 blocks some static libs in static lib, but not others

Until xcode6, we had:
library target "appshared" builds a static lib and embeds multiple other static libs
Multiple apps embed static lib appshared, and automatically get the embedded static libs too
Now, with Xcode6, and a new 3rd party static lib (from MixPanel, who never quite seem to know what they're doing with packaging iOS binaries), score refuses to embed the new static lib, saying:
"can't locate file for -l[library name]
file: -l[library name] is not an object file (not allowed in a library)"
What's wrong with this new library, and ... any ideas what I have to ask the provider to fix in their build setup? (they don't share the source, sadly)
facepalm
It's a bug in Xcode 6 - nothing to do with the particular library.
Xcode no longer supports spaces in folder names, even though this has been a core requirement from Apple Corp for all Mac software for > 15 years; apparently, they don't test this for Xcode any more, and someone wrote some very bad code (probably: used the wrong (20 years old) method calls for manipulating file paths; if they'd used the correct ones, space-handling is automatic and implemented by the OS, IME!)
Solution: when you drag/drop libraries into Xcode 6, if there is a space in the folder name, Xcode will corrupt the build settings, and add a library-import-path for each word in the folder name.
You have to edit your Build Settings, find your library search paths, and you'll see it has lots of stupid values. Delete those, put the real path, and surround it in double-quotes.
All will then work fine.

How to restrict access to .m file of an ios framework while debugging an app?

I have created a framework and importing that into a sample application for testing purpose. When I am debugging the application and click on "STEP INTO", I am able to see the contents of .m file of my framework. what is the possible solution to restrict the access to my .m file ??![enter image description here][1]
Xcode have options of visibility for framework as
Public: The interface is finalized and meant to be used by your product’s clients. A public header is included in the product as readable source code without restriction.
Private: The interface isn’t intended for your clients or it’s in early stages of development. A private header is included in the product, but it’s marked “private.” Thus the symbols are visible to all clients, but clients should understand that they're not supposed to use them.
Project: The interface is for use only by implementation files in the current project. A project header is not included in the target, except in object code. The symbols are not visible to clients at all, only to you.
However, as you mentioned you want something else which secure your code as well so check the post:
How to build a framework or library for other developers, the secure way?

iOS Frameworks, embed another framework or library?

So in Xcode 6, we finally have the possibility to create and distribute our own libraries as Frameworks (as opposed to Static Libraries before).
The question, is it possible to "embed" another framework or library directly inside the framework rather than ask the end user to link them?
The reason is as follow: Creating and distributing frameworks for other people often requires them to manually add whichever framework we link against.
That's fine when these libraries are a default ones that can be added straight from Xcode, but when we need to link against other public frameworks.
One example would be if the framework uses AWS as a backend, it's a bit overkill to ask developers to also download a specific version of their SDK and link against specific bits that are required. And it becomes more overkill when we need others for performance logging or more.
On OSX, there is the possibility to use Umbrella Frameworks, but it's undocumented on iOS.
Thank you.
Recently done this myself on iOS, unfortunately any framework that has sub-frameworks must also be linked to in the project the parent framework gets used in.
Create the framework as per normal, and include the other frameworks under that framework (it should be an aggregate target).
Then build the parent framework, and link this into the main project. Attempt to compile and it will mention that it needs it sub-frameworks also linked. You can then link these sub-frameworks in addition and it will compile.
This is unfortunately a limitation of Xcode/iOS as it currently stands.

iPhone private API compiling

I'm searching through the whole internet since a few hours now, and I just can't find the informations I'm looking for.
I would like to mess around with the private apis, see whats possible, etc., but I can't even compile something.
So I've got a few pretty basic questions:
Do I have to dump the headers? Because I downloaded a sample, where the API is loaded with
char *framework = "/System/Library/PrivateFrameworks/...";
dlopen(...);
I would like to use the objc-syntax (if possible) rather than using C (as mentioned above), if there are any opportunities.
How do I make Xcode compile, if I import the private APIs? Do I have to add other link flags? (because I read about two different opinions)
I added a private framework and created a new Folder "Headers" and put all the headers files in there, so the framework shows up correctly in Xcode. Do I have to import the whole .framework, or only the headers from the framework I would like to use? After I imported the framework, I get 20+ errors, unknown type names, and many more.
And, finally, I've read about entitlements (which seem to be new in iOS 7). How do I use these entitlements and when do I use them?
Could someone please just type a few lines as an example?
Background
In order to use methods in any framework, you can choose to either reference those frameworks statically or dynamically. I haven't seen anything in your question that suggests you need to use dynamic linking, so I'm going to avoid that (it's slightly more complicated for a beginner). (&ddagger;)
To statically reference APIs in a framework, you would import the relevant headers, and then configure your Xcode project to link to the framework. These two steps only change slightly for Private APIs.
Private APIs usually don't provide you with the headers (*.h) that describe the APIs. I say "usually", because sometimes, an API that's private on iOS is actually public on Mac OS X, so to use it, you simply copy the OS X version of the header into your project.
Generating Headers
Probably more common, though, is that you have to generate the header yourself. If you know which header you need, often you can find it posted online under someone's github account. If not, you need a tool like class-dump, or class-dump-z. Run the class dump tool on the private framework, by finding it on your Mac:
cd /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.0.sdk/System/Library/PrivateFrameworks/
class-dump -H -o ~/Headers/7.0/MusicLibrary/ MusicLibrary
Then, go into ~/Headers/7.0/MusicLibrary/ and find lots of dumped header files. Copy (only) the header(s) you need into your Xcode iOS project directory. Then, from inside Xcode, right click on a source folder in your Project Navigator view, select "Add files to <Project Name> ...". Pick the dumped header file you need to include in your project.
Linking
In order to successfully link against the API, you also need to add the framework to your Xcode Build Phases. From your project Target settings, select Build Phases then Link Binary with Libraries. You normally choose a public framework from the default list that the iOS SDK provides you. However, you can choose to browse your Mac for 3rd-party frameworks, or private frameworks, too. For private frameworks, you're just going to have to navigate to a folder location like this
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.0.sdk/System/Library/PrivateFrameworks/
and then pick the *.framework directory.
Then, simply use the APIs like you would use any public/private API. #import the header file, call the APIs, instantiate the classes, etc.
The use of this code:
char *framework = "/System/Library/PrivateFrameworks/...";
dlopen(...);
is an attempt to dynamically open a private framework. That's not necessary, if you know at compile time which framework you want to use, and have it present on your Mac to let Xcode link against.
Entitlements
Entitlements are not new to iOS 7. They have existed for quite some time, and are one technique iOS uses to prevent unauthorized usage of some private APIs. iOS will check to see if your app has been granted a particular entitlement (by name), and if it does not have that entitlement, calling the protected API will fail (usually silently, although sometimes you'll see a message in the Console log).
See here for an example of granting your (jailbreak) app an entitlement.
(&ddagger;) Update: iOS 9.3 has brought some changes with respect to Private APIs, and static vs dynamic linking. Please see this Stack Overflow question here for more.

Resources