1. 程式人生 > >How to Use NSLog to Debug CGRect and CGPoint

How to Use NSLog to Debug CGRect and CGPoint

CGPoint and CGRect are structures (versus objects) and therefore the old NSLog standby %@ will not work as expected.

Here is how each structure is defined:

struct CGPoint {
   CGFloat x;
   CGFloat y;
};
typedef struct CGPoint CGPoint;
 
struct CGRect {
   CGPoint origin;
   CGSize size;
};
typedef
struct CGRect CGRect;

If you attempt NSLog to use the traditional ‘print object’ notation such as this:

// Print point structure using NSLog
CGPoint cgPoint = CGPointMake(1, 11);
NSLog(@"%@", cgPoint);

the compiler will generate a warning: Format specifies type ‘id’ but the argument has type ‘CGPoint’ (aka ‘struct CGPoint’) 

Good news is, this is easy to fix:

NSLog(@"Point: %@", NSStringFromCGPoint(cgPoint));

The output of converting a CGPoint to an NSString looks as follows:

Point: {1, 11}

Output CGRect using NSLog

Likewise, CGRect is a structure and will also give NSLog troubles. The solution is similar:

// Print rect structure using NSLog
CGRect rect = CGRectMake(5, 5, 10, 10); NSLog(@"Rect: %@", NSStringFromCGRect(rect));
Rect: {{5, 5}, {10, 10}}

CGRect, CFDictionaryRef and NSLog

When working with CGRect structures, there is another solution, you can convert the rect to a CFDictionaryRef and print as shown below:

NSLog(@"CFDictionaryRef: %@", CGRectCreateDictionaryRepresentation(rect));
CFDictionaryRef: {
    Height = 10;
    Width = 10;
    X = 5;
    Y = 5;
}

If for some reason you need to keep the dictionary object around, here is how you can so if you are using ARC:

1
2
3
4
5
# Create reference to immutable CFDictionary
CFDictionaryRef currentListingRef = CGRectCreateDictionaryRepresentation(rect);
 
# Create Dictionary object managed by ARC
NSDictionary *dict = CFBridgingRelease(currentListingRef);

The code on line 5 moves the CGRef to and Objective-C object, and also hands the memory management over to ARC.