MOBILE

iphone : Making Connections with GameKit and Bonjour - Peeking Behind the Scenes, Sending Complex Data Through GameKit

1/28/2013 6:41:58 PM

1. Recipe: Peeking Behind the Scenes

At the time of writing, GameKit logs its status information as it runs, mostly by NSLog calls introduced by Apple’s engineers. You can track this information at the debug console, or you can use the following trick to redirect it to a file (the messages will not output to the console) and then display it in-application with a text view. Recipe 1 uses a standard C freopen() call to redirect stderr data, which is what NSLog() produces, to a file. It then sets up an NSTimer instance to monitor that file, and when the file contents change, it updates the text view with that output. You can use this redirection approach with GameKit or with any other application that produces console output of some kind.

Take note of the way this recipe updates the content offset for the text view. It ensures that the text at the bottom of the view is always displayed after an update. It does this by setting the offset to one page height shorter than the full content size.

Recipe 1. Monitoring GameKit
@implementation TestBedViewController
@synthesize textView;
- (void) listenForStderr: (NSTimer *) timer;
{
    // Monitor the stderr output for new information
    NSString *contents = [NSString
        stringWithContentsOfFile:STDERR_OUT];
    contents = [contents stringByReplacingOccurrencesOfString:@"\n"
        withString:@"\n\n"];
    if ([contents isEqualToString:self.textView.text]) return;
    [self.textView setText:contents];
    self.textView.contentOffset = CGPointMake(0.0f,
        MAX(self.textView.contentSize.height -
        self.textView.frame.size.height, 0.0f));
}

- (void) viewDidLoad
{
    // Establish the GameKit session
    [GameKitHelper sharedInstance].sessionID = @"Peeking at GameKit";
    [GameKitHelper assignViewController:self];

    // Redirect stderr output to file
    freopen([STDERR_OUT fileSystemRepresentation], "w", stderr);
    [NSTimer scheduledTimerWithTimeInterval:1.0f target:self
        selector:@selector(listenForStderr) userInfo:nil repeats:YES];
}
@end

					  


2. Recipe: Sending Complex Data Through GameKit

Soon, you’ll need to move forward to more complex objects and data. Property lists offer a good way to transmit custom objects. That’s because property lists are easily serialized to and from NSData objects.

Property lists provide a helpful abstract data type. A property list object can point to data (NSData), strings (NSString), arrays (NSArray), dictionaries (NSDictionary), dates (NSDate), and numbers (NSNumber). When working with collection objects (i.e., arrays and dictionaries) all members and keys must be property list objects as well, that is, data, strings, numbers, and dates as well as embedded arrays and dictionaries.

While that seems limiting, you can transform most structures and objects to and from strings. For example, you can use the built-in NSStringFromCGPoint() or NSStringFromClass() functions, or you can create your own. The following pair of methods extend the UIColor class, providing functionality needed to send color information across a GameKit connection as strings.

@implementation UIColor (utilities)
- (NSString *) stringFromColor
{
    // Recover the color space and store RGB or monochrome color
    const CGFloat *c = CGColorGetComponents(self.CGColor);
    CGColorSpaceModel csm =
        CGColorSpaceGetModel(CGColorGetColorSpace(self.CGColor));
    return (csm == kCGColorSpaceModelRGB) ?
        [NSString stringWithFormat:@"%0.2f %0.2f %0.2f %0.2f",
            c[0], c[1], c[2], c[3]] :
        [NSString stringWithFormat:@"%0.2f %0.2f %0.2f %0.2f",
            c[0], c[0], c[0], c[1]];
}

+ (UIColor *) colorWithString: (NSString *) colorString
{
    // Read a color back from a string
    const CGFloat c[4];
    sscanf([colorString cStringUsingEncoding:NSUTF8StringEncoding],
        "%f %f %f %f", &c[0], &c[1], &c[2], &c[3]);
    return [UIColor colorWithRed:c[0] green:c[1] blue:c[2] alpha:c[3]];
}
@end

					  

Once in property list form, you can serialize your data and send it as a single chunk. On receipt, the deserialized data is ready to use. Recipe 2 shows the transmit and receivedData: methods that handle this. This code comes from a sample that stores a series of drawing points  along with the color used to draw them in an NSDictionary object. You can use the NSKeyedArchiver and NSKeyedUnarchiver classes as well as the NSPropertyListSerialization class shown here.

By storing both the points and colors as strings, this data can easily be converted into a form better suited for transmission via GameKit.

Recipe 2. Serializing and Deserializing Property Lists
- (void) transmit
{
    if (![GameKitHelper sharedInstance].isConnected) return;
    NSString *errorString;

    // Send a copy of the local points to the peer
    // by serializing the property list into data
    NSData *plistdata = [NSPropertyListSerialization
         dataFromPropertyList:self.points
         format:NSPropertyListXMLFormat_v1_0
         errorDescription:&errorString];
    if (plistdata)
         [GameKitHelper sendData:plistdata];
    else
         CFShow(errorString);
}
- (void) receivedData: (NSData *) thedata
{
    // Deserialize the data back into a property list
    CFStringRef errorString;
    CFPropertyListRef plist =
        CFPropertyListCreateFromXMLData(kCFAllocatorDefault,
        (CFDataRef)thedata, kCFPropertyListMutableContainers,
        &errorString);

    if (!plist)
    {
        CFShow(errorString);
        return;
    }

    // Assign the received data to foreignPoints
    self.foreignPoints = (NSArray *)plist;
}

					  

Other  
 
Most View
HTC First – Smartphone With Facebook Home (Part 4)
Bin Your ISP Router (Part 3) : Belkin Play N600, BT Home Hub 3
Make Raspberry PI Projects
Lenovo Ideatab S2110 - A Transformer’s Strong Competitor Running Android 4.0 (Part 1)
iphone SDK 3 : Working with Databases - Processing Row Results
The Best Mobile Apps (Part 1) - BBM
A Trio From HIS: 7970 IceQ X² GHz Edition, 7950 IceQ X² Boost Clock And 7850 IceQ Turbo X Graphics Cards Review (Part 2)
Chord Electronics SPM 1200 MkIISolid-State Power Amplifier(Part 2)
100 More Things Every Mac User Should Know (Part 3)
Sony NEX-6 Mirrorless Camera Review (Part 15)
Top 10
Sharepoint 2013 : Developing Applications Using Office Services - What’s New in Access Services
Sharepoint 2013 : Developing Applications Using Office Services - The New Machine Translation Services
Sharepoint 2013 : Developing Applications Using Office Services - Word Automation Services and the New PowerPoint Automation Services
Sharepoint 2013 : Developing Applications Using Office Services - What’s New in Excel Services
Sharepoint 2013 : Developing Applications Using Office Services - WOPI and the New Office Web Apps Server
Sharepoint 2013 : Building a BCS-enabled Business Solution : Building an Integrated BCS Solution with an App for SharePoint Containing an App for Office
Business Connectivity Services in Apps for SharePoint 2013 : Building an App-level BCS Solution for Office 365 SharePoint Online
Business Connectivity Services in SharePoint 2013 : Adding a Business Data Connectivity Model to Office 365 SharePoint Online
Remote Event Receivers in Sharepoint 2013 : Introducing Remote Event Receivers
Windows Server 2008 and Windows Vista : Common GPO Troubleshooting Tools (part 3) - GPResult, GPOTool