apple Archive

Testflight from Apple is a program with which beta testing for iOS applications can be performed. It consists of a service, which provides the functions, and an app on the test device that interacts with the user. Testflight is especially interesting from the perspective of developers, because they get faster feedback. Also for companies, the use of Testflight is an advantage, because what helps in development increases productivity.

Testflight has been used by app developers as an beta test platform since several years. Apple bought the service this year in connection with the acquisition of Burstly, the company that originally developed the platform. Apple has redesigned the program and made it available as an integrated iOS 8 service for both developers and testers.

Certainly you’ve read some of the many news and articles about the new version 8 of Apple’s iOS, which circulated in the past few months in the media. All the new functions and applications where described extensively in these texts. In business, this is important, but equally important are things that home users mostly do not care for. These mainly include data security, a coordinated management of the mobile equipment and the software as well as an accurate measurability of productivity improvement.

In order to implement your own style ideas or a given layout it might be necessary to create custom UITableViewCells with round corners. In the App the UITableView might look like this:

UITableViewCells with round corners

With your custom UITableViewCell class and some core graphics it’s quite easy to solve this problem.

Open your project in XCode. At first we have to add a new file of type UITableViewCell. I call it “RoundedTableViewCell”.

We have to import the QuartzCore framework which includes all core graphics.

#import <QuartzCore/QuartzCore/>

Don’t forget to add it also to the “frameworks” folder of your project:

add QuartzCore FRamework to your project add QuartzCore framework

In the RoundedTableViewCell.h-file we define a CALayer for every corner of the cell. These small square layers will later on “cover” the round corners where desired.

CALayer* topleft;
CALayer* topright;
CALayer* bottomleft;
CALayer* bottomright;
CALayer* bglayer;
...
@property (nonatomic, retain) CALayer* topleft;
@property (nonatomic, retain) CALayer* topright;
@property (nonatomic, retain) CALayer* bottomleft;
@property (nonatomic, retain) CALayer* bottomright;
@property (nonatomic, retain) CALayer* bglayer;

We also need two BOOLs:

BOOL roundTop;
BOOL roundBottom;
...
@property (nonatomic) BOOL roundTop;
@property (nonatomic) BOOL roundBottom;

.. and two methods to tell the single cell to have round corners at the top and/or the bottom:

-(void) drawRoundTop;
-(void) drawRoundBottom;

