Wrox Programmer Forums
|
BOOK: Professional iPhone and iPad Application Development
This is the forum to discuss the Wrox book Professional iPhone and iPad Application Development by Gene Backlin; ISBN: 978-0-470-87819-4
Welcome to the p2p.wrox.com Forums.

You are currently viewing the BOOK: Professional iPhone and iPad Application Development section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old March 22nd, 2011, 01:02 PM
Friend of Wrox
 
Join Date: Aug 2010
Posts: 298
Thanks: 1
Thanked 62 Times in 60 Posts
Default Chapter 7

Some comments on NetworkServer-Mac

On p. 236 the

Code:
if ([self netService] != nil) {
            NSLog(@"Service was not started");
        }
seems backwards to me. Shouldn't it be

Code:
if ([self netService] == nil) {
            NSLog(@"Service was not started");
        }
?
Once the [self startService]; method is called successfully, the netService is not nil.

In general there is an issue with the -postMessage method. Most of the messages never make it to the window.The window does not appear on screen until after the
-netServiceDidPublish method has returned, so the messages in -startService and -netServiceWillPublish have no where to go. It seems to make more sense to post them to the console. In order to make use of these messages, I added a toggleService method

Code:
- (IBAction)toggleService:(id)sender {
    if (self.netService != nil) {
        [self stopService];
        [sender setTitle:@"Start Service"];
    }
    else
    {
        [self startService];
        [sender setTitle:@"Stop Service"];
    }
}
to the class with a push button in the Interface. With this invoked, the startService, netServiceDidPublish, and stopService methods do show. For some reason, the messages from the -netServiceWillPublish and -netServiceDidStop methods do not make it to the window even with this added method. They can be logged to the console and the messageLabel stringValue as well, but they never appear in the window. Thinking it may be occurring too quickly to see, I added breakpoints to try to catch the messages being displayed, but though they are logged they do not appear on the interface.

On p 239 in the -viewWillAppear method, the *browser variable is instantiated to search for browsable domains yet never is released anywhere. Should it be? I redid this with an instance variable. Is there a particular reason to not use the *localBrowser for both the domain search and the service search?

With the ability to start and stop services it is necessary to add

Code:
-(void)netServiceBrowser:(NSNetServiceBrowser *)aNetServiceBrowser didRemoveService:(NSNetService *)aNetService moreComing:(BOOL)moreComing
{
    [self.services removeObject:aNetService];
    [self.tableView reloadData];
}
so that the view is updated.

The two BOOL variables domainsFound and servicesFound are never used.

Bob
 
Old March 25th, 2011, 11:22 PM
Wrox Author
 
Join Date: Oct 2010
Posts: 61
Thanks: 0
Thanked 9 Times in 7 Posts
Default

As always Bob, thank you for your time and effort with my book.

I will get back on your questions, I am currently swamped !

Take care,
Gene
 
Old March 26th, 2011, 08:40 AM
Wrox Author
 
Join Date: Oct 2010
Posts: 61
Thanks: 0
Thanked 9 Times in 7 Posts
Default

Ok, here is updated code to address your browser question. It should be stored in an instance variable, because if your release it as the way it is currently written, no values will be displayed in the table view. This memory leak will not come up in Build and Analyze in Xcode 3.x nor in 4.x, but you are correct that any alloc and init should be released, so below is an updated listing.

Code:
//
//  RootViewController.h
//  NetServiceBrowser-iPhone
//
//  Created by Gene Backlin on 6/14/10.
//  Copyright MariZack Consulting 2010. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface RootViewController : UITableViewController <NSNetServiceBrowserDelegate, NSNetServiceDelegate> {
	NSNetServiceBrowser *netDomainBrowser;
	NSNetServiceBrowser *netServiceBrowser;
	NSMutableArray *domains;
	NSMutableArray *services;
}

@property (nonatomic, retain) NSNetServiceBrowser *netDomainBrowser;
@property (nonatomic, retain) NSNetServiceBrowser *netServiceBrowser;
@property (nonatomic, retain) NSMutableArray *domains;
@property (nonatomic, retain) NSMutableArray *services;

@end
Code:
//
//  RootViewController.m
//  NetServiceBrowser-iPhone
//
//  Created by Gene Backlin on 6/14/10.
//  Copyright MariZack Consulting 2010. All rights reserved.
//

#import "RootViewController.h"


@implementation RootViewController

@synthesize netDomainBrowser;
@synthesize netServiceBrowser;
@synthesize domains;
@synthesize services;


#pragma mark -
#pragma mark View lifecycle

- (void)viewDidLoad {
	[super viewDidLoad];
	[self setTitle:@"Networks"];
}

- (void)viewWillAppear:(BOOL)animated {
	NSNetServiceBrowser* browser = [[NSNetServiceBrowser alloc] init]; 
	[browser setDelegate:self];
	[self setNetDomainBrowser:browser];
	
	[[self netDomainBrowser] searchForBrowsableDomains];
	
	NSNetServiceBrowser *localBrowser = [[NSNetServiceBrowser alloc] init];
	[localBrowser setDelegate:self];
	[self setNetServiceBrowser:localBrowser];
	
	[[self netServiceBrowser] searchForServicesOfType:@"_hab._tcp." 
											 inDomain:@"local"];
	
	[browser release];
	[localBrowser release];
	
    [super viewWillAppear:animated];
}

- (void)viewWillDisappear:(BOOL)animated {
	[[self netServiceBrowser] stop];
	[[self netServiceBrowser] setDelegate:nil];
	[self setNetServiceBrowser:nil];
	
	[[self netDomainBrowser] stop];
	[[self netDomainBrowser] setDelegate:nil];
	[self setNetDomainBrowser:nil];
	
	[super viewWillDisappear:animated];
}

#pragma mark -
#pragma mark NSNetServiceBrowserDelegate

- (void)netServiceBrowser:(NSNetServiceBrowser *)aNetServiceBrowser 
		   didFindService:(NSNetService *)netService 
			   moreComing:(BOOL)moreServicesComing {
	NSLog(@"didFindService %@", netService);
	if ([self services] == nil)
		[self setServices:[[NSMutableArray alloc] init]];
	
	[[self services] addObject:netService];
	
	[self.tableView reloadData];
}

- (void)netServiceBrowser:(NSNetServiceBrowser *)aNetServiceBrowser 
		 didRemoveService:(NSNetService *)netService 
			   moreComing:(BOOL)moreServicesComing {
	[[self services] removeObject:netService];
	[[self tableView] reloadData];
}

- (void)netServiceBrowserDidStopSearch:(NSNetServiceBrowser *)aNetServiceBrowser {
	[[self services] removeAllObjects];
}

- (void)netServiceBrowser:(NSNetServiceBrowser*)aNetServiceBrowser 
			didFindDomain:(NSString*)domain 
			   moreComing:(BOOL)moreComing {
	NSLog(@"didFindDomain - Domain = %@ more = %d", domain, moreComing);
	if ([self domains] == nil)
		[self setDomains:[[NSMutableArray alloc] init]];
	
	[[self domains] addObject:domain];
	
	if(moreComing == 0) {
		[[self tableView] reloadData];
	}
}

- (void)netServiceBrowser:(NSNetServiceBrowser*)aNetServiceBrowser 
		  didRemoveDomain:(NSString*)domain 
			   moreComing:(BOOL)moreComing {
	NSLog(@"didRemoveDomain - Domain = %@ more = %d", domain, moreComing);
	if([self domains] != nil) {
		[[self domains] removeObject:domain];
		
		if(moreComing == 0) {
			[[self tableView] reloadData];
		}
	}
}

#pragma mark -
#pragma mark NSNetServiceDelegate

- (void)netService:(NSNetService *)sender 
	 didNotResolve:(NSDictionary *)errorDict {
	NSLog(@"didNotResolve - errorDict = %@", errorDict);
}

- (void)netServiceDidResolveAddress:(NSNetService *)service {
	NSLog(@"netServiceDidResolveAddress - name = %@", [service name]);
	NSString *msg = [NSString stringWithFormat:@"%@", [service name]];
	[self setTitle:msg];
}


#pragma mark -
#pragma mark Table view data source

// Customize the number of sections in the table view.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 2;
}

// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
	switch (section) {
		case 0:
			return [domains count];
			break;
		case 1:
			return [services count];
			break;
		default:
			return 0;
			break;
	}
}

// Customize the Header Titles of the table view.
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
	switch (section) {
		case 0:
			return @"Domains";
			break;
		case 1:
			return @"Services";
			break;
		default:
			return @"Unknown";
			break;
	}
}

// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    static NSString *CellIdentifier = @"Cell";
	NSString *cellText = @"Unknown";
	NSNetService *service = nil;
    
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
		[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
    }
    
	switch ([indexPath section]) {
		case 0:
			cellText = [[self domains] objectAtIndex:indexPath.row];
			break;
		case 1:
			service = [[self services] objectAtIndex:indexPath.row];
			cellText = [service name];
			break;
		default:
			break;
	}
	// Configure the cell.
	[[cell textLabel]setText: cellText];
	
    return cell;
}

#pragma mark -
#pragma mark Table view delegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
	NSNetService *service = nil;
	
	switch ([indexPath section]) {
		case 1:
			service = [[self services] objectAtIndex:indexPath.row];
			[service setDelegate:self];
			[service resolveWithTimeout:5];
			break;
		default:
			break;
	}
}

#pragma mark -
#pragma mark Memory management

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}

- (void)viewDidUnload {
    // Relinquish ownership of anything that can be recreated in viewDidLoad or on demand.
    // For example: self.myOutlet = nil;
	[self setNetDomainBrowser:nil];
	[self setNetServiceBrowser:nil];
	[self setDomains:nil];
	[self setServices:nil];
}


- (void)dealloc {
	[netDomainBrowser release];
	[netServiceBrowser release];
	[domains release];
	[services release];
    [super dealloc];
}

@end
 
Old March 26th, 2011, 11:41 AM
Friend of Wrox
 
Join Date: Aug 2010
Posts: 298
Thanks: 1
Thanked 62 Times in 60 Posts
Default

That is how I redid the program, including completing the didRemoveDomain method.
Bob





Similar Threads
Thread Thread Starter Forum Replies Last Post
Chapter 6 - Code Download Missing for this Chapter dbaechtel BOOK: Professional SharePoint 2007 Development ISBN: 978-0-470-11756-9 0 August 11th, 2009 11:02 AM
Chapter 2 - End of chapter exercises whizzkid1892 BOOK: Beginning PHP5, Apache, and MySQL Web Development ISBN: 978-0-7645-7966-0 1 July 30th, 2008 12:02 PM
Generics chapter 12 difficult chapter i found ...? Larryz C# 2005 1 July 4th, 2007 09:40 PM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.