Conditional code for iOS class availability - ios

I am trying to add conditional code to prevent "Symbol not found" errors on an iOS 7 device when using an iOS 8 class, in this case UIBlurEffect:
dyld: Symbol not found: _OBJC_CLASS_$_UIBlurEffect
Even though the code within the conditional does not run (I do not see the "UIBlurEffect will be used!" log statement), I still get the error. If I comment the block out, it runs fine.
BOOL blurAvailable = NSClassFromString(#"UIBlurEffect") ? YES : NO;
if (blurAvailable)
NSLog(#"UIBlurEffect available");
else
NSLog(#"UIBlurEffect not available");
if (navBarBlurBool && blurAvailable)
{
NSLog(#"UIBlurEffect will be used!");
if (![viewController.navigationController.navigationBar viewWithTag:BLUR_NAVBAR_TAG])
{
// Code works on iOS 7 if this block is commented out:
[self storeOriginalNavBarImages];
[self.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
self.navigationController.navigationBar.shadowImage = [UIImage new];
UIVisualEffectView *blur = [[UIVisualEffectView alloc] initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]];
CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];
blur.frame = CGRectMake(0, -1 * statusBarFrame.size.height, self.navigationController.navigationBar.frame.size.width, self.navigationController.navigationBar.frame.size.height + statusBarFrame.size.height);
blur.userInteractionEnabled = NO;
blur.tag = BLUR_NAVBAR_TAG;
[self.navigationController.navigationBar insertSubview:blur atIndex:0];
}
}
I don't understand - I would assume that if blurAvailable is false then the offending code should not run and I should not get the "Symbol not found" runtime error.
I'm using iOS 9.2 SDK. Xcode 7.2. Deployment target is iOS 7.0.

Please make sure that blurAvailable is really NO on iOS 7.
Maybe the class is available on iOS 7 but not marked as such in the documentation. They might have introduced it in iOS 7 as a private class (just hiding it in the doc and headers).
Try testing another class marked as "unavailable on iOS 7" like UIVisualEffectView.

From a comment in this question, the answer is to add UIKit as an Optional dependency in "Build Phases" -> "Link Binary with Libraries". I can now run the conditional iOS 8 code without errors on the iOS 7 device.

Related

UIBarButtons disappeared in iOS 9.2

I have just upgraded one of my Apps under development to iOS 9.2 and I have found that all navigationbar UIBarButtons have just disappeared and are not shown on the navigation bar.
BTW: I'm using the UIBarButton custom class called BBBadgeBarButtonItem
from here
Update 1
Here is a snippet from the code I used to add the UIBarButtonItem
// Add the search button
UIImage* searchBtnImg = [UIImage imageNamed:#"searchBarButton"];
searchBtnImg = [self ipMaskedImage:searchBtnImg color:[UIColor pddAppSelectedIconColor]];
CGRect frame = CGRectMake(0, 0,searchBtnImg.size.width,searchBtnImg.size.height);
UIButton* searchBtn = [[UIButton alloc] initWithFrame:frame];
[searchBtn setBackgroundImage:searchBtnImg forState:UIControlStateNormal];
[searchBtn addTarget:self action:#selector(_searchContent) forControlEvents:UIControlEventTouchDown];
self.searchBarButtonItem = [[BBBadgeBarButtonItem alloc] initWithCustomUIButton:searchBtn];
self.searchBarButtonItem.shouldHideBadgeAtZero = YES;
self.searchBarButtonItem.badgeValue = #"0";
self.navigationItem.leftBarButtonItem = self.searchBarButtonItem;
Update 2
I see the following error message
<Error>: CGContextSetFillColorWithColor: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
and from this answer it seems to be an Apple Bug
I have figure it out, the ImageCatalog for random reason have make the custom BarButtonItem Unassigned for some unknown reason.... What a stupid thing ;(
Also, as I general note I have noticed that opening Xcode project for iOS9.1 on newer Xcode 7.2 or vice versa I got some of the already added images into the ImageCatalog to be in Unusigned state and the App couldn't see it until I fix that in ImageCatalog.

iOS 9 disable support for right-to-left language

My iOS app is in Arabic (right-to-left) language only. Prior to iOS 9 the views layout and view animations were all by default left-to-right. So, I had customised the complete app and had reversed the default behaviour e.g. back button in navigation bar was set to be on the right instead of default left.
But now when the app is compiled using latest SDK (Xcode 7 beta 4), everything is the opposite of what I need.
Is there any simple way to force the app to show views and behave like iOS 8 and 7?
I searched and found a solution but it involves changing the constraints(Uncheck the "Respect language direction") for all views. But this is not a feasible solution in large projects.
This is a screenshot after compiling with Xcode 7 beta 4.
and this is a screenshot when compiled with Xcode 6.
Edit: The following code may cause unexpected behavior as #wakachamo pointed out. So, please watch out for issues e.g. Interactive pop gesture doesn't work, alertviews don't show, etc. Its better to follow the instruction provided by #wakachamo if this doesn't work for you
Add this to app delegate didFinishLaunchingWithOptions method.
[[UIView appearance] setSemanticContentAttribute:UISemanticContentAttributeForceLeftToRight];
Also add guard to support earlier version so that the property doesn't cause any crash.
if([[[UIView alloc] init] respondsToSelector:#selector(setSemanticContentAttribute:)]) {
[[UIView appearance] setSemanticContentAttribute:UISemanticContentAttributeForceLeftToRight];
}
[[UIView alloc] init] instead of [UIView appearance] because respondsToSelector is not currently working with [UIView appearance] for setSemanticContentAttribute. You can also add iOS 9 Check
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"9.0")) {
[[UIView appearance] setSemanticContentAttribute:UISemanticContentAttributeForceLeftToRight];
}
i found the correct way from Apple Developer Forums
here iOS 9 beta - UIAlertController is not working
just add this code to make alertview work with it
if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"9.0")) {
[[UIView appearance] setSemanticContentAttribute:UISemanticContentAttributeForceLeftToRight];
[[UIView appearanceWhenContainedIn:[UIAlertController class], nil] setSemanticContentAttribute:UISemanticContentAttributeUnspecified];
[[UIView appearanceWhenContainedIn:[UIAlertView class], nil] setSemanticContentAttribute:UISemanticContentAttributeUnspecified];
}
I know its too late to answer. But I have figured it out (Only the navigation bar issue).
The answer is adapted from #Kamran Kan. Thanks #Kamran.
Jus replace the UIView with UINavigationBar in #Kamran's answer. then the code will be as follows.
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"9.0")) {
[[UINavigationBar appearance] setSemanticContentAttribute:UISemanticContentAttributeForceLeftToRight];
}
Since it is only effect the UINavigationBar, the other controls won't effect. So the UIAlertView is working fine...
There is no easy way. It's recommended that you migrate to standard API as much as possible long-term.
Another approach is to set the semanticContentAttribute of all the affected views to UISemanticContentAttributeForceLeftToRight, but this is just as feasible as setting all your constraints to use Left/Right instead of Leading/Trailing. In addition to this, you'll also have to gate these calls around an availability check if you're targeting iOS <9.
SWIFT 2 Code
if #available(iOS 9.0, *) {
myView.semanticContentAttribute = .ForceLeftToRight
}
For SWIFT 3
if #available(iOS 10.0, *) {
UIView.appearance().semanticContentAttribute = .forceLeftToRight
}
Use Storyboard and choose for each specific view controllers
Semantic->Force Left-to-Right.