That’s it for the .h-file. In the RoundedTableViewCell.m we have now to implement the rounded corners. At first we define a corner radius and a background color for the cell (between #import and @implemetation):

#define rad 15  // radius
#define normalColor [UIColor colorWithRed:0.39 green:0.15 blue:0.24 alpha:1.0]  // cell background color, dark red

Whithin the implementation we have to synthesize our defined CALayers and BOOLs:

@synthesize topleft;
@synthesize topright;
@synthesize bottomleft;
@synthesize bottomright;
@synthesize bglayer;
@synthesize roundTop;
@synthesize roundBottom;

In the initWithStyle-Method we define an UILabel with some style attributes:

// add label
 label = [[UILabel alloc] initWithFrame:self.contentView.frame];
 label.textAlignment = UITextAlignmentLeft;
 label.backgroundColor = [UIColor clearColor];
 label.textColor = [UIColor whiteColor];
 label.font = [UIFont fontWithName:@"Zapfino" size:16];
 [self.contentView addSubview:label];

// initial values
 roundTop = NO;
 roundBottom = NO;
// set layer background color (= cell background color)
 self.layer.backgroundColor = normalColor.CGColor;

Still within the initWithStyle-method, we set the initial cell style without round top or bottom corners and set the cell’s background color:

roundTop = NO;
roundBottom = NO;
self.layer.backgroundColor = normalColor.CGColor;

Our custom drawRect method will draw our round corners, depending on the defined corner radius. Then the round corners are “covered” by drawing a CALayer for every corner:

- (void) drawRect:(CGRect)rect{
	CGRect fr = rect;

	fr.size.width = fr.size.width-2*rad;
	fr.size.height = fr.size.height-1;
	fr.origin.x = rad;

	// draw round corners layer
	bglayer = [CALayer layer];
    bglayer.backgroundColor = normalColor.CGColor;
	bglayer.cornerRadius = rad;
	bglayer.frame = fr;
	bglayer.zPosition = -5;	// important, otherwise delete button does not fire / is covered
	[self.layer addSublayer:bglayer];

	// set label size (adjust to heightForRowAtIndexPath..)
	label.frame = CGRectMake(rad, 5, fr.size.width, fr.size.height);

	// corner layer top left
	topleft = [CALayer layer];
    topleft.backgroundColor = normalColor.CGColor;
	CGRect tl = CGRectMake(rad, 0, rad, rad);
	topleft.frame = tl;
	topleft.zPosition = -4;
	if(roundTop){
		topleft.hidden = YES;
	}else {
		topleft.hidden = NO;
	}
    [self.layer addSublayer:topleft];

	// corner layer top right
	topright = [CALayer layer];
    topright.backgroundColor = normalColor.CGColor;
	topright.frame = CGRectMake(fr.size.width, 0, rad, rad);
	topright.zPosition = -3;
	if(roundTop){
		topright.hidden = YES;
	}
	else {
		topright.hidden = NO;
	}
    [self.layer addSublayer:topright];

	// corner layer bottom left
	bottomleft = [CALayer layer];
    bottomleft.backgroundColor = normalColor.CGColor;
	bottomleft.frame = CGRectMake(rad, fr.size.height-rad, rad, rad);
	bottomleft.zPosition = -2;
	if(roundBottom){
		bottomleft.hidden = YES;
	}else {
		bottomleft.hidden = NO;
	}
    [self.layer addSublayer:bottomleft];

	// corner layer bottom right
	bottomright = [CALayer layer];
	bottomright.backgroundColor = normalColor.CGColor;
	bottomright.frame = CGRectMake(fr.size.width, fr.size.height-rad, rad, rad);
	bottomright.zPosition = -1;
	if(roundBottom){
		bottomright.hidden = YES;
	}else {
		bottomright.hidden = NO;
	}
    [self.layer addSublayer:bottomright];

	[super drawRect:rect];

}

Now we implement both methods to show round corners on top or bottom of the cell by hiding the appropriate CALayers:

-(void) drawRoundTop{
roundTop = YES;
topleft.hidden = YES;
topright.hidden = YES;
}

For the cell bottom:

-(void) drawRoundBottom{
roundBottom = YES;
bottomleft.hidden = YES;
bottomright.hidden = YES;
}

Ok, our custom UITableViewCell class is ready for use. Therefore we open our UITableViewController file (.m). In the viewDidLoad method we have to implement at least the first line of the following code (if not, the standard table background view will hide our new cells).

// important! without this line it does not work!
[self.tableView setBackgroundView:[[[UIView alloc] init] autorelease]];
// set plain background color
 [self.tableView setBackgroundColor:[UIColor colorWithRed:0.69 green:0.81 blue:0.79 alpha:1.0]];
// remove seperator color
 self.tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
 [self.tableView setSeparatorColor:[UIColor clearColor]];

In my case I have defined two sections, one with normal cells and one with rounded cells, like a separate block. The cell type is defined in the cellForRowAtIndexPath method like this:

if (indexPath.section == SECTION_NORMAL) {

 static NSString *CellIdentifier = @"Cell";

 NormalTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
 if (cell == nil) {
 cell = [[[NormalTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
 }
 cell.label.text = @"normal cell";
 return cell;

 } else if (indexPath.section == SECTION_ROUNDED) {
// define round cell
 static NSString *CellRoundedIdentifier = @"RoundedTableViewCell";
 RoundedTableViewCell *cell = (RoundedTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellRoundedIdentifier];
 if (cell == nil) {
 cell = [[[RoundedTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellRoundedIdentifier] autorelease];
 }

 // Configure the cell.
 [cell.label setText:[NSString stringWithFormat:@"my round cell No.%d",(indexPath.row+1)]];
 cell.selectionStyle = UITableViewCellSelectionStyleNone;
 // draw round top corners in first row
 if(indexPath.row == 0){
 [cell drawRoundTop];
 }
// draw round corners in last row
if (indexPath.row == [self.tableView  numberOfRowsInSection:indexPath.section]-1) {
 [cell drawRoundBottom];
 }

 return cell;
 }

In order to set a margin between both sections, use the heightForHeaderInSection and the viewForHeaderInSection methods:

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {

 UIView* header = nil;
 if(section == SECTION_ROUNDED){
 CGRect rect = CGRectMake(0, 0, self.tableView.frame.size.width, [self tableView:(tableView) heightForHeaderInSection:section]);
 header = [[UIView alloc] initWithFrame:rect];

 }
 return header;
}

- (CGFloat) tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
 CGFloat h = 0;
 if(section == SECTION_ROUNDED){
 h = 15;
 }
 return h;
}

You can download the zipped XCode example project from github.