Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 88 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
88
Dung lượng
11,45 MB
Nội dung
ptg 587 One More Thing: FTPHelper Listing 13-2 shows the interface for the FTPHelper class and the protocol for its dele- gate. It provides its functionality via simple class methods. Listing 13-2 FTPHelper @protocol FTPHelperDelegate <NSObject> @optional // Successes - (void) receivedListing: (NSDictionary *) listing; - (void) downloadFinished; - (void) dataUploadFinished: (NSNumber *) bytes; - (void) progressAtPercent: (NSNumber *) aPercent; // Failures - (void) listingFailed; - (void) dataDownloadFailed: (NSString *) reason; - (void) dataUploadFailed: (NSString *) reason; - (void) credentialsMissing; @end @interface FTPHelper : NSObject { NSString *urlString; id <FTPHelperDelegate> delegate; NSString *uname; NSString *pword; NSMutableArray *fileListings; NSString *filePath; } @property (retain) NSString *urlString; @property (retain) id delegate; @property (retain) NSString *uname; @property (retain) NSString *pword; @property (retain) NSMutableArray *fileListings; @property (retain) NSString *filePath; // valid after download + (FTPHelper *) sharedInstance; + (void) download:(NSString *) anItem; + (void) upload: (NSString *) anItem; + (void) list: (NSString *) aURLString; + (NSString *) textForDirectoryListing: (CFDictionaryRef) dictionary; @end ptg 588 Chapter 13 Networking Summary This chapter introduced a wide range network supporting technologies.You saw how to check for network connectivity, work with keychains for secure authentication chal- lenges, upload and download data via NSURLConnection, via FTP, and more. Here are a few thoughts to take away with you before leaving this chapter: n Most of Apple’s networking support is provided through very low-level C-based routines. If you can find a friendly Objective-C wrapper to simplify your program- ming work, consider using it.The only drawback occurs when you specifically need tight networking control at the most basic level of your application. n There was not space in this chapter to discuss more detailed authentication schemes for data APIs. If you need access to OAuth, for example, search for existing Cocoa implementations.A number are available in open source repositories, and they are easily ported to Cocoa Touch. If you need to work with simpler data checksum, digest, and encoding routines, point your browser to http://www.cocoadev.com/ index.pl?NSDataCategory.This extremely handy NSData category offers md5, sha1, and base32 solutions, among others. n Many data services provide simple to use APIs such as Twitter and TwitPic.These APIs are often more limited than the fully authorized developer APIs, which typi- cally require developer credentials and advanced authorization.At the same time, they often offer simple solutions to the tasks you actually need to perform, espe- cially if you’re not writing a full client specific to a given service. n Sharing keychains across applications is tied to the provision that signed them.You can share user login items between your own applications but not with other devel- opers. Make sure you take care when creating and using keychain entitlement files to follow every step of the process.This avoids a lot of frustration when trying to produce a successful compilation. n Even when Apple provides Objective-C wrappers, as they do with NSXMLParser, it’s not always the class you wanted or hoped for.Adapting classes is a big part of the iPhone programming experience.This chapter introduced many custom classes that simplify access to core Cocoa Touch objects. ptg 14 Device Capabilities E ach iPhone device represents a meld of unique, shared, momentary, and persistent properties.These properties include the device’s current physical orientation, its model name, its battery state, and its access to onboard hardware.This chapter looks at the device from its build configuration to its active onboard sensors. It provides recipes that return a variety of information items about the unit in use.You read about testing for hardware prerequisites at runtime and specifying those prerequisites in the application’s Info.plist file.You discover how to solicit sensor feedback and subscribe to notifications to create callbacks when those sensor states change.This chapter covers the hardware, file system, and sensors available on the iPhone device and helps you programmatically take advantage of those features. Recipe: Accessing Core Device Information The UIDevice class enables you to recover key device-specific values, including the iPhone or iPod touch model being used, the device name, and the OS name and version. As Recipe 14-1 shows, it’s a one-stop solution for pulling out certain system details. Each method is an instance method, which is called using the UIDevice singleton, via [UIDevice currentDevice]. The information you can retrieve from UIDevice includes these items: n System name—This returns the name of the operating system currently in use. For current generations of iPhones, there is only one OS that runs on the platform: iPhone OS. n System version—This value lists the firmware version currently installed on the unit, for example, 2.2.1, 3.0, 3.1, and so on. n Unique identifier—The iPhone unique identifier provides a hexadecimal num- ber that is guaranteed to be unique for each iPhone or iPod touch.According to Apple, the iPhone produces this identifier by applying an internal hash to several hardware specifiers, including the device serial number.The iPhone’s unique identifier is used to register devices at the iPhone portal for provisioning, including Ad Hoc distribution. ptg 590 Chapter 14 Device Capabilities n Model—The iPhone model returns a string that describes its platform, namely iPhone and iPod touch. Should the iPhone OS be extended to new devices, addi- tional strings will describe those models. n Name—This string presents the iPhone name assigned by the user in iTunes such as “Joe’s iPhone” or “Binky.”This name is also used to create the local host name for the device. See Chapter 13,“Networking,” for more details about host name retrieval. Recipe 14-1 Using the UIDevice Class - (void) action: (UIBarButtonItem *) bbi { [self doLog:@"System Name: %@", [[UIDevice currentDevice] systemName]]; [self doLog:@"System Version: %@", [[UIDevice currentDevice] systemVersion]]; [self doLog:@"Unique ID: %@", [[UIDevice currentDevice] uniqueIdentifier]]; [self doLog:@"Model %@", [[UIDevice currentDevice] model]]; [self doLog:@"Name %@", [[UIDevice currentDevice] name]]; } Get This Recipe’s Code To get the code used for this recipe, go to http://github.com/erica/iphone-3.0-cookbook-, or if you’ve downloaded the disk image containing all of the sample code from the book, go to the folder for Chapter 14 and open the project for this recipe. Adding Device Capability Restrictions When you submit 3.0 applications to iTunes, you no longer specify which platforms your application is compatible with. Instead, you tell iTunes what device features your applica- tion needs. Each iPhone and iPod touch provides a unique feature set. Some devices offer cameras and GPS capabilities. Others don’t. Some support OpenGL ES 2.0. Others are limited to OpenGL ES 1.1. Starting in firmware 3.0, you can specify what features are needed to run your application on a device. When you include the UIRequiredDeviceCapabilities key in your Info.plist file, iTunes limits application installation to devices that offer the required capabilities. Provide this list as an array of strings, whose possible values are detailed in Table 14-1. Only include those features that your application requires. If your application can provide workarounds, do not add the restriction. ptg 591 Adding Device Capability Restrictions Table 14-1 Required Device Capabilities Key Use telephony Application requires the Phone application or uses tel:// URLs. sms Application requires Messages application or uses sms:// URLs. still-camera Application uses camera mode for the image picker controller. auto-focus- camera Application requires extra focus capabilities for macro photography or especially sharp images for in-image data detection. video-camera Application uses video mode for the image picker controller. wifi Application requires local 802.11-based network access. accelerometer Application requires accelerometer-specific feedback beyond simple UIViewController orientation events. location- services Application uses Core Location. gps Application uses Core Location and requires the additional accuracy of GPS positioning. magnetometer Application uses Core Location and requires heading-related events, i.e., the direction of travel. (The magnetometer is the built-in compass.) microphone Application uses either built-in microphones or (approved) accessories that provide a microphone. opengles-1 Application uses OpenGL ES 1.1. opengles-2 Application uses OpenGL ES 2.0. armv6 Application is compiled only for the armv6 instruction set (3.1 or later). armv7 Application is compiled only for the armv7 instruction set (3.1 or later). peer-peer Application uses GameKit peer-to-peer connectivity over Bluetooth (3.1 or later). For example, consider an application that offers an option for taking pictures when run on a camera-ready device. If the application otherwise works on iPod touch units, do not include the still-camera restriction. Instead, use check for camera capability from within the application and present the camera option when appropriate.Adding a still-camera restriction eliminates all first, second, and third generation iPod owners from your poten- tial customer pool. Adding Device Requirements To add device requirements to the Info.plist file open it in the Xcode editor. Select the last row (usually Application Requires iPhone Environment) and press Return. A new item appears, already set for editing. Enter “Req”, and Xcode auto completes to “Required device capabilities”.This is the “human readable” form of the ptg 592 Chapter 14 Device Capabilities Figure 14-1 Adding required device capabilities to the Info.plist file in Xcode. UIRequiredDeviceCapabilities key.You can view the normal key name by right- clicking (Ctrl-clicking) any item in the key list and choosing Show Raw Keys/Values. Xcode automatically sets the item type to an array and adds a new Item 1. Edit the value to your first required capability.To add more items, select any item and press Return. Xcode inserts a new key-value pair. Figure 14-1 shows the editor in action. Recipe: Recovering Additional Device Information Both sysctl() and sysctlbyname() allow you to retrieve system information.These standard UNIX functions query the operating system about hardware and OS details.You can get a sense of the kind of scope on offer by glancing at the /usr/include/sys/sysctl.h include file on the Macintosh.There you find an exhaustive list of constants that can be used as parameters to these functions. These constants allow you to check for core information like the system’s CPU fre- quency, the amount of available memory, and more. Recipe 14-2 demonstrates this. It introduces a UIDevice category that gathers system information and returns it via a series of method calls. You might wonder why this category includes a platform method, when the standard UIDevice class returns device models on demand.The answer lies in distinguishing differ- ent types of iPhones and iPod touch units. An iPhone 3GS’s model is simply “iPhone,” as is the model of an iPhone 3G and the original iPhone. In contrast, this recipe returns a platform value of “iPhone2,1” for the 3GS.This allows you to programmatically differentiate the unit from a first generation iPhone (“iPhone1,1”) or iPhone 3G (“iPhone1,2”). Each model offers distinct built-in capabilities. Knowing exactly which iPhone you’re dealing with helps you determine whether that unit supports features like accessibility, GPS, and magnetometers. ptg 593 Recipe: Recovering Additional Device Information Recipe 14-2 Accessing Device Information Through sysctl() and sysctlbyname() @implementation UIDevice (Hardware) + (NSString *) getSysInfoByName:(char *)typeSpecifier { // Recover sysctl information by name size_t size; sysctlbyname(typeSpecifier, NULL, &size, NULL, 0); char *answer = malloc(size); sysctlbyname(typeSpecifier, answer, &size, NULL, 0); NSString *results = [NSString stringWithCString:answer encoding: NSUTF8StringEncoding]; free(answer); return results; } - (NSString *) platform { return [UIDevice getSysInfoByName:"hw.machine"]; } + (NSUInteger) getSysInfo: (uint) typeSpecifier { size_t size = sizeof(int); int results; int mib[2] = {CTL_HW, typeSpecifier}; sysctl(mib, 2, &results, &size, NULL, 0); return (NSUInteger) results; } - (NSUInteger) cpuFrequency { return [UIDevice getSysInfo:HW_CPU_FREQ]; } - (NSUInteger) busFrequency { return [UIDevice getSysInfo:HW_BUS_FREQ]; } - (NSUInteger) totalMemory { return [UIDevice getSysInfo:HW_PHYSMEM]; } - (NSUInteger) userMemory { ptg 594 Chapter 14 Device Capabilities return [UIDevice getSysInfo:HW_USERMEM]; } - (NSUInteger) maxSocketBufferSize { return [UIDevice getSysInfo:KIPC_MAXSOCKBUF]; } @end Get This Recipe’s Code To get the code used for this recipe, go to http://github.com/erica/iphone-3.0-cookbook-, or if you’ve downloaded the disk image containing all of the sample code from the book, go to the folder for Chapter 14 and open the project for this recipe. Recipe: Monitoring the iPhone Battery State The 3.0 and later API allows you to keep track of the iPhone’s battery level and charge state.The level is a floating-point value that ranges between 1.0 (fully charged) and 0.0 (fully discharged). It provides an approximate discharge level that you can use to query before performing operations that put unusual strain on the device. For example, you might want to caution your user about performing a large series of convolutions and suggest that the user plug in to a power source.You retrieve the battery level via this UIDevice call.The value returned is produced in 5% increments. NSLog(@"Battery level: %0.2f%", [[UIDevice currentDevice] batteryLevel] * 100); The iPhone charge state has four possible values.The unit can be charging (i.e., connected to a power source), full, unplugged, and a catchall “unknown.” Recover the state using the UIDevice batteryState property. NSArray *stateArray = [NSArray arrayWithObjects: @"Battery state is unknown", @"Battery is not plugged into a charging source", @"Battery is charging", @"Battery state is full", nil]; NSLog(@"Battery state: %@", [stateArray objectAtIndex: [[UIDevice currentDevice] batteryState]]); Don’t think of these choices as persistent states. Instead, think of them as momentary reflections of what is actually happening to the device.They are not flags.They are not or’ed together to form a general battery description. Instead, these values reflect the most recent state change. Recipe 14-3 monitors state changes.When it detects that the battery state has changed, only then does it check to see what that state change indicated. In this way, you ptg 595 Recipe: Monitoring the iPhone Battery State can catch momentary events, such as when the battery finally recharges fully, when the user has plugged in to a power source to recharge, and when the user disconnects from that power source. To start monitoring, set the batteryMonitoringEnabled property to YES. During monitoring, the UIDevice class produces notifications when the battery state or level changes. Recipe 14-3 subscribes to both notifications. Please note that you can also check these values directly, without waiting for notifications.Apple provides no guarantees about the frequency of level change updates, but as you can tell by testing this recipe, they arrive in a fairly regular fashion. Recipe 14-3 Monitoring the iPhone Battery - (void) checkBattery: (id) sender { NSArray *stateArray = [NSArray arrayWithObjects: @"Battery state is Unknown", @"Battery is unplugged", @"Battery is charging", @"Battery state is full", nil]; NSLog(@"Battery level: %0.2f%", [[UIDevice currentDevice] batteryLevel] * 100); NSLog(@"Battery state: %@", [stateArray objectAtIndex:[[UIDevice currentDevice] batteryState]]); } - (void) viewDidLoad { // Enable battery monitoring [[UIDevice currentDevice] setBatteryMonitoringEnabled:YES]; // Add observers for battery state and level changes [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(checkBattery) name:UIDeviceBatteryStateDidChangeNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(checkBattery) name:UIDeviceBatteryLevelDidChangeNotification object:nil]; } Get This Recipe’s Code To get the code used for this recipe, go to http://github.com/erica/iphone-3.0-cookbook-, or if you’ve downloaded the disk image containing all of the sample code from the book, go to the folder for Chapter 14 and open the project for this recipe. ptg 596 Chapter 14 Device Capabilities Recipe: Enabling and Disabling the Proximity Sensor Unless you have some pressing reason to hold an iPhone against body parts (or vice versa), enabling the proximity sensor accomplishes little.When enabled, it has one primary task. It detects whether there’s a large object right in front of it. If so, it switches the screen off and sends off a general notification. Move the blocking object away and the screen switches back on.This prevents you from pressing buttons or dialing the phone with your ear when you are on a call. Some poorly designed protective cases keep the iPhone’s prox- imity sensors from working properly. The Google Mobile application on App Store used this feature to start a voice record- ing session.When you held the phone up to your head it would record your query, send- ing it off to be interpreted when moved away from your head.The developers didn’t mind that the screen blanked as the voice recording interface did not depend on a visual GUI to operate. Recipe 14-4 demonstrates how to work with proximity sensing on the iPhone. It uses the UIDevice class to toggle proximity monitoring and subscribes to UIDeviceProximity ➥StateDidChangeNotification to catch state changes.The two states are on and off. When the UIDevice proximityState property returns YES, the proximity sensor has been activated. Note Prior to the 3.0 firmware, proximity used to be controlled by the UIApplication class. This approach is now deprecated. Also be aware that setProximityState: is documented, but the method is actually nonexistent. Proximity state is a read-only property. Recipe 14-4 Enabling Proximity Sensing - (void) toggle: (id) sender { // Determine the current proximity monitoring and toggle it BOOL isIt = [UIDevice currentDevice].proximityMonitoringEnabled; [UIDevice currentDevice].proximityMonitoringEnabled = !isIt; NSString *title = isIt ? @"Enable" : @"Disable"; self.navigationItem.rightBarButtonItem = BARBUTTON(title, @selector(toggle)); NSLog(@"You have %@ the Proximity sensor.", isIt ? @"disabled" : @"enabled"); } - (void) stateChange: (NSNotificationCenter *) notification { // Log the notifications NSLog(@"The proximity sensor %@", [UIDevice currentDevice].proximityState ? [...]... measure the current forces It’s up to the timer routine to apply those forces to the butterfly over time by changing its frame n n n As long as the direction of force remains the same, the butterfly accelerates Its velocity increases, scaled according to the degree of acceleration force in the X or Y direction The tick routine, called by the timer, moves the butterfly by adding the velocity vector to the. .. the code used for this recipe, go to http://github.com/erica /iphone- 3.0 -cookbook- , or if you’ve downloaded the disk image containing all of the sample code from the book, go to the folder for Chapter 14 and open the project for this recipe Recipe: Detecting Shakes Using Motion Events When the iPhone detects a motion event, it passes that event to the current first responder, the primary object in the. .. http://github.com/erica /iphone- 3.0 -cookbook- , or if you’ve downloaded the disk image containing all of the sample code from the book, go to the folder for Chapter 15 and open the project for this recipe Recipe: Audio That Ignores Sleep Locking an iPhone by pressing the sleep/wake button causes an iPhone or iPod to experience the same interruption events that occur with phone calls.When the unit locks, the AVAudioPlayer... http://github.com/erica /iphone- 3.0 -cookbook- , or if you’ve downloaded the disk image containing all of the sample code from the book, go to the folder for Chapter 14 and open the project for this recipe Recipe: Using Acceleration to Locate “Up” The iPhone provides three onboard sensors that measure acceleration along the iPhone s perpendicular axis; that is, left/right (X), up/down (Y), and front/back (Z).These values... { [self.delegate performSelector:@selector(shake)]; } } @end Get This Recipe’s Code To get the code used for this recipe, go to http://github.com/erica /iphone- 3.0 -cookbook- , or if you’ve downloaded the disk image containing all of the sample code from the book, go to the folder for Chapter 14 and open the project for this recipe One More Thing: Checking for Available Disk Space The NSFileManager class... used for this recipe, go to http://github.com/erica /iphone- 3.0 -cookbook- , or if you’ve downloaded the disk image containing all of the sample code from the book, go to the folder for Chapter 14 and open the project for this recipe Recipe: Detecting Device Orientation The iPhone orientation refers to the way that a user is holding the device Query the device orientation at any time by retrieving [UIDevice... events The motion callbacks mirror the touch ones discussed in Chapter 8, “Gestures and Touches.” They are n n n motionBegan:withEvent:—This callback indicates the start of a motion event.At the time of writing this book, there was only one kind of motion event recognized: a shake.This may not hold true for the future, so you might want to check the motion type in your code motionEnded:withEvent: The first... the sample code from the book, go to the folder for Chapter 14 and open the project for this recipe Recipe: Detecting Shakes Directly from the Accelerometer Recipe 14-9 mimics the Apple motion detection system while avoiding the need for the event consumer to be the first responder It’s built on two key parameters: a sensitivity level that provides a threshold that must be met before a shake is acknowledged... viewDidLoad { // Init the delegate to start catching accelerometer events [[UIAccelerometer sharedAccelerometer] setDelegate:self]; } Get This Recipe’s Code To get the code used for this recipe, go to http://github.com/erica /iphone- 3.0 -cookbook- , or if you’ve downloaded the disk image containing all of the sample code from the book, go to the folder for Chapter 14 and open the project for this recipe Recipe:... so, use the peakPowerForChannel: and averagePowerForChannel: methods to read those levels Recipe 15-7, later in this chapter, shows the details of what’s likely going on under the hood in the player when it requests those power levels.You can see that code request the meter levels and then extract either the peak or average power The AVAudioPlayer class hides those details, simplifying access to these . use. For current generations of iPhones, there is only one OS that runs on the platform: iPhone OS. n System version—This value lists the firmware version currently installed on the unit, for. get the code used for this recipe, go to http://github.com/erica /iphone- 3.0 -cookbook- , or if you’ve downloaded the disk image containing all of the sample code from the book, go to the folder for. recipe returns a platform value of iPhone2 ,1” for the 3GS.This allows you to programmatically differentiate the unit from a first generation iPhone ( iPhone1 ,1”) or iPhone 3G ( iPhone1 ,2”). Each