Thursday, February 24, 2011

Transparent Grouped UITableView on iPad

Recently I found myself needing to have a transparent UITableView on the iPad. Just setting the background to clearColor works on the iPhone but not on the iPad. So after more research I found this snippet that needs to be placed in viewDidLoad.

tableView.backgroundView = nil;

Setting this property to nil will allow whatever is behind the tableView (in my case a UIImageView) to show through.

Tuesday, January 4, 2011

SplitViewController with NavigationBar doesn't retain Tint

Update: This appears to be working in the beta of IOS 4.3!
--------------------

One of the things that is broken in iOS 4.2 is the tint color on the navigation bar in the Root View of the SplitViewController. What happens is that if you set the tint color, it will show correctly until you rotate to portrait mode, tap the List button, then rotate back to landscape.

The issue is discussed in great detail here: https://devforums.apple.com/thread/68443?start=0&tstart=0

One of the proposed solutions is to SubClass the NavigationBar Class and override the setTint method. (Credit goes to Hans Harris)

Below is a link to a complete working implementation.
http://dl.dropbox.com/u/9163557/SplitView_NavBar_setTint2.zip

Saturday, January 1, 2011

Memory Management

I was starting to put together a post on memory management and retain/release when I came across this post.

http://cocoasamurai.blogspot.com/2010/12/objective-c-memory-management-garbage.html

Wednesday, August 25, 2010

Using the External VGA Connector

One of the things that we wanted to do was plug in the external VGA adapter to a projector and demo the app to a room of people.  Sounds simple right?  Well, not really.

When using the external VGA Adapter, the device as two windows that you must add separate views to.  After an entire day attempting to capture all events from one window and attempting to pass them to the other window, I decided to take a more brute force method.  Take a screen capture every 1/4 second and display it on the external display.

The steps are below.

1. Create a UIViewController with a XIB and call it ExternalDisplayViewController.
2. In Interface Builder add a single UIImageView and set the View Mode to Aspect Fit.
3. Add a property to the ExternalDisplayViewController.h.  Don't forget to "Wire" it up in interface builder.
4. Modify the AppDelegate.h file accordingly.

#import <UIKit/UIKit.h>

@class ExternalDisplayViewController;

@interface MyAppDelegate : NSObject <UIApplicationDelegate, UIAlertViewDelegate> {
    UIWindow *deviceWindow;
 
 NSArray *screenModes;
 UIScreen *externalScreen;
 
 ExternalDisplayViewController *externalVC;

}
@property (nonatomic, retain) NSTimer *repeatingTimer;

@property (nonatomic, retain) IBOutlet UIWindow *deviceWindow;
@property (nonatomic, retain) IBOutlet UIWindow *externalWindow;

- (void) takeCapture:(NSTimer*)theTimer;

@end

5. Modify the MainWindow.xib file.  Add a second window (that will dsplayed on the external display).  Don't forget to "Wire" two windows to the new properties.

6. Add the Quartz Framework to your project and add the import line to the AppDelegate.m file.

#import <QuartzCore/QuartzCore.h>

7. Add the following code to your AppDelegate.m didFinishLaunchingWithOptions
if ([[UIScreen screens] count] > 1) {
    
   //[self log:@"Found an external screen."];
   
   // Internal display is 0, external is 1.
   externalScreen = [[[UIScreen screens] objectAtIndex:1] retain];
   //[self log:[NSString stringWithFormat:@"External screen: %@", externalScreen]];
   
   screenModes = [externalScreen.availableModes retain];
   //[self log:[NSString stringWithFormat:@"Available modes: %@", screenModes]];
   
   // Allow user to choose from available screen-modes (pixel-sizes).
   UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:@"External Display Size" 
            message:@"Choose a size for the external display." 
            delegate:self 
            cancelButtonTitle:nil 
            otherButtonTitles:nil] autorelease];
   for (UIScreenMode *mode in screenModes) {
    CGSize modeScreenSize = mode.size;
    [alert addButtonWithTitle:[NSString stringWithFormat:@"%.0f x %.0f pixels", modeScreenSize.width, modeScreenSize.height]];
   }
   [alert show];
   
}

8. Add the following code to your AppDelegate.m file.

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
 UIScreenMode *desiredMode = [screenModes objectAtIndex:buttonIndex];
 externalScreen.currentMode = desiredMode;
 externalWindow.screen = externalScreen;
 
 [screenModes release];
 [externalScreen release];
 
 CGRect rect = CGRectZero;
 rect.size = desiredMode.size;
 externalWindow.frame = rect;
 externalWindow.clipsToBounds = YES;
 
 externalWindow.hidden = NO;
 [externalWindow makeKeyAndVisible];
 
 externalVC = [[ExternalDisplayViewController alloc] initWithNibName:@"ExternalDisplayViewController" bundle:nil];
 CGRect frame = [externalScreen applicationFrame];
 switch(externalVC.interfaceOrientation){
  case UIInterfaceOrientationPortrait:
  case UIInterfaceOrientationPortraitUpsideDown:
   [externalVC.view setFrame:frame];
   break;
  case UIInterfaceOrientationLandscapeLeft:
  case UIInterfaceOrientationLandscapeRight:
   [externalVC.view setFrame:CGRectMake(frame.origin.x, frame.origin.y, frame.size.height, frame.size.width)];
   break;
 }
 
 [externalWindow addSubview:externalVC.view];
 
 NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.25
   target:self selector:@selector(takeCapture:)
   userInfo:nil repeats:YES];
 self.repeatingTimer = timer;
}

- (void) takeCapture:(NSTimer*)theTimer{
 UIView *mainView = [deviceWindow.subviews objectAtIndex:0];
 
 if (mainView) {
  UIGraphicsBeginImageContext(mainView.frame.size);
  [mainView.layer renderInContext:UIGraphicsGetCurrentContext()];
  UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
  
  [externalVC.imgView setImage:viewImage];
  UIGraphicsEndImageContext();
 }
 
}




Monday, August 23, 2010

Getting Started

Over the past two months myself and co-worker have been tasked with creating a working prototype of and iPad application for our company to demo at fall trade shows.  Being a complete Microsoft technology shop this has been quite an undertaking.

The goal of this blog is to share some of stuff that we struggled with the hopes that you won't have to re-invent our wheel.

The posts will not be in any particular order, as I post stuff from the past couple of months.