Archive for the ‘objectiveC snippets’ Category
Sometimes it’s crucial in your app, that you know whether your users are connected to a wireless network (EDGE, 3G, WiFi) or not.
I’ve been using the following snippet quite a lot in the past and thought, maybe someone might find it useful too.
In order to get this to work, you need to follow these steps:
1) Import the “SystemConfiguration.framework” framework into your app.
2) Add the following lines into the .m file of the class, you want to make the calls from (right below your #import lines):
#include <netinet/in.h> #import <SystemConfiguration/SCNetworkReachability.h>
3) Finally add a new method to your class:
- (BOOL)connectedToNetwork {
// Create zero addy
struct sockaddr_in zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sin_len = sizeof(zeroAddress);
zeroAddress.sin_family = AF_INET;
// Recover reachability flags
SCNetworkReachabilityRef defaultRouteReachability = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr*)&zeroAddress);
SCNetworkReachabilityFlags flags;
BOOL didRetrieveFlags = SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags);
CFRelease(defaultRouteReachability);
if (!didRetrieveFlags)
{
NSLog(@"Error. Could not recover network reachability flags");
return 0;
}
BOOL isReachable = flags & kSCNetworkFlagsReachable;
BOOL needsConnection = flags & kSCNetworkFlagsConnectionRequired;
return (isReachable && !needsConnection) ? YES : NO;
}
3a) Same method, but with updated code as suggested by Ariel in comments below
<pre>- (BOOL)connectedToNetwork {
// Create zero addy
struct sockaddr_in zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sin_len = sizeof(zeroAddress);
zeroAddress.sin_family = AF_INET;
// Recover reachability flags
SCNetworkReachabilityRef defaultRouteReachability = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr*)&zeroAddress);
SCNetworkReachabilityFlags flags;
BOOL didRetrieveFlags = SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags);
CFRelease(defaultRouteReachability);
if (!didRetrieveFlags)
{
NSLog(@"Error. Could not recover network reachability flags");
return 0;
}
BOOL isReachable = flags & kSCNetworkFlagsReachable;
BOOL needsConnection = flags & kSCNetworkFlagsConnectionRequired;
//below suggested by Ariel
BOOL nonWiFi = flags & kSCNetworkReachabilityFlagsTransientConnection;
NSURL *testURL = [NSURL URLWithString:@"http://www.apple.com/"]; //comment by friendlydeveloper: maybe use www.google.com
NSURLRequest *testRequest = [NSURLRequest requestWithURL:testURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:20.0];
//NSURLConnection *testConnection = [[NSURLConnection alloc] initWithRequest:testRequest delegate:nil]; //suggested by Ariel
NSURLConnection *testConnection = [[[NSURLConnection alloc] initWithRequest:testRequest delegate:nil] autorelease]; //modified by friendlydeveloper
return ((isReachable && !needsConnection) || nonWiFi) ? (testConnection ? YES : NO) : NO;</pre>
}
Now, you can easily check, if there is a network connection or not, like:
if ([self connectedToNetwork]) {
//yes we're connected
}
else {
//no we're not connected
}
Hope, you enjoy it.
Feedback always welcome…
Usually, iPhone apps are built using some kinda hierarchy:
- ->AppDelegate
- ->-> RootViewController
- ->->->OtherViewController(s)
- ->->->->Views
On various occasions, you might want to get some information from your AppDelegate (e.g. values, array infos, etc…).
You might already know, that there is a simple line of code, which gives you access to your AppDelegate:
AppDelegate *mainDelegate = (AppDelegate*)[[UIApplication sharedApplication]delegate];
If you need access to your AppDelegate only once or twice in a View or ViewController, this is the best way to go. However, if you have several methods in your View or ViewController and some of them need AppDelegate access, you always have to repeat the above line of code first.
In order to avoid that, there is a simple way, to permanently implement AppDelegate access in your View or ViewController:
//this example assumes, that we are using a ViewController
//inside .h file
//below #import lines
@class AppDelgate;
@interface MyViewController : UIViewController {
AppDelegate *mainDelegate;
}
//@property (nonatomic, retain) AppDelegate *mainDelegate; //error correction here - no need to @property
@end
//inside .m file
//below #import lines
#import "AppDelegate.h"
@implementation MyViewController
@synthesize mainDelegate;
- (void)viewDidLoad {
mainDelegate = (AppDelegate*)[[UIApplication sharedApplication]delegate];
}
- (void)dealloc {
//[mainDelegate release]; //error correction here - the mainDelegate object does not need to be released, since we do not call alloc init on it.
[super dealloc];
}
//now you have access to your AppDelegate in every method
//example: we assume, that our AppDelegate holds three different integer values we want to grab
- (void)methodA {
int numberA = mainDelegate.numberA;
}
- (void)methodB {
int numberB = mainDelegate.numberB;
}
- (void)methodC {
int numberC = mainDelegate.numberC;
}
As you can see, it’s slightly more work to implement AppDelegate access than just using that single line of code over and over again. However, in my opinion it’s well worth the time, especially if your .m file holds many methods.
Your code appears much cleaner that way.
[IMPORTANT: The information below is no longer up to date. Apple does now no longer allow you to use UIGetScreenImage(). Instead you need to use a different method. You can read about that on the official developer forum, located at developer.apple.com]
Not too long ago Apple decided to make on of their private APIs public. They now officially allow developers to make use of a very handy method:
+ (UIImage *)imageWithScreenContents;
Before they released it, grabbing screen contents could be a real nightmare. In some (rare) situations, it was pretty much impossible.
When you were using lots of openGL stuff in your project and wanted to grab the current state of your screen, you had to use glReadPixels();
This worked fine most of the time, but when you were dealing with transparency, it could make you pull your hair off
Anyways, those times are finally over.
To make use of this API, simply add the following lines to the .m file where you want to call it later:
//right below #import lines
CGImageRef UIGetScreenImage();
@interface UIImage (ScreenImage)
+ (UIImage *)imageWithScreenContents;
@end
@implementation UIImage (ScreenImage)
+ (UIImage *)imageWithScreenContents
{
CGImageRef cgScreen = UIGetScreenImage();
if (cgScreen) {
UIImage *result = [UIImage imageWithCGImage:cgScreen];
CGImageRelease(cgScreen);
return result;
}
return nil;
}
@end
Now you can easily do something like this:
- (void)saveScreenshotToPhotolibrary {
UIImageWriteToSavedPhotosAlbum([UIImage imageWithScreenContents], nil, nil, nil);
}
Congrats! You just saved an image with screen contents to your iPhone photo library.
-(int)getRandomNumber:(int)from to:(int)to {
return (int)from + arc4random() % (to-from+1);
}
How to use:
1) Implement method above into your .m file
2) Add the following line to your .h file:
-(int)getRandomNumber:(int)from to:(int)to;
3) Call the method like:
int randomNumber = [self getRandomNumber:9 to:99]; //this gets you a random number between 9 and 99
