well to begin with I'm sure this is a simple question.
I am developing an iPhone app with the iAd Framework, which only runs for iOS 4.0 or higher.
Still, I wanna choose a iPhone OS 3.0 deployment target, which causes everything to crash.
How do I conditionally include the iAd framework?
...I mean, it would be something like:
...if([[UIDevice currentDevice] systemVersion]>=4.0]) #import
Obviously this won't work because I don't know the correct syntax. Also:
How do I conditionally declare an AdView* variable?
How do I conditionally handle this AdView* variable in my implementation file.
If you guys could help me, I will be very well impressed.
Thanks
You don't need to change your include, you need to make the iAd (or any other new framework) linked weakly:
In your target, find iAd in the linked frameworks and change its "Role" from "Required" to "Weak".
To handle the variable conditionally, use NSClassFromString function, like this:
Class AdClass = NSClassFromString(#"ADBannerView");
if(AdClass) {//if the class exists
ADBannerView* myAd = [[AdClass alloc] initWithFrame:CGRectZero];
// do something with the ad
}
If OS is older than iOS 4.0, AdClass will be nil and the code won't execute. Note that using ADBannerView* as the type of the variable shouldn't cause any problems, as it's just a hint for a compiler and is the same as id after compilation.
Related
In my Swift 2 project, targeting iOS 9.2 and above, in Xcode 8.2.1, I have code that shows the mail-compose screen like so:
if MFMailComposeViewController.canSendMail() {
let composeMailVC = MFMailComposeViewController()
composeMailVC.mailComposeDelegate = self
composeMailVC.setSubject("Test")
// etc
}
Originally I had a reference to the MessageUI.framework in my project properties, but after removing the framework reference and cleaning the project, it still builds fine and when I run the code on my device the mail compose window still appears and seems fully functional.
I cannot find any explicit references to MessageUI.framework in the raw text of my .xcodeproj file, nor is there anything in my Objective-C bridging header.
I know that Swift does make some implicit framework references, but I couldn't find anything that suggests MessageUI.framework is one of them.
Curiously when I jump to the definition of MFMailComposeViewController XCode shows it in the MessageUI module.
The compiler automatically added the frame work in given its previous direction - IE. Import.
So I am attempting to bring the iOS 5 SDK to the Theos Makefile system. I have the following things working: Private Frameworks, Multitasking from UIKit. Since Theos uses SDK 3. This jump to SDK 5 breaks a few methods as they're deprecated. Keep in mind that I'll be using RPetrich's headers on GitHub for this. With that in mind, I'm trying to add the following dismissal code to the UIViewController header.
- (void)dismissViewControllerAnimated: (BOOL)flag completion: (void (^)(void))completion __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_5_0);
This makes my compiler complain about the (void (^) (void)) part. I've tried replacing it with BOOL and just a regular void and then just calling nil when using the method. Doesn't work that way. I wanted to know if there was a way I can successfully compile with this method, or if I can somehow use dismissModalViewControllerAnimated: again. Some reason I can still use presentModalViewController:animated: and it says they both WILL be deprecated. Any suggestions?
change default compiler gcc/g++ to apple's clang/clang++
There are 2 "writeImageToSavedPhotosAlbum" methods in ALAssetsLibrary Class:
- (void)writeImageToSavedPhotosAlbum:(CGImageRef)imageRef
metadata:(NSDictionary *)metadata
completionBlock:(ALAssetsLibraryWriteImageCompletionBlock)completionBlock
(available on iOS 4.1+)
- (void)writeImageToSavedPhotosAlbum:(CGImageRef)imageRef
orientation:(ALAssetOrientation)orientation
completionBlock:(ALAssetsLibraryWriteImageCompletionBlock)completionBlock
(available on iOS 4.0+)
I am using the 1st one (need iOS 4.1) in my code and it will crash on iOS 4.0 device. I am trying to use respondsToSelector to check which method is supported, however looks like the selector only check the method name, not the parameters.
I read some suggestions and feel it might not good by purely check on OS version, so is there anything similar to respondstoselector that can help me solve this problem?
You misunderstand the Objective-C method naming system. The selector is the combination of all foo:bar:baz: combined.
So, in this case, there is no method called writeImageToSavedPhotosAlbum. The first one is, as a selector, corresponds to
#selector(writeImageToSavedPhotosAlbum:metadata:completionBlock:)
and the second one is
#selector(writeImageToSavedPhotosAlbum:orientation:completionBlock:)
In your code, check whether the first selector is available or not, as in
if([obj respondsToSelector:#selector(writeImageToSavedPhotosAlbum:metadata:completionBlock:)]){
....
}
This should distinguish whether the first one is available or not.
These methods have different names, so you can test them separately.
if ([assetsLibrary respondsToSelector:
#selector(writeImageToSavedPhotosAlbum:metadata:completionBlock:)]) {
// Now you can safely use this method.
}
If you wanted to test the other one you would use #selector(writeImageToSavedPhotosAlbum:orientation:completionBlock:).
You can then differentiate them with os version. How about it?
Hi
I am using SDK 4.1 to build an iPhone app and I set the target OS to 3.1.3.
When I install the app on devices running iOS4.1. everything goes smoothly.
When I try to run the app on devices running 3.1.3 I get the stacktrace below.
dyld: Symbol not found: _OBJC_CLASS_$_UINib
Referenced from: /var/mobile/Applications/BDD67A1E-9B40-43E7-A012-7D92036B2E24/ThisIsMy.app/ThisIsMy
Expected in: /System/Library/Frameworks/UIKit.framework/UIKit
in /var/mobile/Applications/BDD67A1E-9B40-43E7-A012-7D92036B2E24/ThisIsMy.app/ThisIsMy
My guess is that it's because UINib was only added to the SDK in 4.0.
What I would like to know is how you mitigate this problem. What should I do to support 3.1.3?
Cheers..
I strongly recommend you not weakly link UIKit. This may hide future linker issues and result in crashes. I'm also simply not comfortable with telling the linker that UIKit is optional when it plainly isn't. Big hack.
Instead, initialize and call UIPopoverController indirectly using NSClassFromString:
Class popover = NSClassFromString(#"UIPopoverController");
if (nil != popover)
{
self.myPopover = [[popover alloc] initWithContentViewController:myContent];
}
If you still have linker errors, you may need to call UIPopoverController's messages using NSSelectorFromString:
Class popover = NSClassFromString(#"UIPopoverController");
if (nil != popover)
{
SEL myInit = NSSelectorFromString(#"initWithContentViewController:");
self.myPopover = [[popover alloc] performSelector:myInit withObject:myContent];
}
For portability, I recommend writing a proxy object to handle these implementation details.
First, you need to change the framework reference to a weak link (aka "optional"). Then use the techniques described here to test that a class exists before calling your code that uses it.
I am writing an app for my iPad running 3.2.2 with XCode 3.2.3. It seems that the highest version of the iOS for iPad this version of XCode has is 3.2, but other apps load fine onto the phone so this doesn't seem to be an issue. I am attempting to make use of the new UITextChecker class. I have imported UIKit, and UITextChecker.h appears in the headers folder under the UIKit.framework icon. However, when I try to compile this code:
NSString *theLanguage = [[UITextChecker availableLanguages] objectAtIndex:0];
or simply this:
UITextChecker *textChecker;
XCode tells me that UITextChecker is undeclared. Any ideas what it going on here? Thanks!
James
Here is a picture of the UIViewController's header file:
For whatever reason, UIKit.h does not import UITextChecker.h. You can fix this by also adding the following line.
#import <UIKit/UITextChecker.h>