How to differenciate between Public vs Undocumented / Private API in iOS programmatically? - ios

Is their a safe way to determine if class / method you are accessing is not restricted at runtime ?
Or
do these classes have some property which you check and safely avoid using them?
E.g. UINavigationTransitionView or UITransitionView are accessible but undocumented, hence I assume you are not allowed to use them.

Uhm, as the name implies, any method or class not documented in the public Apple documentation or in the SDK header files is considered private API and should not be used for AppStore submissions.
Note, that sometimes you may find yourself accessing public methods on private classes. This is generally acceptable, but it depends on your use.
There are also cases, where Apple has opened API and made public retroactively, meaning you can use a method for current SDK as well as call it on previous versions of iOS safely. Examples of this include NSArray's firstObject and NSDatas base64 API.

There's no way to check programmatically at run-time. In order to know whether you're accessing a private API, you'd need to know which SDK the app was built with, and then you'd need to check every function or method call against the headers from that SDK. Since iPhones don't generally have an SDK installed, there's no way to do that check at runtime.

If you use constructions like:
Class transitionViewClass = NSClassFromString("UITransitionView");
then it's impossible to determine it's access level (public or private) at runtime.
It's better to use direct access to classes/methods:
Class transitionViewClass = [UITransitionView class];
In this case compiler that Xcode uses will show warnings/errors that this class is undeclared:
Semantic issue: Use of undeclared identifier 'UITransitionView'

Related

How to check if a method is available in an OCX interface

Currently I have an OCX embedded in our product using standard boilerplate Delphi importing of the OCX. The vendor has issued a new version of the OCX that uses the exact same GUIDs for everything (object and interfaces) but there are changes to the API. These changes are quite limited but I'm having some difficulty coming up with a reliable way to identify if the installed OCX is using the old or new version. The obvious way is to drill into the interface and check if a specific method is available from the object once it has been instantiated. I would like to do this by actually asking the object what the dispatch ID is for a particular method to see if it is present.
I don't want to use the approach of calling a new method and getting an exception as the object won't work until it has been initialised and the initialisation API is one of the things that has changed. This means that any call of a new method before initialisation will fail anyway.
Does anyone know what would be the proper way to poke through the Delphi wrapper and find out if a particular method can be resolved?
The answer is actually in your question:
I would like to do this by actually asking the object what the dispatch ID is for a particular method to see if it is present.
An OCX object implements the IDispatch interface, and IDispatch has a GetIDsOfNames() method for the very purpose of returning the dispatch ID of the object's methods and properties (for use with IDispatch.Invoke()). If a requested name is not known to the object, GetIDsOfNames() returns DISP_E_UNKNOWNNAME.

meaning of - Apps that use non-public APIs will be rejected

our app have been rejected by iTunes because of using non-public APIs
We found that your app uses one or more non-public APIs, which is not in compliance with the App Store Review Guidelines. The use of non-public APIs is not permissible because it can lead to a poor user experience should these APIs change.
We found the following non-public API/s in your app:
.......
If you have defined methods in your source code with the same names as the above-mentioned APIs, we suggest altering your method names so that they no longer collide with Apple's private APIs to avoid your application being flagged in future submissions.
what is the meaning of that rejection?
does it means:there are some apple interface "SomeAppleInterface"
// SomeAppleInterface.m
#implementation SomeAppleInterface
- (void)SomePrivateAPI // this api doesn't exists in SomeAppleInterface.h file
{
// ... some code
}
and in my code i call to a private api of apple class:
- (void)MyCodeMethod
{
SomeAppleInterface x;
[x SomePrivateAPI];
}
is it the meaning of this error? if yes how could i call to this private method, it is not mentioned in h file?
please help me to understand
You are asking for clarification for a rejection that is, most likely, simply an error on Apple's part. This list looks like a bunch of false positives. All they're saying is that you appear be calling a bunch of methods that they believe to be part of the private API.
In this question, you provide a straw man, showing us an invocation of a private method which will not compile. You seem to be asking "how could I have accidentally called the Apple private API?"
The thing is, it's really hard to accidentally call the private API. You'd could create a category #interface that exposed the private API. There are other ways, too, but this simply isn't something you can accidentally do. You have to consciously take steps to call a private API.
So the question becomes how one could get a false positive report from Apple. It's possible that you're not using Apple's private API at all, but happen to have methods in your own classes with the same signature. This might result in a false positive which can be resolved by simply changing the name of your method.
But in this case, I think there is something completely different going on and I don't think it's worth trying to track it down until you hear back from Apple. There's no point in getting all lathered up about it until you hear back from them.

