Posts Tagged Development

iPhone Network Connectivity Test Example

Every iPhone developer that has integrated a network connection based application has had to follow the Apple HID (Human Interface Design) rules. This means, that in order to get the Apple reviewers to sign-off on your application, you have to pass the network connectivity test. Basically, in the case of a catastrophic network disconnect issue with 3G and WiFi does your application properly alert the user that it will not perform properly without the usage of the network? I’ve seen a lot of workaround techniques where users attempt to do an HTTP GET on say Google or some other website. Clearly, this kind of technique will work sporadically in an unknown environment common to the mobile device. I mean, imagine causing your application users to sit through a 5-30 second web request timeout. The end-user will probably believe that the application is hung. The ideal solution happens to be handed to us in the API Framework SCNetworkReachability. (Make sure your codebase is linked properly with the “SystemConfiguration” Framework).
It’s worked for me and I recommend it for doing a simple network connectivity test.

#import <sys/socket.h>
#import <netinet/in.h>
#import <arpa/inet.h>
#import <netdb.h>
#import <SystemConfiguration/SCNetworkReachability.h>
//Snip, you know we're in the implementation...
- (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)
	{
		return NO;
	}
 
	BOOL isReachable = flags & kSCNetworkFlagsReachable;
	BOOL needsConnection = flags & kSCNetworkFlagsConnectionRequired;
	return (isReachable && !needsConnection) ? YES : NO;
}
 
//call like:
-(void) start {
	if (![self connectedToNetwork]) {
                UIAlertView *alert = [[UIAlertView alloc] 
                         initWithTitle:@"Network Connection Error" 
                         message:@"You need to be connected to the internet to use this feature." 
                         delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
		[alert show];
		[alert release];
        } else {
             //do something 
        }
}

This code can also be found on this forum post.

, , , ,

17 Comments

.Net C Sharp Date Range Check Method

This function is a trivial example of how to do a basic date range check in .Net. I do a few silly conversions from string to timestamp only to serve as an example.

View Code CSHARP
/*
Assumes the local culture.  
Does a check to see if the current time is within the range 
  of 7 AM and 1 PM.  If so, returns true.
*/
if (IsCurrentDateInRange("7:00", "13:00")) {
   //The current date is in range.
} else {
  //The current date is out of range.
}
View Code CSHARP
using System;
/*
startTime should be in the format HH:mm such as 09:45
endTime should be in the format HH:mm such as 18:45
The culture is assumed to be the local one which can be 
troubling in applications that extend themselves internationally.
*/
public bool IsCurrentDateInRange(string startTime, string endTime) {
  DateTime dtNow = DateTime.Now;
  DateTime dtStart, dtEnd;
  int hour = 0, minute = 0;
 
  string[] strDt = startTime.Split(new char[] { ':' });
  if (strDt.Length > 1)
  {
     Int32.TryParse(strDt[0], out hour);
     Int32.TryParse(strDt[1], out minute);
 
     dtStart = new DateTime(dtNow.Year, dtNow.Month, dtNow.Day, hour, minute, 0);
  }
  else
  {
     //TODO: log an error in formatting.
     return false;
  }               
 
  strDt = endTime.Split(new char[] { ':' });
  if (strDt.Length > 1)
  {
     hour = minute = 0;
     Int32.TryParse(strDt[0], out hour);
     Int32.TryParse(strDt[1], out minute);
 
     dtEnd = new DateTime(dtNow.Year, dtNow.Month, dtNow.Day, hour, minute, 0);
  }
  else
  {
     //TODO: log an error in formatting.
    return false;
  }
 
  TimeSpan tsEndDiff = dtEnd - dtNow;
  TimeSpan tsStartDiff = dtNow - dtStart;
  if (tsStartDiff.TotalSeconds >= 0 && tsEndDiff.TotalSeconds >= 0)
  {
     return true;
  }
  else 
     return false;
}

, , ,

No Comments

iPhone (SIGBUS) Issue

If you’ve ever done any iPhone development, you’ve probably had an accident with the (nonatomic, retain) methods. These methods are difficult to use in the case where you’re working with multiple threads. Our application does not do this, but we do utilize the OpenGL ES 1.1 framework. Have a look at the following console log from the other night when my brother was beta testing our application with some friends at a bar.

View Code IPHONE_CONSOLE_LOG
Process:         myExampleApp [800]
Path:            /var/mobile/Applications/5D234CF0-1234-4E2F-9A7F-14175F39A0B6/myExampleApp.app/myExampleApp
Identifier:      myExampleApp
Version:         ??? (???)
Code Type:       ARM (Native)
Parent Process:  launchd [1]
 
Date/Time:       2009-07-19 23:20:40.285 -0700
OS Version:      iPhone OS 3.0 (7A341)
Report Version:  104
 
Exception Type:  EXC_BAD_ACCESS (SIGBUS)
Exception Codes: KERN_PROTECTION_FAILURE at 0x00000008
Crashed Thread:  0
 
Thread 0 Crashed:
0   libobjc.A.dylib                   0x30011940 objc_msgSend + 20
1   libobjc.A.dylib                   0x3001313c objc_setProperty + 160
2   myExampleApp                          0x000126e6 -[GameUIView setBasicObj:] (GameUIView.m:36)
3   myExampleApp                          0x0000f694 -[GameUIView setupView] (GameUIView.m:404)
4   myExampleApp                          0x0000ec42 -[GameUIView start] (GameUIView.m:173)
5   myExampleApp                          0x00002816 -[CoreViewController playGame] (CoreViewController.m:79)
6   myExampleApp                          0x00005e80 -[SplashGLUIView touchesEnded:withEvent:] (SplashGLUIView.m:606)
7   UIKit                             0x309a60d4 -[UIWindow _sendTouchesForEvent:] + 520
8   UIKit                             0x309a5464 -[UIWindow sendEvent:] + 108
9   UIKit                             0x30936e3c -[UIApplication sendEvent:] + 400
10  UIKit                             0x30936874 _UIApplicationHandleEvent + 4336
11  GraphicsServices                  0x32046964 PurpleEventCallback + 1028
12  CoreFoundation                    0x30254a70 CFRunLoopRunSpecific + 2296
13  CoreFoundation                    0x30254164 CFRunLoopRunInMode + 44
14  GraphicsServices                  0x3204529c GSEventRunModal + 188
15  UIKit                             0x308f0374 -[UIApplication _run] + 552
16  UIKit                             0x308eea8c UIApplicationMain + 960
17  myExampleApp                          0x000020b6 main (main.m:14)
18  myExampleApp                          0x0000202c start + 44

The core method here that is the issue is implemented as:

//in the .h file.  
@property (nonatomic, retain) NSObject *basicObj;
 
//in the .m file.
@synthesize basicObj;
 
- (void)setupView
{
   if (self.basicObj != nil) {
		[self.basicObj release];
		self.basicObj = nil; //line 404, this is where the error is located.
   }
}

As you can see, the issue appears to be based on how we access the basicObj object. The definition of a SIGBUS error, is pretty straight forward. We are generically having some sort of memory issue.

As of this writing, I’m still doing extensive testing and I’ll update this post if I find a better solution. Here is what I’ve found to work. I’m beginning to wonder if there is a funny timing issue with the “release” methodology. I’ll make sure to post back here if I find there to still be an issue or I find a better solution. Comments are appreciated.

- (void)setupView
{
   if (self.basicObj != nil) {
		[basicObj release];
		basicObj = nil;
}

, , ,

9 Comments