iOS Development

iOS taking a screenshot programatically – using Swift

On a project I am currently working on I recently had to use one screen as the background of the next screen. In order to achieve this I opted to take a screenshot of the initial screen, save it as a UIImage and then set it as the background image of the next screen.

public class func screenShotOfView(view: UIView) -> UIImage
    {
        UIGraphicsBeginImageContextWithOptions(UIScreen.mainScreen().bounds.size, false, 0);
        view.window!.layer.renderInContext(UIGraphicsGetCurrentContext()!)
        let image:UIImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return image
}

I added the code above to a helper class that I could call from anywhere in my app allowing any screen to pass a screenshot of itself to the next screen.

You need to ensure that you are rendering the layer of the window and not just the view so that you capture navigation and tab bars in the screen shot.

“{library} does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE)”

I have been working with Xcode 7 and iOS 9 beta and updating an existing app for an iOS 9 release.
So far I have encountered a couple issues with new features introduced in iOS 9. The first, is to do with App Transport Security the second is this one. The full error is: “{library} does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. for architecture arm64

Bitcode is one component of App Thinning. It allows Apple to re-optimize your app binary in the future without the need to submit a new version of your app to the store. By default Bitcode is enabled in Xcode so any existing libraries included in the app will need to contain bitcode, hence the error.

Read more about App Thinning here

“The resource could not be loaded because the App Transport Security policy requires the use of a secure connection.”

I started getting this error when making network requests to our dev server after upgrading and testing our app using Xcode 7 and iOS 9.

It turns out that this is a feature introduced in iOS 9, App Transport Security. It basically requires the app to make requests to https urls. These also should be specified in the info.plist.

It is possible to switch this off and at the time of writing this post that was the easiest course of action.

<key>NSAppTransportSecurity</key>
<dict>
  <!--Include to allow all connections (DANGER)-->
  <key>NSAllowsArbitraryLoads</key>
      <true/>
</dict>

** This is not the advised way to deal with this error **

Have a look at Steven Peterson’s blog post going into a lot more detail about how to configure your app for App Transport Security

AFNetworking requestWithMethod:URLString: parameters:error: returns nil for URLString

I was creating a request as below to test one of my network calls.

NSMutableURLRequest *request = [self.requestSerializer
requestWithMethod:@"POST"
URLString:[NSURL URLWithString:URLString relativeToURL:self.baseURL].absoluteString
parameters:parameters
error:nil];

Annoyingly the requestSerializer would return nil for the URLString. This is the url I was expecting it to return.
{baseURL}/users/396250/bookings/33050/cancellation?reason=Bad weather

After a lot of search around for why requestSerialiser was failing on query strings, I realised I actually needed to escape the space. As soon as I did this, it worked fine.

This did reveal a bit of an architectural issue with my app and the testing as the request made within the app worked without any problems, which would suggest that at a higher level my requests are being escaped but the tests don’t seem to route through there.

Unknown class in Interface Builder file.

I was recently updating an app cerated a long time ago and I opened it in Xcode 6 hit run. Once the app launched I got an error that said “Unknown class <ClassDelegate> in Interface Builder file.

After reading through a number of suggestions of what to try, most of which were fixes for if you are using a storyboard (which I wasn’t), I found that in the didFinishLaunchingWithOption if you put [<ClassDelegate> class] then this removed the error.

“UINavigationController set unrecognized selector sent to instance” when trying to set NSString in modal view – Xcode 6

I created a new view controller embedded in a UINavigationController in my storyboard and linked it with the class. I created a action segue to a button so that when it was clicked it should present the view controller modally. When I tried to setup the segue for it and update an NSString declared in the header file of that view controller I would get an error “-[UINavigationController setCurrentSpeaker:]: unrecognized selector sent to instance 0x14c634a70

This is the code I was using to update the currentSpeaker NSString:

if ([[segue identifier] isEqualToString:@"speakerSegue"]){
        SpeakerViewController *svc = [segue destinationViewController];
        svc.currentSpeaker = thisSpeaker;
 
    }

The problem with this code is that the segue’s destinationViewController is actually the navigation controller and not the SpeakerViewController I thought it was.
I updated it to this which worked perfectly:

if ([[segue identifier] isEqualToString:@"speakerSegue"]){
        UINavigationController *navController = (UINavigationController*)[segue destinationViewController];
        SpeakerViewController *svc = (SpeakerViewController *)[navController topViewController];
        svc.currentSpeaker = thisSpeaker;
 
    }

“Warning: Attempt to present <CDVInAppBrowserViewController: 0x1ed97060> on <MainViewController: 0x1ed64730> while a presentation is in progress!”

“Warning: Attempt to present <CDVInAppBrowserViewController: 0x1ed97060> on <MainViewController: 0x1ed64730> while a presentation is in progress!”
I was getting this issue when i opened an InAppBrowser on an iOS device. When this happened the InAppBrowser would not actually load.

The solution to this is to wrap the window.open call in a setTimeout

setTimeout( function() { 
     var ref = window.open("http://www.google.co.uk","_blank","location=no");
}, 500);

This is only required for iOS as for some reason it needs some extra time before starting the InAppBrowser.
One other thing to note is that any event listeners you have on ref will need to go in the timeout or you will be trying to bind and event listener to nothing.

Undefined symbols for architecture i386 – Reachability

Today I add the Reachability classes to an app I am working on, added my #import Reachability.h to the correct files and then implemented a method to check if the device was using wifi.

When I hit build, I got the following error.

Undefined symbols for architecture i386:
"_SCNetworkReachabilityCreateWithAddress", referenced from:
+[Reachability reachabilityWithAddress:] in Reachability.o
"_SCNetworkReachabilityCreateWithName", referenced from:
+[Reachability reachabilityWithHostName:] in Reachability.o
"_SCNetworkReachabilityGetFlags", referenced from:
-[Reachability connectionRequired] in Reachability.o
-[Reachability currentReachabilityStatus] in Reachability.o
"_SCNetworkReachabilityScheduleWithRunLoop", referenced from:
-[Reachability startNotifier] in Reachability.o
"_SCNetworkReachabilitySetCallback", referenced from:
-[Reachability startNotifier] in Reachability.o
"_SCNetworkReachabilityUnscheduleFromRunLoop", referenced from:
-[Reachability stopNotifier] in Reachability.o
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)

 

I figured it was a framework that I had forgotten to add to I added the CFNetwork.framework and hit build again, same error again. I then added SystemConfiguration.framework into the project and hit build, and success!!

It was such a simple fix but the errors that were displayed weren’t really helpful with explaining what framework needed to be added.

Push Notifications for iOS Apps – PushWoosh

I came across a service for push notifications, probably a bit late to the table but I have only just needed push notifications in my apps.

Being a web developer my original idea was to host the service on my hosting and then that way I would be able to send as many notifications as I wanted without having to worry about any extra costs etc.
This seemed to be more problematic than planned as I had to have ssl and specific ports opened and my hosting is a shared hosting which means that its a bit harder to get this all implemented.

I did some research and found a number of online services that offered push notification but the one that I went with was http://www.pushwoosh.com as they offered the best free package. You get unlimited notifications and up to 10 applications. Other services like http://www.parse.com.

Push Woosh was perfect for me as I just needed bog-standard notifications and it was also pretty easy to implement too.

1 2 3  Scroll to top