How do I access the source level definition of classes at runtime?

How do I access the Objective-C class interface defanition that is collected from headers at (pre or actual) compile time so I can provide introspection that is true to the defined public interface.
Problem: F-Script, SuperDB, IKBClassBrowser, CBIntrospection use the class_copyPropertyList() family of functions to introspect objects at run time. While powerful, there are drawbacks…
the runtime has no concept of private and public… everything is
returned
I can not see a reliable way to access the to the ObjC types of
method arguments and returns
Goal: I am researching a iOS app to help teach coding via a live / immediate development environment (similar to SmallTalk, F-Script, SuperDB, IKBClassBrowser, CBIntrospection). I want users to introspect objects, send messages, create new objects, and build and run code via a VM. But I want to limit the functionality to public functions (there is no way Apple would approve the app otherwise) and I want to have access to types so I limit so users can only pass legal objects.
My hope is that there is some way to access Clang or the symbol file to pull this information in way I can use it at runtime. It does not have to be fully automated (I will probably want to limit functionality in some ways)
You're encountering one of the distinguishing characteristics of Objective-C: There is no such thing as private or public API. There's only documented API vs. undocumented API. You can call any method on any object at any time, regardless of whether it appears in a header file. Public/private distinctions exist only for the compiler; at run time, they don't exist, and there's no way to reverse the process and discern what the header files might have said.

What constitutes a private API in an iPhone app?

I'm fairly new to Objective-C and am confused on what falls under the unbrella of a "private API" that could cause Apple to reject my app. Does this include adding methods to existing classes? For example, I found some code on stackoverflow to recolor the tab bar icons for UITabBars with this extension to the UITabBarItem class. Is this considered a "private API"? If not, what does?
#interface UITabBar (ColorExtensions)
- (void)recolorItemsWithImage:(UIImage *)image shadowColor:(UIColor *)shadowColor shadowOffset:(CGSize)shadowOffset shadowBlur:(CGFloat)shadowBlur;
#end
No, categories added by user code are not "private." Private APIs are Apple's internal APIs, which are undocumented. Methods are private if they aren't in the header files and aren't in the developer documentation. (As a rule of thumb, if you don't get any compiler warnings, you aren't using private APIs.)
The above is probably an Objective-C category that extends the UITabBar class with new methods. This is perfectly kosher. You can even overwrite existing methods with categories, although this isn't recommended.
In general, private methods will often have underscores in front of them. You also don't want to use private classes that Apple reserves for large UI objects, such as the private components within a UIWebView. You don't want to use these or your app will get rejected.
Anything that you see in a header file in the Frameworks in your project is "public" and usable. It's a good idea to thumb through the header if you really want to know everything about the class, anyway.

Overriding UITabBarController , is it safe?

Just wanted to know if overriding UITabBarController would get my app rejected? Is it allowed by Apple??
Any of you have submitted an app by overriding UITabBarController??
It won't get your app rejected. In general it's fine to subclass UIKit classes, or any Cocoa Touch class. Apple docs actually recommend subclassing for UITableViewCell if you can't get by just using its properties. What gets you rejected is calling private APIs -- the ones that exist if you use reflection to inspect UIKit objects, but aren't in the reference material.
However, look closely at the delegate spec for what you're subclassing. If you can use a partner object better, that's going to produce more reusable code. In other words, when the SDK gets updated and the API class changes, your code is more likely to still work if you supply a delegate rather than subclassing.

Resources