Posts Tagged ‘iOS’

Exploring iOS 7 Rounded Corners

Thursday, June 20th, 2013

Apple announced iOS 7 at the WWDC 2013. Compared to the previous iOS versions it gets a whole new look for the first time. There’s a lot of discussion going on whether it’s good or bad design. I personally like it very much, and it reminds me a bit of the huge step from Mac OS 9 to Mac OS X years ago. Many things have changed in iOS 7, but one little detail attracted my attention and that’s what this article is about: rounded corners. Apple is very obsessed about every little detail; in my opinion that’s one of the secrets why they make so beautiful and successful products. Usually a rounded corner is just a quarter of a circle, one might think. But Apple changed the form factor of rounded corners in iOS 7. Here is a little comparison:

Rounded Corners in iOS 6Rounded Corners in iOS 7


Animated iOS 6 vs 7 Comparison


To me, the corners in iOS 7 look much smoother and organic. These new corners are everywhere in iOS 7. One reason for this is that as a developer you get these new corners for free. Whenever you use the existing functions of the operating system to create rounded corners, you get the improved ones in iOS 7, e. g. when calling [UIBezierPath bezierPathWithRoundedRect:cornerRadius:].

Here is an image that shows the difference between the old and the new corners:

Corner Difference between iOS 6 and iOS 7


You see that not many pixels have changed, even at this big size, but nevertheless it has some subtle but perceptible impact in how the corners look and feel.

Currently there are a few discussions on how Apple draws these new corners; even some mathematical equations are published. I took a rather pragmatic approach to analyze it: I created a small test app that lets the system create a rounded rectangle and then introspects and visualizes the elements of the returned bezier path. Then I launched this app on iOS 6 and iOS 7. Here are the results:

Rounded Corner Bezier Path on iOS 6
Rounded Corner Bezier Path on iOS 7
A red cross marks every point where a straight line is drawn to. An orange cross with two green control points in between define a bezier curve. As you can see there are four little points where the path is not perfect yet: there are four (very) short straight lines from a curve end point (orange) to a new point (red) very closely together. These unnecessary four short lines can be stripped out of the path; maybe this will be fixed in the final version of iOS 7.

What’s also interesting is the fact that the edges of the rectangle are bent much earlier than before. In the picture below the blue area is where the lines are curved in iOS 6. The red area is where the lines are curved in iOS 7. It’s more than half the corner radius earlier:

Line bending areas

Update: Together with @flarup and @marcedwards we tried to figure out the exact radius for the corners being used for the app icons in iOS 7. Additionally I filtered out the annoying short lines metioned above and exported the UIBezierPath as SVG file. As far as we can see a radius of 27 pixels at 120×120 pixel icon size produces a pretty good match. Download it here.

In case you wonder how I introspected the UIBezierPath to draw the images above – here is the UIView code:

@interface CornerTestView ()
@property (nonatomic) CGPoint previousPoint;
@end

@implementation CornerTestView

static void pathInspector(void *info, const CGPathElement *element)
{
	CornerTestView *view = (__bridge CornerTestView *)info;
	[view addElement:element];
}

- (void)drawRect:(CGRect)dirtyRect
{
	[[UIColor whiteColor] setFill];
	UIRectFill(dirtyRect);

	CGRect rect = self.bounds;
	CGFloat size = MIN(CGRectGetWidth(rect), CGRectGetHeight(rect)) - 20;
	size = round(size / 2) * 2;
	rect = CGRectMake(round(CGRectGetMidX(rect) - size / 2), round(CGRectGetMidY(rect) - size / 2), size, size);
	CGFloat radius = size / 4;
	UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:radius];
	[[UIColor colorWithRed:0.90 green:0.93 blue:1.0 alpha:1.0] setFill];
	[path fill];

	CGPathRef cgPath = path.CGPath;
	CGPathApply(cgPath, (__bridge void *)(self), pathInspector);
}

static UIBezierPath *crossAtPoint(CGPoint p)
{
	UIBezierPath *cross = [UIBezierPath bezierPath];
	cross.lineWidth = 0.5;
	[cross moveToPoint:CGPointMake(p.x - 2, p.y - 2)];
	[cross addLineToPoint:CGPointMake(p.x + 2, p.y + 2)];
	[cross moveToPoint:CGPointMake(p.x - 2, p.y + 2)];
	[cross addLineToPoint:CGPointMake(p.x + 2, p.y - 2)];
	return cross;
}

- (void)addElement:(const CGPathElement *)element
{
	switch (element->type) {
		case kCGPathElementMoveToPoint:
			[[UIColor grayColor] setStroke];
			[crossAtPoint(element->points[0]) stroke];
			self.previousPoint = element->points[0];
			break;
		case kCGPathElementAddLineToPoint:
		{
			UIBezierPath *line = [UIBezierPath bezierPath];
			line.lineWidth = 0.25;
			[[UIColor lightGrayColor] setStroke];
			[line moveToPoint:self.previousPoint];
			[line addLineToPoint:element->points[0]];
			[line stroke];

			[[UIColor redColor] setStroke];
			[crossAtPoint(element->points[0]) stroke];
			self.previousPoint = element->points[0];
		}
			break;
		case kCGPathElementAddQuadCurveToPoint:
		{
			UIBezierPath *line = [UIBezierPath bezierPath];
			line.lineWidth = 0.25;
			[[UIColor lightGrayColor] setStroke];
			[line moveToPoint:self.previousPoint];
			[line addLineToPoint:element->points[0]];
			[line addLineToPoint:element->points[1]];
			[line stroke];
			[[UIColor cyanColor] setStroke];
			[crossAtPoint(element->points[0]) stroke];
			[[UIColor magentaColor] setStroke];
			[crossAtPoint(element->points[1]) stroke];
			self.previousPoint = element->points[1];
		}
			break;
		case kCGPathElementAddCurveToPoint:
		{
			UIBezierPath *line = [UIBezierPath bezierPath];
			line.lineWidth = 0.25;
			[[UIColor lightGrayColor] setStroke];
			[line moveToPoint:self.previousPoint];
			[line addLineToPoint:element->points[0]];
			[line addLineToPoint:element->points[1]];
			[line addLineToPoint:element->points[2]];
			[line stroke];
			[[UIColor greenColor] setStroke];
			[crossAtPoint(element->points[0]) stroke];
			[crossAtPoint(element->points[1]) stroke];
			[[UIColor orangeColor] setStroke];
			[crossAtPoint(element->points[2]) stroke];
			self.previousPoint = element->points[2];
		}
			break;
		case kCGPathElementCloseSubpath:
			break;
	}
}

@end

Have fun!

Cocoa and RAII

Wednesday, May 2nd, 2012

Today I want to write a bit about memory management and how I do it in my projects. Memory management is always an issue when writing programs, programmers have to know what they are doing, and there are some strategies how to handle it. Because I am doing OS X and iOS development most of the time and at the same time have specialized myself in cross-platform model programming, this article will focus on solutions I use in my daily work in these areas. While everybody talks about Manual Reference Counting or Garbage Collection (GC) or Automatic Reference Counting (ARC) when doing Cocoa development, I rarely hear Resource Acquisition Is Initialization (RAII). So maybe this is something new for the one or the other, although the idea of RAII is not so new, as you will see.

Manual Memory Management

When managing memory manually, it’s entirely up to the programmer when and how much memory to allocate and when to free it. This style should not be used anymore. Never. There are a lot of alternatives to this approach. This was used when programming “the old way” in C or C++, when alternative techniques where not so widely known, but you usually don’t see this anymore in modern code.

Examples (don’t do this at home):

C:
 MyStruct *info = (MyStruct *)malloc(sizeof(MyStruct));
 info->something = 42;
 free(info);
C++:
 MyClass *object = new MyClass();
 object->doSomething();
 delete object;

You can easily forget to free the allocated memory block resulting in a memory leak. Things get very complicated soon when you pass around pointers to allocated blocks of memory this way. The problem is to figure out when (and how) to free the allocated memory. Because there are no memory management concepts used here, there is no general solution to this problem and the programmer makes errors for sure as the code grows.

Manual Reference Counting

When doing Cocoa development and programming in Objective-C, one of the first things you learn is how to create and manage objects. In your code you write classes and instantiate objects of classes. One of the most important concepts in Cocoa is that every class should inherit from the base class NSObject and this class contains a retain counter. Every time you create or otherwise want to “own” an object, you increase the retain counter and once you don’t need the object anymore, you decrement this counter in your code through some special methods provided by NSObject, like retain, release or autorelease. When the retain counter falls back to zero, the object is automatically deleted. You never inspect the retain counter and you never delete objects by yourself anymore. You just follow a few very simple rules, any everything will be alright. No memory leaks or dangling pointers. Reference Counting is a simple but effective concept about the ownership of objects.

Example:

MyClass *object1 = [[MyClass alloc] init];
[object1 doSomething];
MyClass *object2 = [object1 retain];
// object1 and object2 point to the same object
[object1 release];
// object2 still points to a valid object
[object2 doSomethingElse];
[object2 release];
// no more valid references to the object; it automatically gets deleted

Garbage Collection

Some programming languages provide automatic garbage collection with sophisticated algorithms, so you don’t have to care about your memory management. If you don’t reference to objects anymore, they get freed. Hopefully. At some time. This has pros and cons, but I personally never was a big fan of garbage collection. Apple introduced a garbage collection solution for OS X programming (starting with OS X 10.5), but it never got its way into iOS and it does not seem to be very encouraged anymore. Everybody is talking about ARC (automatic reference counting) nowadays.

Example:

MyClass *object = [[MyClass alloc] init];
[object doSomething];

Note that you never have to call any code to “release” or “free” your object. The garbage collector does this magic for you. This is very convenient for the programmer, but does not come without cost. The garbage collector needs processor power, your application usually consumes more memory, and you never know when exactly your objects get freed.

Automatic Reference Counting (ARC)

A relatively new technology introduced for the Objective-C language is ARC (Automatic Reference Counting). This technique is basically the same as reference counting, but the compiler inserts the necessary retain and release calls by itself. So the manual counting becomes automatic. Basically it feels a lot like writing garbage collected code, but there is no garbage collector at runtime. You still have to know a bit about memory management, e. g. you have to avoid retain cycles by wisely declaring your references “strong” or “weak”  (something you don’t have to worry about in garbage collected code), but the reference counting itself is completely controlled by the compiler. Programmers don’t have the ability anymore to increment or decrement the retain counter explicitly. ARC has some advantages over garbage collection. Objects are always deleted immediately whenever they are no longer referenced and there is no additional processing power needed. When using garbage collecting, all your used code and libraries have to be prepared to run under garbage collecting, but not so for ARC: you can mix ARC and Non-ARC code at will. To use ARC you need the relatively new LLVM compiler. Currently there is a lot of buzz around ARC in the OS X and iOS developer scene.

Resource Acquisition Is Initialization (RAII)

Another way to control object lifetime is RAII. If you’re a Cocoa developer you may not have heard about this, but this technique is fairly old now – every C++ compiler provides this feature. The basic idea is to make use of the fact that data types (classes or structs) can have a destructor in C++. Variables have a precisely defined lifetime known by the compiler and the destructor is guaranteed to be called when the variable goes out of scope – even when exceptions are thrown. This is an advantage over the other mentioned “manual” techniques where you explicitly have to retain and release ownership on an object. If there is an exception thrown between these two steps, you usually have a memory leak. Not so when following the RAII idiom. You can see a simple example here:

class RAIIData {
public:
    RAIIData(size_t count)
        : _data(malloc(count))
        , _size(count)
    {}

    ~RAIIData() {
        free(_data);
    }

    void *data() {
        return _data;
    }

    size_t size() {
        return _size;
    }

private:
    void *_data;
    size_t _size;
};

Now you can use objects of this RAIIData type very easily:

RAIIData block(100);

This will allocate a block of memory of 100 bytes. This block is automatically freed when the code exits the scope of the block variable. This is also true for exceptions. RAII is one of the basic concepts used for implementing smart pointers (shared_ptr) provided by either the boost library or the new C++11 language standard. The basic idea of RAII is to combine two relating steps into one inseparable step: opening and closing a file, allocating and freeing memory, … or: retaining and releasing a reference counter!

Unfortunately there is no built-in support for the RAII idiom when using Cocoa. Objective-C objects are always created on the heap and referenced through a raw pointer; they can not be statically allocated and there is no concept of a smart pointer.

Still, I am using RAII a lot in my OS X and iOS code.

To describe that, I have to start a little earlier:

As said above, I specialized in writing cross-platform code. Although I love to code in Objective-C and write native UI code for OS X or iOS, I always searched for the best techniques to do cross-platform programming for the internal model of my apps. In my opinion, (Not Your Father’s) C++ is the way to go here. I used Java for some time, but although it’s a great language and it has its use cases or sure, it has not established well for end user software on desktop systems. Finally, on iOS Java is not available at all.

First of all, when holding references to objects of C++ classes, I always use smart pointers (boost::shared_ptr or std::shared_ptr). Everybody who used smart pointers knows what I am talking about. You never have to delete your objects yourself, they get automatically deleted whenever the lifetime of last referencing smart pointer ends. Using raw pointers to C++ objects is very discouraged.

