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.
Related
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.
I'm trying to implement a multilanguage support with mvvmcross in iOS. The "languages" are stored in a .resx file in the core (Portable Library Class).
So on the android side it works great......I have just to call the recreathe()-Method to rebuild the views.
Is there some similiar method I can call in iOS or in the MVVMCROSS-Library? I experimented a lot with several methods, but without any success.
I know how to make it manually:
Remove all Subviews
Create new instances for each removed subview
Do the bindings again
Add the views back to subviews
But honestly this just can't be the way it goes.
Has anyone a much more sleek suggestion?
if your views use binding (like I described here ) to display the localized version of the string values, the only thing you need to do is to call
RaisePropertyChanged(string.empty) or RaiseAllPropertiesChanged() on the view-models
When user changes the language, you could broadcast a message (using MvmCross messenger) which all the language aware view-models listen to, and on handling this message have the view-models can then call RaisePropertyChanged(string.empty) or RaiseAllPropertiesChanged() on the view-models
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'
Hi I want to create an application for the iPhone/ iPad, and on the initial page I want the user to have the option to change the language of the application (default language is English). Depending on the language the user chooses, for example Spanish, the initial page text and buttons will all be in Spanish. Then, after a button is pressed, the next view is also in Spanish. (And the back button is also in Spanish)
How could I do this? Remember, I DO NOT want to use Localization. Instead, I want the user to have to possibility to change the language of the app, WITHIN the same app, and NOT the Settings app.
Help with maybe a few examples would be very much appreciated.
Thank you very much in advance!
I've done this a few times. iOS is not designed for this and the first thing you should do is reconsider your approach or go back to the client and make absolutely sure it is necessary. There are only a few situations where this approach is the right one, it's mostly a mistake.
Your first issue is with localising string resources. NSBundle offers methods to load localised strings. Have a singleton class to manage which language you've currently got selected. When you change the language, it can load the en.lproj directory (or whichever language is selected) as a bundle. From that point, instead of using the usual macros to get localised string resources, use a method on your singleton to fetch them from the current bundle.
The same applies to images and other resources - your singleton knows which localisation bundle is in play, so ask it for the resources you need.
When you change language, tell your singleton, and your singleton can load the relevant bundle and post a notification so that your view controllers know to update themselves.
If you are lucky, your nibs layouts work independently of language without modification. This means you can set up a base view controller that others inherit from that has an outlet collection for localised interface elements. It should listen for the notification and walk the collection to update the necessary items.
If you are unlucky and different localisations need different layouts, you'll probably have to save state, get the relevant nib from your singleton, then reload everything and restore state.
You also have a problem that can't be entirely fixed - iOS will still think it's in the main system language. Where there is iOS-supplied content that is out of your control, it will be localised to the main system language. You can mitigate that a little by setting the user preference AppleLanguages to an array with a string containing the locale before the application is fully initialised (i.e. in main.c). However this can only change languages when the application is launched.
A possible implementation:
Use CoreData to create a table of localized strings
Store a Name/Key, language, and value.
You'll then want to build out a manager class to help you read the values. Using a singleton here would probably be a good approach. You could then do things like this:
[[LanguageManager] instance] getLocalizedString:#"mainView_title" forLang:#"en"];
Have you tried to checkout this article?
I see you are asking to NOT to use localization, but the only reason I figured out is because you'd like to change language at runtime.
That post then offers (and explains how to use) a custom utility class to meet your requirements leveraging part of the already existing localization functionalities of the SDK.
Hope that's going to be useful.
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.