EXC_BAD_ACCESS when retrieving views from transition context on iPhone 4

I have the following code, which works perfectly on my iPhone 5 and all the iPhone simulators, but it crashes on my iPhone 4. I get EXC_BAD_ACCESS on the last line where I pass UITransitionContextToViewKey to my transition context.
I have a clean analyze and build, and the same happens for both UITransitionContextFromViewKey and UITransitionContextToViewKey.
My iPhone 4 is on iOS 7.1.2, my deployment target is 7.0, targeted build base SDK 8.0.
Anyone knows what to do here? thx.
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
// get transition parameters from context
UIView *containerView = transitionContext.containerView;
UIViewController *destinationViewController =
[transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
if ([destinationViewController.title isEqualToString:#"ListController"]) {
// get source and destination views
UIView *sourceViewSnapshot = [self.view snapshotViewAfterScreenUpdates:YES];
UIView *destinationView = [transitionContext viewForKey:UITransitionContextToViewKey]; // EXC_BAD_ACCESS
// ...
}
The viewForKey method is iOS 8 and up, but the viewControllerForKey method is supported in iOS 7. A small change to your code gets the view in iOS 7:
UIView *destinationView = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey].view;
From the documentation:
UITransitionContextToViewKey
Available in iOS 8.0 and later.
You can't run that code on iOS 7
You might want to add runtime system version checks and branch out to a iOS 7 compatible code at this point if you want to maintain compatibility with this version of the system

IBM Worklight 6.0 - App Center on iOS7 fails to open

After building the IBMAppCenter application with Xcode 5.0.2,
When running the .ipa on an iPhone it unfortunately doesn't work.
When clicking the app it opens up, shows the splash image for a few seconds, but then closes without throwing an error.
Is this a known error?
Make sure that you have followed the instructions on how to enable the AppCenter application for iOS 7, as detailed in the following IBM technote: http://www-01.ibm.com/support/docview.wss?uid=swg27039574
I'd even say to make sure you are running the correct version of Worklight.
Please carefully read the technote.
Copy/paste:
Enable the Application Center Client
Complete the following steps to enable your Application Center Client to run on iOS 7:
Import the App Center project into Eclipse as the documentation states.
Use the Worklight Studio wizard to create another Worklight project and add an iPhone environment.
Copy the apps/appName/iphone/native/WorklightSDK/libWorklightStaticLibProject.a file to the App Center project. Overlay the existing file by using the same name.
Add the following code in the CDVMainViewController Worklight generated class (CDVMainViewController.m). This code handles the iOS 7 status bar design change.
- (UIStatusBarStyle)preferredStatusBarStyle
{
return UIStatusBarStyleLightContent;
}
- (void)viewWillAppear:(BOOL)animated
{
CGFloat version = [[UIDevice currentDevice].systemVersion floatValue];
if (version >= 7) {
// iOS 7 or above
CGRect oldBounds = [self.view bounds];
CGRect newViewBounds = CGRectMake( 0, -10, oldBounds.size.width,
oldBounds.size.height-20 );
CGRect newWebViewBounds = CGRectMake( 0, -20, oldBounds.size.width,
oldBounds.size.height-40 );
UIColor *headerColor =
[UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:1.0f];
[self.view setBackgroundColor:headerColor];
[self.view setBounds:newViewBounds];
[self.webView setBounds:newWebViewBounds];
}
[super viewWillAppear:animated];
}

UITableView background View nil doesn't work in iOS 5

I need to make my grouped UITableView backgroundColor transparent.
So i write following code. That is work in iOS 6. But in iOS 5, it doesn't work.
self.tbView.backgroundView = nil;
How to do that in iOS 5.
Are you setting [self.tbView setBackgroundColor:[UIColor clearColor]];?
If not, you need to add that or you won't get a transparent backgorund color.
You Need to put background Nil code into ViewDidLoad this is working fine in my Code. Hope this Helps you.
[tbl_My_Table setBackgroundView:nil];
[tbl_My_Table setBackgroundView:[[[UIView alloc] init] autorelease]];
I got it answer.
We need to add two lines of codes for both iOS 6 and iOS 5.
Here is codes.
self.tblPreferences.backgroundView = nil;
self.myTable.backgroundColor = [UIColor clearColor];
That is working both iOS 5 and 6.

Resources