While I think C++ (correctly used) is a very great language, in my opinion it lacks of good libraries. There is a lot of C++ code in the wild, but I never saw a good library (apart from boost) with great concepts that can be used as base for your apps. The language itself just provides some wicked containers and algorithms and things like that (that are great for specific needs), but that’s it. I think this is the biggest advantage of Cocoa: it provides an insanely great set of classes that are so simple but powerful. It makes fun to write code in Cocoa. It’s just like building worlds by using LEGO bricks. Expressed with some exaggeration, with plain C++ it’s like having a machine that can be used to build a machine that could eventually build LEGO bricks so you can finally start to build your world. But you’re far away from a usable set of reusable bricks. The very first thing I noticed in C++ is the lack of a good string class. I mean a real string class usable for human readable text. There is a string class in C++, but that’s a very dumb class. It’s for the “literal” meaning of “string”: a linear concatenation of objects (e.g. characters). But that’s it. The std::string class does not know what “text” is. There are no compare methods, there is no Unicode support, there’s nothing. It’s just a simple sequence of characters. Additionally, when using the std::wstring class you have the problem that wchar_t may have different size on different platforms and so on. So every time you start to code in C++ the very first thing you need is a usable string class, especially if you tend to write end user applications with UI. A user interface of an application uses text to communicate with the user in almost every case. I’ve not seen many end user applications that don’t use text of any sort. So, dealing with text is essential for a programmer! Unfortunately C++ does not help here much out of the box. As a resulting side effect, if you start to use third party C++ libraries, you’ll see very soon that many of these libraries provide their own string implementation. That’s not good. But that’s the way it currently is. In contrast, think about a Cocoa library from a third party: It’s totally natural (and convenient) to use NSString for text here – nobody would ever came to the idea to write his own string class to use in a Cocoa library.

So I love C++ as a language, but I also love the classes and concepts of Cocoa, and I want to write cross-platform code for the model. What’s the solution? I thought about solutions to use Objective-C and Cocoa libraries on other platforms, e.g. with GNUstep. But I finally decided against this in my projects. One problem is that you depend on having a compiler that can compile Objective-C code. Additonally GNUstep is fairly large and tries to port everything including the UI classes, but I am not interested in the UI classes of Cocoa. In my opinion on every platform you should use the native way to code the UI. I am interested in cross-platform model classes like strings and containers. My solution is using Core Foundation! Core Foundation is the “heart” of Cocoa and it is open sourced by Apple. It is written in C and many Cocoa classes are just Objective-C wrappers around Core Foundation. There is a great port named OpenCFLite that makes Core Foundation run on Windows. So, Core Foundation is great and (being part of Cocoa) well tested. But I don’t want to actually use it through an inconvenient C-API in my application code. So I wrote thin wrapper classes in C++ around Core Foundation and called it “maniCore”. And – to finally come back to the point – one of the basic idioms I used here is RAII. Here is some sample code how maniCore can be used:

namespace mani {
    String nullString;
    String emptyString("");
    String helloString("Hello");
    String sampleString = helloString.stringByAppending(" world!");
    CFRange worldRange1 = sampleString.rangeOf("world");
    // worldRange1.location is 6, worldRange1.length is 5
    // case insensitive search works, too:
    CFRange worldRange2 = sampleString.rangeOf("WoRlD", kCFCompareCaseInsensitive);
    // It also fully supports Unicode "for free"; provided by Core Foundation
    String everything("everything");
    String possible("possible");
    String(withFormat(), "%@ is %@, isn't that %s?", *everything, possible._NSString(), "great");
    MutableString mutableString;
    mutableString.append(everything);
    // easier appending through overwritten operator<<:
    mutableString << " is " << possible << "!";
}

You see mani::String objects can be created and used in various ways (only a very small set of possibilities is shown here) and you never have to care about retaining or releasing your objects, the same way as with smart pointers. It’s all done automatically using the RAII principle. Objects are freed automatically as soon as they are not used anymore. And you don’t need a garbage collector, and you don’t need a new compiler that does statical analysis and inserts code for you. It’s a simple old but robust technique provided by every C++ compiler based on the lifetime of variables.

Because maniCore objects wrap Core Foundation objects, they are retain counted internally. The classes just contain the CFTypeRef reference, and whenever you assign an object to another variable, the reference is copied and CFRetain() is called. Whenever the object is destructed, CFRelease() is called. So the internal Core Foundation object is deleted whenever the last referencing maniCore object is deleted. If you think about it, it has a minor disadvantage over Cocoa: In Cocoa you can pass plain pointers around – that’s very fast – and only if you need ownership of an object longer than for the current context, you send it a retain message. In maniCore you pass objects by value (not by pointer), and every time you pass such an object to another variable, CFRetain/CFRelease calls are made. This may be slower in some cases, but that’s more a theoretical problem. I’ve already used it a lot and never saw any performance problems. And if it ever gets a problem, you can simply move over to plain Core Foundation calls (or other solutions) for time critical tasks. Finally when adopting the new “move semantics” of the C++11 standard, this problem might occur even less often. Additionally when passing objects as parameters, you can pass them by const reference in many cases:

void myFunctionThatTakesAString(const mani::String& string);
To summarize: maniCore turns the Manual Reference Counting of Core Foundation into Automatic Reference Counting with the help of RAII (a feature provided by the C++ compiler):

Manual Reference Counting + RAII = Automatic Reference Counting

Of course I can convert easily between mani::String and NSString; this is needed to communicate between UI code and model code. And because I have the source of maniCore I can extend it at any time and adapt for my needs. Currently maniCore is private, but maybe I will release it to the public at some time in the future. I find it very handy, especially for cross-platform projects.

Core Foundation containers (CFArray, CFDictionary, etc.) were also wrapped into C++ classes. Because of the stricter type system of C++ compared to Objective-C I had to think of some tricks sometimes. There are cases where I find it even safer and a bit “funnier” to read, e.g. here is an example how to get a CFString out of an CFArray using maniCore wrappers:

namespace mani {
    Array array;
    // assume array is filled with Strings somehow,
    // now get the String at index 7:
    String string = array.get<String>(7);
}

When getting objects out of a Core Foundation or Cocoa Container, you always have to know what type they are. The container itself doesn’t do any type checking here. In Cocoa the getter usually just returns objects of type id and this is implicitly casted to the type of your variable by the compiler. When directly using the C-API of Core Foundation you usually have to cast the type yourself. I want to avoid casting in the higher level code that uses maniCore and because of the stricter type system of C++ I had to specify the type in the getter of my C++ wrapper. I did that with some template magic and I ended up with the nice verbose get<Type> solution, that even can do type checking, if desired (e.g. in the Debug build).

In maniCore I wrote another crazy class: a container for Cocoa pointers (NSObject and all subclasses) that provides the RAII idiom for them, too. You can use it as follows:

namespace mani {
    Cocoa<NSString> string = @"Test";
    NSUInteger stringLength = [*string length];
}

The overwritten operator* returns the internal Cocoa pointer for easy usage.

As soon as the string variable goes out of scope, the internal NSString object is sent a release message. It’s like a smart pointer, but for Objective-C objects instead of C++ objects and directly using the internal retain counter of these Cocoa objects instead of implementing an own solution. This is very convenient when being used as instance variables. You do not have to release these instance variables in your dealloc method anymore. They are automatically destructed. You just have to make sure to have turned on GCC_OBJC_CALL_CXX_CDTORS (Call C++ Default Ctors/Dtors in Objective-C) in your compiler settings:

@interface MyClass {
@private
    mani::Cocoa<NSString> _internalString;
}
@end

It can also be used for variables with getters and setters, especially for IBOutlets. Although in this case you’re not able to @synthesize the getter and setter, but it’s very easy to write it yourself, because the entire retain/release procedure of the setter is hidden (and written only once) in the mani::Cocoa implementation:

@interface MyClass {
@private
    mani::Cocoa<NSButton> _button;
}
@property (nonatomic, retain) IBOutlet NSButton *button;
@end
@implementation MyClass
- (NSButton *)button
{
    return *_button;
}
- (void)setButton:(NSButton *)button
{
    _button = button;
}

@end

Note that you don’t have to think about overwriting dealloc and free the instance variable. It’s done automatically.

Another nice example it how you can use a local NSAutoreleasePool by using the RAII-Wrapper:

{
    mani::Cocoa<NSAutoreleasePool> pool(mani::alreadyRetained(), [[NSAutoreleasePool alloc] init]);
    // do your work ...
    // if pool gets out of scope, it's automatically released
}

You can even wrap this verbose bit of code into another self-made special “AutoAutoreleasePool” class that hides the call above and you can even make it cross-platform by simply doing nothing in the Windows specific implementation, so you end up with that in your code:

{
    AutoAutoreleasePool pool;
    // do your work ...
    // if pool gets out of scope, it's automatically released
}

You see there are a lot of things possible when mixing C++ and Objective-C. Although C++ is a very old language, I am still a huge fan of it and wanted to demonstrate that a modern usage of C++ is not the way as most people have seen in their life. There is a lot of cryptic and ugly C++ code out there. Don’t use it this way. C++ has a lot of possibilites, that makes it difficult and requires a lot of knowledge and discipline to use it “the right way”, but I don’t like it when people argue “Objective-C is better” or “C++ is a hell of a language” etc. When used in a modern and smart way it has cool features. I demonstrated how I use it to write cross-platform code in a style that’s pretty comparable to Cocoa using ARC.

I love to write Objective-C code but I also love to write good C++ code and became kind of an expert in combining both together.