I made iPhone app with eventkit framework. However, i upgrade to universal app, app can't run in ipad. I got error message
dyld: Library not loaded: /System/Library/Frameworks/EventKit.framework/EventKit
Yes, event kit only work for iOS 4.0 or later. So, how to make it for universal.
I want to make , if iPad app, don't use event kit framework.
However, I can't add
#import <EventKit/EventKit.h>
#import <EventKitUI/EventKitUI.h>
in run time
You need to do two things:
First, weak link against the EventKit framework. You do this in Target->Get Info->General.
Secondly, you need to decide at run time whether or not certain functionality is available:
Class someClass = NSClassFromString(#"SomeClass");
if(someClass) {
// iOS4 code
}
else {
// iOS3.2 code
}
Need to make weak linking.
Right Click on Target -> Get Info -> General Tab
change Eventkit Framework required to weak.
I know this is a really weak answer, but the only answer if you need EventKit on the iPad: Wait until next month when iOS 4.2 ships for the iPad. At this time use the 4.2 beta to develop your universal app. Maybe your app can be ready when the App Store starts accepting apps requiring iOS 4.2.
Related
I wrote my application for iPhone in xcode 5.0 and it supports only 7 ios.
How can I make it available for ios 6?
Also interested in how to prevent applications load on ipad?
First question: Make sure your deployment target is 6.0, don't use API's that are iOS 7 only, or check by using
if ([someObject respondsToSelector:#selector(ios7onlymethod)] {
// do your iOS 7 only stuff
} else {
// Fall back to iOS 6-supported ways
}
Or use
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0f) {
// do your iOS 7 only stuff
} else {
// Fall back to iOS 6-supported ways
}
New frameworks you want to use should be marked as optional in Xcode; to do that select your target, click general, and scroll to the "Linked Frameworks and Libraries" section.
What's really cool is that classes in frameworks marked as optional are replaced with nil on versions of iOS that don't have them. So suppose you write some code like this, using a class from the Sprite Kit framework, new in iOS 7:
SKSpriteNode *spriteNode = [SKSpriteNode spriteWithImageNamed:#"mySprite"];
On iOS 6, when the linker, which "links" frameworks to apps (apps don't copy frameworks, they just get them from the system), sees SKSpriteNode in your code, and the framework is marked as optional, that line of code will be replaced by this:
... = [nil spriteWithImageNamed:#"mySprite"];
Sending messages to nil in Objective-C does absolutely nothing, so the above code doesn't crash. No problem. So instead of lingering your code with if-statements checking for the existence of a class, you can just go with the flow and let the dynamic linker do the work.
Further reading:
iOS 7 UI Transition Guide: Supporting iOS 6
Supporting Multiple iOS Versions and Devices
Second question: There is no way to say that you want your app to only run on iPhones and iPod touches. You can require things that are specifical to the iPhone and iPod touch (like a certain processor architecture or the M7 motion coprocessor) but Apple won't like it if you require the M7 chip to exclude a certain device when you don't even need it. You should probably think about why you don't want your app to run on iPads.
With ios 4.x it is under SpringBoard, but in ios5 I can't find it.
Where is SBSMSManager in ios5 or which class in ios5 has same functions with SBSMSManager in ios4.x?
Thanks.
It seems that no SBSMSManager, but I get a simulator class called SMSPluginManager. Get the binary file named ChatKit in your iPhone.The file is under the path "/System/Library/SpringBoardPlugins/ChatKit.servicebundle/" and then class-dump it.
By the way, SpringBoard will load some plugins that are under the /System/Library/SpringBoardPlugins when it starts. When you can't find a class, try there.
I've an application which is working fine on iOS 4.0 or higher but keep crashing immediately after launch on device 3.1.3 or lower. I've set "Base SDK" to "4.1" and "Deployment Target" to "3.0".
Crash Log -
Dyld Error Message:
Symbol not found: _UIKeyboardFrameEndUserInfoKey
Referenced from: /var/mobile/Applications/FE470A03-6285-48E4-B188-A0023500AA84/XXX
Expected in: /System/Library/Frameworks/UIKit.framework/UIKit
Dyld Version: 149
I've weak linking to new frameworks.
Any help greatly appreciated.
Regards,
Amit
The constant UIKeyboardFrameEndUserInfoKey was introduced with iOS 3.2. So it's not available on a 3.1.3 device. Furthermore, the constant is defined in the UIKit framework. So weakly linking to new frameworks is not sufficient because UIKit is an old framework.
I see two options:
Switch to weak linking for UIKit (and make sure the constant isn't used on older devices).
Replace the use of UIKeyboardFrameEndUserInfoKey with UIKeyboardBoundsUserInfoKey. It's deprecated and works slightly differently. But it still works.
Weak Linking "UIKit" framework did the trick. And one more line that crashing a application was using "UIApplicationWillEnterForegroundNotification" without checking whether it's available or not.
Following checking has fixed that issue.
if (&UIApplicationWillEnterForegroundNotification != NULL) {
//Register for a notifiation when application enter into foreground state
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(reloadVCData:) name:UIApplicationWillEnterForegroundNotification object:nil];
}
Regards,
Amit
how to set iAds so the application does not crash on older OS (3.0 - 3.2)
I suppose you need to do 2 things (hope I haven't missed anything):
Link with iAd framework as 'weak': Target->Info->Linked Libraries -> Set library type as weak
Check if iAd classes are present in run-time before use them e.g.:
Class adBannerClass = NSClassFromString(#"ADBannerView");
if (adBannerClass)
// Work with banner
I'm working on a new app that I want to be universal for the iPhone and iPad. I started out with the "Create a Window-based app" wizard, and it created separate app delegates in "iPhone" and "iPad" groups. Since I already was quite familiar with iPhone dev, I did that part of my project, and now I'm ready to do some iPad stuff.
So... I started out by adding a UISplitViewController to my iPad delegate, switch the Active SDK to 3.2, and it works! But when I switch back to 3.1.3, and try to run it in the simulator, Build and Go fails. For starters, I see:
...path.../iPad/AppDelegate_Pad.h:13: error: expected specifier-qualifier-list before 'UISplitViewController'
I've got my Base SDK set to 3.2 and my Deployment Target set to 3.1.3. I thought that was enough. But I also have found in the documentation this method to conditionally compile:
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 30200
MyIPadViewController* vc;
// Create the iPad view controller
#else
MyIPhoneViewController* vc;
// Create the iPhone view controller
#endif
So do I need to do this everywhere? It seems like an awful lot of code to add (that I'll be getting rid of in a short time for 4.0 anyway) so I feel like I must be doing something wrong. And, I don't even have any idea how this works for things like #property or #synthesize declarations.
tl;dr version of the question - did I miss a setting somewhere?
I use this C function to help keep the code concise:
BOOL isPad() {
return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad);
}
Another thing I do, when I have different xib files for iPhone vs iPad. I have a stripPadSuffixOnPhone() function that helps keep the code simpler:
// Load/create the Delete table cell with delete button
self.deleteCell = [Utilities loadNib:stripPadSuffixOnPhone(#"DeleteCell~ipad")
ClassName:#"DeleteCell"
Owner:self];
Things like that can make coding more straightforward and a lot less conditionals. Still have to test everything twice though.
Quite the opposite. A universal app runs the same binary on iPhone and iPad so you cannot use conditional compilation to differentiate between the two version. But you need to use the macro Apple cites in the documentation:
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
// iPad-specific code
} else {
// iPhone-specific code
}
Here's what works for me:
Build your app using SDK 3.2.
Switch the active SDK to iPhone Simulator 3.1.3 (or whatever).
From the Run menu select Debug (not Build and Debug).
The binary built under 3.2 will be installed in the 3.x simulator without rebuilding. When you are finished don't forget to set your active SDK back to 3.2.