⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 browserviewcontroller.m

📁 This is an example application that shows how to connect connect two iPhone devices using Bonjour wi
💻 M
字号:
/*File: BrowserViewController.mAbstract:  View controller for the service instance list. This object manages a NSNetServiceBrowser configured to look for Bonjourservices. It has an array of NSNetService objects that are displayed in a table view. When the service browser reports that it has discovered a service, thecorresponding NSNetService is added to the array. When a service goes away, the corresponding NSNetService is removed from thearray. Selecting an item in the table view asynchronously resolves the correspondingnet service. When that resolution completes, the delegate is called with the correspondingNSNetService. Version: 2.5Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple Inc.("Apple") in consideration of your agreement to the following terms, and youruse, installation, modification or redistribution of this Apple softwareconstitutes acceptance of these terms.  If you do not agree with these terms,please do not use, install, modify or redistribute this Apple software.In consideration of your agreement to abide by the following terms, and subjectto these terms, Apple grants you a personal, non-exclusive license, underApple's copyrights in this original Apple software (the "Apple Software"), touse, reproduce, modify and redistribute the Apple Software, with or withoutmodifications, in source and/or binary forms; provided that if you redistributethe Apple Software in its entirety and without modifications, you must retainthis notice and the following text and disclaimers in all such redistributionsof the Apple Software.Neither the name, trademarks, service marks or logos of Apple Inc. may be usedto endorse or promote products derived from the Apple Software without specificprior written permission from Apple.  Except as expressly stated in this notice,no other rights or licenses, express or implied, are granted by Apple herein,including but not limited to any patent rights that may be infringed by yourderivative works or by other works in which the Apple Software may beincorporated.The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NOWARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIEDWARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULARPURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR INCOMBINATION WITH YOUR PRODUCTS.IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL ORCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTEGOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/ORDISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OFCONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IFAPPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.Copyright (C) 2008 Apple Inc. All Rights Reserved.*/#import "BrowserViewController.h"#define kProgressIndicatorSize 20.0// A category on NSNetService that's used to sort NSNetService objects by their name.@interface NSNetService (BrowserViewControllerAdditions)- (NSComparisonResult) localizedCaseInsensitiveCompareByName:(NSNetService*)aService;@end@implementation NSNetService (BrowserViewControllerAdditions)- (NSComparisonResult) localizedCaseInsensitiveCompareByName:(NSNetService*)aService {	return [[self name] localizedCaseInsensitiveCompare:[aService name]];}@end@interface BrowserViewController()@property (nonatomic, assign, readwrite) BOOL showDisclosureIndicators;@property (nonatomic, retain, readwrite) NSMutableArray* services;@property (nonatomic, retain, readwrite) NSNetServiceBrowser* netServiceBrowser;@property (nonatomic, retain, readwrite) NSNetService* currentResolve;@property (nonatomic, retain, readwrite) NSTimer* timer;@property (nonatomic, assign, readwrite) BOOL needsActivityIndicator;@property (nonatomic, assign, readwrite) BOOL initialWaitOver;- (void)stopCurrentResolve;- (void)initialWaitOver:(NSTimer*)timer;@end@implementation BrowserViewController@synthesize delegate = _delegate;@synthesize showDisclosureIndicators = _showDisclosureIndicators;@synthesize currentResolve = _currentResolve;@synthesize netServiceBrowser = _netServiceBrowser;@synthesize services = _services;@synthesize needsActivityIndicator = _needsActivityIndicator;@dynamic timer;@synthesize initialWaitOver = _initialWaitOver;- (id)initWithTitle:(NSString*)title showDisclosureIndicators:(BOOL)show showCancelButton:(BOOL)showCancelButton {		if ((self = [super initWithStyle:UITableViewStylePlain])) {		self.title = title;		_services = [[NSMutableArray alloc] init];		self.showDisclosureIndicators = show;		if (showCancelButton) {			// add Cancel button as the nav bar's custom right view			UIBarButtonItem *addButton = [[UIBarButtonItem alloc]										  initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancelAction)];			self.navigationItem.rightBarButtonItem = addButton;			[addButton release];		}		// Make sure we have a chance to discover devices before showing the user that nothing was found (yet)		[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(initialWaitOver:) userInfo:nil repeats:NO];	}	return self;}- (NSString *)searchingForServicesString {	return _searchingForServicesString;}// Holds the string that's displayed in the table view during service discovery.- (void)setSearchingForServicesString:(NSString *)searchingForServicesString {	if (_searchingForServicesString != searchingForServicesString) {		[_searchingForServicesString release];		_searchingForServicesString = [searchingForServicesString copy];        // If there are no services, reload the table to ensure that searchingForServicesString appears.		if ([self.services count] == 0) {			[self.tableView reloadData];		}	}}// Creates an NSNetServiceBrowser that searches for services of a particular type in a particular domain.// If a service is currently being resolved, stop resolving it and stop the service browser from// discovering other services.- (BOOL)searchForServicesOfType:(NSString *)type inDomain:(NSString *)domain {		[self stopCurrentResolve];	[self.netServiceBrowser stop];	[self.services removeAllObjects];	NSNetServiceBrowser *aNetServiceBrowser = [[NSNetServiceBrowser alloc] init];	if(!aNetServiceBrowser) {        // The NSNetServiceBrowser couldn't be allocated and initialized.		return NO;	}	aNetServiceBrowser.delegate = self;	self.netServiceBrowser = aNetServiceBrowser;	[aNetServiceBrowser release];	[self.netServiceBrowser searchForServicesOfType:type inDomain:domain];	[self.tableView reloadData];	return YES;}- (NSTimer *)timer {	return _timer;}// When this is called, invalidate the existing timer before releasing it.- (void)setTimer:(NSTimer *)newTimer {	[_timer invalidate];	[newTimer retain];	[_timer release];	_timer = newTimer;}- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {	return 1;}- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {	// If there are no services and searchingForServicesString is set, show one row to tell the user.	NSUInteger count = [self.services count];	if (count == 0 && self.searchingForServicesString && self.initialWaitOver)		return 1;	return count;}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {		static NSString *tableCellIdentifier = @"UITableViewCell";	UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:tableCellIdentifier];	if (cell == nil) {		cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:tableCellIdentifier] autorelease];	}		NSUInteger count = [self.services count];	if (count == 0 && self.searchingForServicesString) {        // If there are no services and searchingForServicesString is set, show one row explaining that to the user.        cell.text = self.searchingForServicesString;		cell.textColor = [UIColor colorWithWhite:0.5 alpha:0.5];		cell.accessoryType = UITableViewCellAccessoryNone;		return cell;	}		// Set up the text for the cell	NSNetService* service = [self.services objectAtIndex:indexPath.row];	cell.text = [service name];	cell.textColor = [UIColor blackColor];	cell.accessoryType = self.showDisclosureIndicators ? UITableViewCellAccessoryDisclosureIndicator : UITableViewCellAccessoryNone;		// Note that the underlying array could have changed, and we want to show the activity indicator on the correct cell	if (self.needsActivityIndicator && self.currentResolve == service) {		if (!cell.accessoryView) {			CGRect frame = CGRectMake(0.0, 0.0, kProgressIndicatorSize, kProgressIndicatorSize);			UIActivityIndicatorView* spinner = [[UIActivityIndicatorView alloc] initWithFrame:frame];			[spinner startAnimating];			spinner.activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray;			[spinner sizeToFit];			spinner.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin |										UIViewAutoresizingFlexibleRightMargin |										UIViewAutoresizingFlexibleTopMargin |										UIViewAutoresizingFlexibleBottomMargin);			cell.accessoryView = spinner;			[spinner release];		}	} else if (cell.accessoryView) {		cell.accessoryView = nil;	}		return cell;}- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {	// Ignore the selection if there are no services.	if ([self.services count] == 0)		return nil;	return indexPath;}- (void)stopCurrentResolve {	self.needsActivityIndicator = NO;	self.timer = nil;	[self.currentResolve stop];	self.currentResolve = nil;}- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {	// If another resolve was running, stop it first		[self stopCurrentResolve];	self.currentResolve = [self.services objectAtIndex:indexPath.row];	[self.currentResolve setDelegate:self];	// Attempt to resolve the service. A value of 0.0 sets an unlimited time to resolve it. The user can	// choose to cancel the resolve by selecting another service in the table view.	[self.currentResolve resolveWithTimeout:0.0];		// Make sure we give the user some feedback that the resolve is happening.	// We will be called back asynchronously, so we don't want the user to think	// we're just stuck.	self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(showWaiting:) userInfo:self.currentResolve repeats:NO];	[self.tableView reloadData];}// If necessary, sets up state to show an activity indicator to let the user know that a resolve is occuring.- (void)showWaiting:(NSTimer*)timer {		if (timer == self.timer) {		[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];		NSNetService* service = (NSNetService*)[self.timer userInfo];		if (self.currentResolve == service) {			self.needsActivityIndicator = YES;			[self.tableView reloadData];		}	}}- (void)initialWaitOver:(NSTimer*)timer {	self.initialWaitOver= YES;	if (![self.services count])		[self.tableView reloadData];}- (void)sortAndUpdateUI {	// Sort the services by name.	[self.services sortUsingSelector:@selector(localizedCaseInsensitiveCompareByName:)];	[self.tableView reloadData];}- (void)netServiceBrowser:(NSNetServiceBrowser*)netServiceBrowser didRemoveService:(NSNetService*)service moreComing:(BOOL)moreComing {	// If a service went away, stop resolving it if it's currently being resolve,	// remove it from the list and update the table view if no more events are queued.		if (self.currentResolve && [service isEqual:self.currentResolve]) {		[self stopCurrentResolve];	}	[self.services removeObject:service];		// If moreComing is NO, it means that there are no more messages in the queue from the Bonjour daemon, so we should update the UI.	// When moreComing is set, we don't update the UI so that it doesn't 'flash'.	if (!moreComing) {		[self sortAndUpdateUI];	}}	- (void)netServiceBrowser:(NSNetServiceBrowser*)netServiceBrowser didFindService:(NSNetService*)service moreComing:(BOOL)moreComing {	// If a service came online, add it to the list and update the table view if no more events are queued.	[self.services addObject:service];	// If moreComing is NO, it means that there are no more messages in the queue from the Bonjour daemon, so we should update the UI.	// When moreComing is set, we don't update the UI so that it doesn't 'flash'.	if (!moreComing) {		[self sortAndUpdateUI];	}}	// This should never be called, since we resolve with a timeout of 0.0, which means indefinite- (void)netService:(NSNetService *)sender didNotResolve:(NSDictionary *)errorDict {	[self stopCurrentResolve];	[self.tableView reloadData];}- (void)netServiceDidResolveAddress:(NSNetService *)service {	assert(service == self.currentResolve);		[service retain];	[self stopCurrentResolve];		[self.delegate browserViewController:self didResolveInstance:service];	[service release];}- (void)cancelAction {	[self.delegate browserViewController:self didResolveInstance:nil];}- (void)dealloc {	// Cleanup any running resolve and free memory	[self stopCurrentResolve];	self.services = nil;	[self.netServiceBrowser stop];	self.netServiceBrowser = nil;	[_searchingForServicesString release];		[super dealloc];}@end

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -