Apple Key-Value Observing Programming Guide Manuel Apple sur Fnac.com - Pour voir la liste complète des manuels APPLE, cliquez ici
ou juste avant la balise de fermeture -->
ou juste avant la balise de fermeture -->

 

 

TELECHARGER LE PDF sur :

https://developer.apple.com/library/mac/documentation//Cocoa/Conceptual/KeyValueObserving/KeyValueObserving.pdf

Commander un produit Apple sur Fnac.com

 

 

Voir également d'autres Guides et documentation APPLE :

Apple-InstrumentsUserGuide.pdf-manuel

Apple-Logic-Pro-9-TDM-Guide-manuel

Apple-macbook_air_users_guide.pdf-manuel

Apple-macbook_air-13-inch_mid-2012-qs_ta.pdf-manuel

Apple-AppStoreMarketingGuidelines-JP.pdf-Japon-manuel

Apple-macbook_pro_retina_qs_ta.pdf-manuel

Apple-ipad_user_guide_tu.pdf-manuel

Apple-ipad_user_guide_th.pdf-manuel

Apple-iphone_user_guide_gr.pdf-manuel

Apple-Nike_Plus_iPod_Sensor_UG_2A.pdf-manuel

Apple-ipad_manual_del_usuario.pdf-manuel

Apple-ipad_uzivatelska_prirucka.pdf-manuel

Apple-ipad_wifi_informations_importantes.pdf-manuel

Apple-Xsan_2_Admin_Guide_v2.3.pdf-manuel

Apple-macbook_pro-13-inch-late-2012-quick_start.pdf-manuel

Apple-CocoaDrawingGuide.pdf-manuel

Apple-Cryptographic-Services-Guide-manuel

Apple-Resource-Programming-Guide-manuel

AppleSafariVisualEffectsProgGuide.pdf-manuel

/Apple-WorkingWithUSB.pdf-manuel

Apple-macbook_pro-retina-mid-2012-important_product_info_f.pdf-manuel

Apple-iOS_Security_May12.pdf-manue

Apple-Mac-Pro-2008-Performance-and-Productivity-for-Creative-Pros

Apple-iPod_shuffle_4thgen_Manuale_utente.pdf-Italie-Manuel

Apple-KernelProgramming.pdf-manuel

Apple-Core-Data-Model-Versioning-and-Data-Migration-Programming-Guide-manuel

Apple-RED_Workflows_with_Final_Cut_Pro_X.pdf-manuel

Apple-Transitioning-to-ARC-Release-Notes-manuel

Apple-iTunes-Connect-Sales-and-Trends-Guide-manuel

Apple-App-Sandbox-Design-Guide-manuel

Apple-String-Programming-Guide-manuel

Apple-Secure-Coding-Guide-manuel

Apple_AirPort_Networks_Early2009.pdf-manuel

Apple-TimeCapsule_SetupGuide_TA.pdf-manuel

Apple-time_capsule_4th_gen_setup.pdf-manuel

Apple-TimeCapsule_SetupGuide.pdf-manuel

Apple-TimeCapsule_SetupGuide_CH.pdf-Chinois-manuel

Apple-CodeSigningGuide.pdf-manuel

Apple-ViewControllerPGforiOS.pdf-manuel

Apple-KeyValueObserving.pdf-manuel

Apple-mac_mini-late-2012-quick_start.pdf-manuel

Apple-OS-X-Mountain-Lion-Core-Technologies-Overview-June-2012-manuel

Apple-OS-X-Server-Product-Overview-June-2012-manuel

Apple-Apple_Server_Diagnostics_UG_109.pdf-manuel

Apple-PackageMaker_UserGuide.pdf-manuel

Apple-Instrumentos_y_efectos_de_Logic_Studio.pdf-Manuel

Apple-ipod_nano_kayttoopas.pdf-Finlande-Manuel

Apple_ProRes_White_Paper_October_2012.pdf-Manuel

Apple-wp_osx_configuration_profiles.pdf-Manuel

Apple-UsingiTunesProducerFreeBooks.pdf-Manuel

Apple-ipad_manual_do_usuario.pdf-Portugais-Manuel

Apple-Instruments_et_effets_Logic_Studio.pdf-Manuel

Apple-ipod_touch_gebruikershandleiding.pdf-Neerlandais-Manuel

AppleiPod_shuffle_4thgen_Manual_del_usuario.pdf-Espagnol-Manuel

Apple-Premiers-contacts-avec-votre-PowerBook-G4-Manuel

Apple_Composite_AV_Cable.pdf-Manuel

Apple-iPod_shuffle_3rdGen_UG_DK.pdf-Danemark-Manuel

Apple-iPod_classic_160GB_Benutzerhandbuch.pdf-Allemand-Manuel

Apple-VoiceOver_GettingStarted-Manuel

Apple-iPod_touch_2.2_Benutzerhandbuch.pdf-Allemand-Manuel

Apple-Apple_TV_Opstillingsvejledning.pdf-Allemand-Manuel

Apple-iPod_shuffle_4thgen_Manuale_utente.pdf-Italie-Manuel

Apple-iphone_prirucka_uzivatela.pdf-Manuel

Apple-Aan-de-slag-Neerlandais-Manuel

Apple-airmac_express-80211n-2nd-gen_setup_guide.pdf-Thailande-Manuel

Apple-ipod_nano_benutzerhandbuch.pdf-Allemand-Manuel

Apple-aperture3.4_101.pdf-Manuel

Apple-Pages09_Anvandarhandbok.pdf-Manuel

Apple-nike_plus_ipod_sensor_ug_la.pdf-Mexique-Manuel

Apple-ResEdit-Reference-For-ResEdit02.1-Manuel

Apple-ipad_guide_de_l_utilisateur.pdf-Manuel

Apple-Compressor-4-Benutzerhandbuch-Allemand-Manuel

Apple-AirPort_Networks_Early2009_DK.pdf-Danemark-Manuel

Apple-MacBook_Pro_Mid2007_2.4_2.2GHz_F.pdf-Manuel

Apple-MacBook_13inch_Mid2010_UG_F.pdf-Manuel

Apple-Xserve-RAID-Presentation-technologique-Janvier-2004-Manuel

Apple-MacBook_Pro_15inch_Mid2010_F.pdf-Manuel

Apple-AirPort_Express-opstillingsvejledning.pdf-Danemark-Manuel

Apple-DEiPod_photo_Benutzerhandbuch_DE0190269.pdf-Allemand-Manuel

Apple-Final-Cut-Pro-X-Logic-Effects-Reference-Manuel

Apple-iPod_touch_2.1_Brugerhandbog.pdf-Danemark-Manuel

Apple-Remote-Desktop-Administratorhandbuch-Version-3.1-Allemand-Manuel

Apple-Qmaster-4-User-Manual-Manuel

Apple-Server_Administration_v10.5.pdf-Manuel

Apple-ipod_classic_features_guide.pdf-Manuel

Apple-Lecteur-Optique-Manuel

Apple-Carte-AirPort-Manuel

Apple-iPhone_Finger_Tips_Guide.pdf-Anglais-Manuel

Apple-Couvercle-Manuel

Apple-battery.cube.pdf-Manuel

Apple-Boitier-de-l-ordinateur-Manuel

Apple-Pile-Interne-Manuel

Apple-atacable.pdf-Manuel

Apple-videocard.pdf-Manuel

Apple-Guide_de_configuration_de_l_Airport_Express_5.1.pdf-Manuel

Apple-iMac_Mid2010_UG_F.pdf-Manuel

Apple-MacBook_13inch_Mid2009_F.pdf-Manuel

Apple-MacBook_Mid2007_UserGuide.F.pdf-Manuel

Apple-Designing_AirPort_Networks_10.5-Windows_F.pdf-Manuel

Apple-Administration_de_QuickTime_Streaming_et_Broadcasting_10.5.pdf-Manuel

Apple-Opstillingsvejledning_til_TimeCapsule.pdf-Danemark-Manuel

Apple-iPod_nano_5th_gen_Benutzerhandbuch.pdf-Manuel

Apple-iOS_Business.pdf-Manuel

Apple-AirPort_Extreme_Installationshandbuch.pdf-Manuel

Apple-Final_Cut_Express_4_Installation_de_votre_logiciel.pdf-Manuel

Apple-MacBook_Pro_15inch_2.53GHz_Mid2009.pdf-Manuel

Apple-Network_Services.pdf-Manuel

Apple-Aperture_Performing_Adjustments_f.pdf-Manuel

Apple-Supplement_au_guide_Premiers_contacts.pdf-Manuel

Apple-Administration_des_images_systeme_et_de_la_mise_a_jour_de_logiciels_10.5.pdf-Manuel

Apple-Mac_OSX_Server_v10.6_Premiers_contacts.pdf-Francais-Manuel

Apple-Designing_AirPort_Networks_10.5-Windows_F.pdf-Manuel

Apple-Mise_a_niveau_et_migration_v10.5.pdf-Manue

Apple-MacBookPro_Late_2007_2.4_2.2GHz_F.pdf-Manuel

Apple-Mac_mini_Late2009_SL_Server_F.pdf-Manuel

Apple-Mac_OS_X_Server_10.5_Premiers_contacts.pdf-Manuel

Apple-iPod_touch_2.0_Guide_de_l_utilisateur_CA.pdf-Manuel

Apple-MacBook_Pro_17inch_Mid2010_F.pdf-Manuel

Apple-Comment_demarrer_Leopard.pdf-Manuel

Apple-iPod_2ndGen_USB_Power_Adapter-FR.pdf-Manuel

Apple-Feuille_de_operations_10.4.pdf-Manuel

Apple-Time_Capsule_Installationshandbuch.pdf-Allemand-Manuel

Apple-F034-2262AXerve-grappe.pdf-Manuel

Apple-Mac_Pro_Early2009_4707_UG_F

Apple-imacg5_17inch_Power_Supply

Apple-Logic_Studio_Installieren_Ihrer_Software_Retail

Apple-IntroductionXserve1.0.1

Apple-Aperture_Getting_Started_d.pdf-Allemand

Apple-getting_started_with_passbook

Apple-iPod_mini_2nd_Gen_UserGuide.pdf-Anglais

Apple-Deploiement-d-iPhone-et-d-iPad-Reseaux-prives-virtuels

Apple-F034-2262AXerve-grappe

Apple-Mac_OS_X_Server_Glossaire_10.5

Apple-FRLogic_Pro_7_Guide_TDM

Apple-iphone_bluetooth_headset_userguide

Apple-Administration_des_services_reseau_10.5

Apple-imacg5_17inch_harddrive

Apple-iPod_nano_4th_gen_Manuale_utente

Apple-iBook-G4-Getting-Started

Apple-XsanGettingStarted

Apple-Mac_mini_UG-Early2006

Apple-Guide_des_fonctionnalites_de_l_iPod_classic

Apple-Guide_de_configuration_d_Xsan_2

Apple-MacBook_Late2006_UsersGuide

Apple-sur-Fnac.com

Apple-Mac_mini_Mid2010_User_Guide_F.pdf-Francais

Apple-PowerBookG3UserManual.PDF.Anglais

Apple-Installation_de_votre_logiciel_Logic_Studio_Retail

Apple-Pages-Guide-de-l-utilisateur

Apple-MacBook_Pro_13inch_Mid2009.pdf.Anglais

Apple-MacBook_Pro_15inch_Mid2009

Apple-Installation_de_votre_logiciel_Logic_Studio_Upgrade

Apple-FRLogic_Pro_7_Guide_TDM

Apple-airportextreme_802.11n_userguide

Apple-iPod_shuffle_3rdGen_UG

Apple-iPod_classic_160GB_User_Guide

Apple-iPod_nano_5th_gen_UserGuide

Apple-ipod_touch_features_guide

Apple-Wireless_Mighty_Mouse_UG

Apple-Advanced-Memory-Management-Programming-Guide

Apple-iOS-App-Programming-Guide

Apple-Concurrency-Programming-Guide

Apple-MainStage-2-User-Manual-Anglais

Apple-iMacG3_2002MultilingualUserGuide

Apple-iBookG3_DualUSBUserGuideMultilingual.PDF.Anglais

Apple-imacG5_20inch_AirPort

Apple-Guide_de_l_utilisateur_de_Mac_Pro_Early_2008

Apple-Installation_de_votre_logiciel_Logic_Express_8

Apple-iMac_Guide_de_l_utilisateur_Mid2007

Apple-imacg5_20inch_OpticalDrive

Apple-FCP6_Formats_de_diffusion_et_formats_HD

Apple-prise_en_charge_des_surfaces_de_controle_logic_pro_8

Apple-Aperture_Quick_Reference_f

Apple-Shake_4_User_Manual

Apple-aluminumAppleKeyboard_wireless2007_UserGuide

Apple-ipod_shuffle_features_guide

Apple-Color-User-Manual

Apple-XsanGettingStarted

Apple-Migration_10.4_2e_Ed

Apple-MacBook_Air_SuperDrive

Apple-MacBook_Late2007-f

ApplePowerMacG5_(Early_2005)_UserGuide

Apple-iSightUserGuide

Apple-MacBook_Pro_Early_2008_Guide_de_l_utilisateur

Apple-Nouvelles-fonctionnalites-aperture-1.5

Apple-premiers_contacts_2e_ed_10.4.pdf-Mac-OS-X-Server

Apple-premiers_contacts_2e_ed_10.4

Apple-eMac_2005UserGuide

Apple-imacg5_20inch_Inverter

Apple-Keynote2_UserGuide.pdf-Japon

Apple-Welcome_to_Tiger.pdf-Japon

Apple-XsanAdminGuide_j.pdf-Japon

Apple-PowerBookG4_UG_15GE.PDF-Japon

Apple-Xsan_Migration.pdf-Japon

Apple-Xserve_Intel_DIY_TopCover_JA.pdf-Japon

Apple-iPod_nano_6thgen_User_Guide_J.pdf-Japon

Apple-Aperture_Photography_Fundamentals.pdf-Japon

Apple-nikeipod_users_guide.pdf-Japon

Apple-QuickTime71_UsersGuide.pdf-Japon

Apple-iMacG5_iSight_UG.pdf-Japon

Apple-Aperture_Performing_Adjustments_j.pdf-Japon

Apple-iMacG5_17inch_HardDrive.pdf-Japon

Apple-iPod_shuffle_Features_Guide_J.pdf-Japon

Apple-MacBook_Air_User_Guide.pdf-Japon

Apple-MacBook_UsersGuide.pdf-Japon

Apple-iPad_iOS4_Brukerhandbok.pdf-Norge-Norvege

Apple-Apple_AirPort_Networks_Early2009_H.pd-Norge-Norvege

Apple-iPod_classic_120GB_no.pdf-Norge-Norvege

Apple-StoreKitGuide.pdf-Japon

Apple-Xserve_Intel_DIY_ExpansionCardRiser_JA.pdf-Japon

Apple-iMacG5_Battery.pdf-Japon

Apple-Logic_Pro_8_Getting_Started.pdf-Japon

Apple-PowerBook-handbok-Norge-Norveg

Apple-iWork09_formler_og_funksjoner.pdf-Norge-Norvege

Apple-MacBook_Pro_15inch_Mid2010_H.pdf-Norge-Norvege

Apple-MacPro_HardDrive_DIY.pdf-Japon

Apple-iPod_Fifth_Gen_Funksjonsoversikt.pdf-Norge-Norvege

Apple-MacBook_13inch_white_Early2009_H.pdf-Norge-Norvege

Apple-GarageBand_09_Komme_i_gang.pdf-Norge-Norvege

Apple-MacBook_Pro_15inch_Mid2009_H.pdf-Norge-Norvege

Apple-imac_mid2011_ug_h.pdf-Norge-Norvege

Apple-iDVD_08_Komme_i_gang.pdf-Norge-Norvege

Apple-MacBook_Air_11inch_Late2010_UG_H.pdf-Norge-Norvege

Apple-iMac_Mid2010_UG_H.pdf-Norge-Norvege

Apple-MacBook_13inch_Mid2009_H.pdf-Norge-Norvege

/Apple-iPhone_3G_Viktig_produktinformasjon_H-Norge-Norvege

Apple-MacBook_13inch_Mid2010_UG_H.pdf-Norge-Norvege

Apple-macbook_air_13inch_mid2011_ug_no.pdf-Norge-Norvege

Apple-Mac_mini_Early2009_UG_H.pdf-Norge-Norvege

Apple-ipad2_brukerhandbok.pdf-Norge-Norvege

Apple-iPhoto_08_Komme_i_gang.pdf-Norge-Norvege

Apple-MacBook_Air_Brukerhandbok_Late2008.pdf-Norge-Norvege

Apple-Pages09_Brukerhandbok.pdf-Norge-Norvege

Apple-MacBook_13inch_Late2009_UG_H.pdf-Norge-Norvege

Apple-iPhone_3GS_Viktig_produktinformasjon.pdf-Norge-Norvege

Apple-MacBook_13inch_Aluminum_Late2008_H.pdf-Norge-Norvege

Apple-Wireless_Keyboard_Aluminum_2007_H-Norge-Norvege

Apple-NiPod_photo_Brukerhandbok_N0190269.pdf-Norge-Norvege

Apple-MacBook_Pro_13inch_Mid2010_H.pdf-Norge-Norvege

Apple-MacBook_Pro_17inch_Mid2010_H.pdf-Norge-Norvege

Apple-Velkommen_til_Snow_Leopard.pdf-Norge-Norvege.htm

Apple-TimeCapsule_Klargjoringsoversikt.pdf-Norge-Norvege

Apple-iPhone_3GS_Hurtigstart.pdf-Norge-Norvege

Apple-Snow_Leopard_Installeringsinstruksjoner.pdf-Norge-Norvege

Apple-iMacG5_iSight_UG.pdf-Norge-Norvege

Apple-iPod_Handbok_S0342141.pdf-Norge-Norvege

Apple-ipad_brukerhandbok.pdf-Norge-Norvege

Apple-GE_Money_Bank_Handlekonto.pdf-Norge-Norvege

Apple-MacBook_Air_11inch_Late2010_UG_H.pdf-Norge-Norvege

Apple-iPod_nano_6thgen_Brukerhandbok.pdf-Norge-Norvege

Apple-iPod_touch_iOS4_Brukerhandbok.pdf-Norge-Norvege

Apple-MacBook_Air_13inch_Late2010_UG_H.pdf-Norge-Norvege

Apple-MacBook_Pro_15inch_Early2011_H.pdf-Norge-Norvege

Apple-Numbers09_Brukerhandbok.pdf-Norge-Norvege

Apple-Welcome_to_Leopard.pdf-Japon

Apple-PowerMacG5_UserGuide.pdf-Norge-Norvege

Apple-iPod_touch_2.1_Brukerhandbok.pdf-Norge-Norvege

Apple-Boot_Camp_Installering-klargjoring.pdf-Norge-Norvege

Apple-MacOSX10.3_Welcome.pdf-Norge-Norvege

Apple-iPod_shuffle_3rdGen_UG_H.pdf-Norge-Norvege

Apple-iPhone_4_Viktig_produktinformasjon.pdf-Norge-Norvege

Apple_TV_Klargjoringsoversikt.pdf-Norge-Norvege

Apple-iMovie_08_Komme_i_gang.pdf-Norge-Norvege

Apple-iPod_classic_160GB_Brukerhandbok.pdf-Norge-Norvege

Apple-Boot_Camp_Installering_10.6.pdf-Norge-Norvege

Apple-Network-Services-Location-Manager-Veiledning-for-nettverksadministratorer-Norge-Norvege

Apple-iOS_Business_Mar12_FR.pdf

Apple-PCIDualAttachedFDDICard.pdf

Apple-Aperture_Installing_Your_Software_f.pdf

Apple-User_Management_Admin_v10.4.pdf

Apple-Compressor-4-ユーザーズマニュアル Japon

Apple-Network_Services_v10.4.pdf

Apple-iPod_2ndGen_USB_Power_Adapter-DE

Apple-Mail_Service_v10.4.pdf

Apple-AirPort_Express_Opstillingsvejledning_5.1.pdf

Apple-MagSafe_Airline_Adapter.pdf

Apple-L-Apple-Multiple-Scan-20-Display

Apple-Administration_du_service_de_messagerie_10.5.pdf

Apple-System_Image_Admin.pdf

Apple-iMac_Intel-based_Late2006.pdf-Japon

Apple-iPhone_3GS_Finger_Tips_J.pdf-Japon

Apple-Power-Mac-G4-Mirrored-Drive-Doors-Japon

Apple-AirMac-カード取り付け手順-Japon

Apple-iPhone開発ガイド-Japon

Apple-atadrive_pmg4mdd.j.pdf-Japon

Apple-iPod_touch_2.2_User_Guide_J.pdf-Japon

Apple-Mac_OS_X_Server_v10.2.pdf

Apple-AppleCare_Protection_Plan_for_Apple_TV.pdf

Apple_Component_AV_Cable.pdf

Apple-DVD_Studio_Pro_4_Installation_de_votre_logiciel

Apple-Windows_Services

Apple-Motion_3_New_Features_F

Apple-g4mdd-fw800-lowerfan

Apple-MacOSX10.3_Welcome

Apple-Print_Service

Apple-Xserve_Setup_Guide_F

Apple-PowerBookG4_17inch1.67GHzUG

Apple-iMac_Intel-based_Late2006

Apple-Installation_de_votre_logiciel

Apple-guide_des_fonctions_de_l_iPod_nano

Apple-Administration_de_serveur_v10.5

Apple-Mac-OS-X-Server-Premiers-contacts-Pour-la-version-10.3-ou-ulterieure

Apple-boot_camp_install-setup

Apple-iBookG3_14inchUserGuideMultilingual

Apple-mac_pro_server_mid2010_ug_f

Apple-Motion_Supplemental_Documentation

Apple-imac_mid2011_ug_f

Apple-iphone_guide_de_l_utilisateur

Apple-macbook_air_11inch_mid2011_ug_fr

Apple-NouvellesfonctionnalitesdeLogicExpress7.2

Apple-QT_Streaming_Server

Apple-Web_Technologies_Admin

Apple-Mac_Pro_Early2009_4707_UG

Apple-guide_de_l_utilisateur_de_Numbers08

Apple-Decouverte_d_Aperture_2

Apple-Guide_de_configuration_et_d'administration

Apple-mac_integration_basics_fr_106.

Apple-iPod_shuffle_4thgen_Guide_de_l_utilisateur

Apple-ARA_Japan

Apple-081811_APP_iPhone_Japanese_v5.4.pdf-Japan

Apple-Recycle_Contract120919.pdf-Japan

Apple-World_Travel_Adapter_Kit_UG

Apple-iPod_nano_6thgen_User_Guide

Apple-RemoteSupportJP

Apple-Mac_mini_Early2009_UG_F.pdf-Manuel-de-l-utilisateur

Apple-Compressor_3_Batch_Monitor_User_Manual_F.pdf-Manuel-de-l-utilisateur

Apple-Premiers__contacts_avec_iDVD_08

Apple-Mac_mini_Intel_User_Guide.pdf

Apple-Prise_en_charge_des_surfaces_de_controle_Logic_Express_8

Apple-mac_integration_basics_fr_107.pdf

Apple-Final-Cut-Pro-7-Niveau-1-Guide-de-preparation-a-l-examen

Apple-Logic9-examen-prep-fr.pdf-Logic-Pro-9-Niveau-1-Guide-de-preparation-a-l-examen

Apple-aperture_photography_fundamentals.pdf-Manuel-de-l-utilisateu

Apple-emac-memory.pdf-Manuel-de-l-utilisateur

Apple-Apple-Installation-et-configuration-de-votre-Power-Mac-G4

Apple-Guide_de_l_administrateur_d_Xsan_2.pdf

Apple-premiers_contacts_avec_imovie6.pdf

Apple-Tiger_Guide_Installation_et_de_configuration.pdf

Apple-Final-Cut-Pro-7-Level-One-Exam-Preparation-Guide-and-Practice-Exam

Apple-Open_Directory.pdf

Apple-Nike_+_iPod_User_guide

Apple-ard_admin_guide_2.2_fr.pdf

Apple-systemoverviewj.pdf-Japon

Apple-Xserve_TO_J070411.pdf-Japon

Apple-Mac_Pro_User_Guide.pdf

Apple-iMacG5_iSight_UG.pdf

Apple-premiers_contacts_avec_iwork_08.pdf

Apple-services_de_collaboration_2e_ed_10.4.pdf

Apple-iPhone_Bluetooth_Headset_Benutzerhandbuch.pdf

Apple-Guide_de_l_utilisateur_de_Keynote08.pdf

APPLE/Apple-Logic-Pro-9-Effectsrfr.pdf

Apple-Logic-Pro-9-Effectsrfr.pdf

Apple-iPod_shuffle_3rdGen_UG_F.pdf

Apple-iPod_classic_160Go_Guide_de_l_utilisateur.pdf

Apple-iBookG4GettingStarted.pdf

Apple-Administration_de_technologies_web_10.5.pdf

Apple-Compressor-4-User-Manual-fr

Apple-MainStage-User-Manual-fr.pdf

Apple-Logic_Pro_8.0_lbn_j.pdf

Apple-PowerBookG4_15inch1.67-1.5GHzUserGuide.pdf

Apple-MacBook_Pro_15inch_Mid2010_CH.pdf

Apple-LED_Cinema_Display_27-inch_UG.pdf

Apple-MacBook_Pro_15inch_Mid2009_RS.pdf

Apple-macbook_pro_13inch_early2011_f.pdf

Apple-iMac_Mid2010_UG_BR.pdf

Apple-iMac_Late2009_UG_J.pdf

Apple-iphone_user_guide-For-iOS-6-Software

Apple-iDVD5_Getting_Started.pdf

Apple-guide_des_fonctionnalites_de_l_ipod_touch.pdf

Apple_iPod_touch_User_Guide

Apple_macbook_pro_13inch_early2011_f

Apple_Guide_de_l_utilisateur_d_Utilitaire_RAID

Apple_Time_Capsule_Early2009_Setup_F

Apple_iphone_4s_finger_tips_guide_rs

Apple_iphone_upute_za_uporabu

Apple_ipad_user_guide_ta

Apple_iPod_touch_User_Guide

apple_earpods_user_guide

apple_iphone_gebruikershandleiding

apple_iphone_5_info

apple_iphone_brukerhandbok

apple_apple_tv_3rd_gen_setup_tw

apple_macbook_pro-retina-mid-2012-important_product_info_ch

apple_Macintosh-User-s-Guide-for-Macintosh-PowerBook-145

Apple_ipod_touch_user_guide_ta

Apple_TV_2nd_gen_Setup_Guide_h

Apple_ipod_touch_manual_del_usuario

Apple_iphone_4s_finger_tips_guide_tu

Apple_macbook_pro_retina_qs_th

Apple-Manuel_de_l'utilisateur_de_Final_Cut_Server

Apple-iMac_G5_de_lutilisateur

Apple-Cinema_Tools_4.0_User_Manual_F

Apple-Personal-LaserWriter300-User-s-Guide

Apple-QuickTake-100-User-s-Guide-for-Macintosh

Apple-User-s-Guide-Macintosh-LC-630-DOS-Compatible

Apple-iPhone_iOS3.1_User_Guide

Apple-iphone_4s_important_product_information_guide

Apple-iPod_shuffle_Features_Guide_F

Liste-documentation-apple

Apple-Premiers_contacts_avec_iMovie_08

Apple-macbook_pro-retina-mid-2012-important_product_info_br

Apple-macbook_pro-13-inch-mid-2012-important_product_info

Apple-macbook_air-11-inch_mid-2012-qs_br

Apple-Manuel_de_l_utilisateur_de_MainStage

Apple-Compressor_3_User_Manual_F

Apple-Color_1.0_User_Manual_F

Apple-guide_de_configuration_airport_express_4.2

Apple-TimeCapsule_SetupGuide

Apple-Instruments_et_effets_Logic_Express_8

Apple-Manuel_de_l_utilisateur_de_WaveBurner

Apple-Macmini_Guide_de_l'utilisateur

Apple-PowerMacG5_UserGuide

Disque dur, ATA parallèle Instructions de remplacement

Apple-final_cut_pro_x_logic_effects_ref_f

Apple-Leopard_Installationshandbok

Manuale Utente PowerBookG4

Apple-thunderbolt_display_getting_started_1e

Apple-Compressor-4-Benutzerhandbuch

Apple-macbook_air_11inch_mid2011_ug

Apple-macbook_air-mid-2012-important_product_info_j

Apple-iPod-nano-Guide-des-fonctionnalites

Apple-iPod-nano-Guide-des-fonctionnalites

Apple-iPod-nano-Guide-de-l-utilisateur-4eme-generation

Apple-iPod-nano-Guide-de-l-utilisateur-4eme-generation

Apple-Manuel_de_l_utilisateur_d_Utilitaire_de_reponse_d_impulsion

Apple-Aperture_2_Raccourcis_clavier

AppleTV_Setup-Guide

Apple-livetype_2_user_manual_f

Apple-imacG5_17inch_harddrive

Apple-macbook_air_guide_de_l_utilisateur

Apple-MacBook_Early_2008_Guide_de_l_utilisateur

Apple-Keynote-2-Guide-de-l-utilisateur

Apple-PowerBook-User-s-Guide-for-PowerBook-computers

Apple-Macintosh-Performa-User-s-Guide-5200CD-and-5300CD

Apple-Macintosh-Performa-User-s-Guide

Apple-Workgroup-Server-Guide

Apple-iPod-nano-Guide-des-fonctionnalites

Apple-iPad-User-Guide-For-iOS-5-1-Software

Apple-Boot-Camp-Guide-d-installation-et-de-configuration

Apple-iPod-nano-Guide-de-l-utilisateur-4eme-generation

Power Mac G5 Guide de l’utilisateur APPLE

Guide de l'utilisateur PAGE '08 APPLE

Guide de l'utilisateur KEYNOTE '09 APPLE

Guide de l'Utilisateur KEYNOTE '3 APPLE

Guide de l'Utilisateur UTILITAIRE RAID

Guide de l'Utilisateur Logic Studio

Power Mac G5 Guide de l’utilisateur APPLE

Guide de l'utilisateur PAGE '08 APPLE

Guide de l'utilisateur KEYNOTE '09 APPLE

Guide de l'Utilisateur KEYNOTE '3 APPLE

Guide de l'Utilisateur UTILITAIRE RAID

Guide de l'Utilisateur Logic Studio

Guide de l’utilisateur ipad Pour le logiciel iOS 5.1

PowerBook G4 Premiers Contacts APPLE

Guide de l'Utilisateur iphone pour le logiciel ios 5.1 APPLE

Guide de l’utilisateur ipad Pour le logiciel iOS 4,3

Guide de l’utilisateur iPod nano 5ème génération

Guide de l'utilisateur iPod Touch 2.2 APPLE

Guide de l’utilisateur QuickTime 7  Mac OS X 10.3.9 et ultérieur Windows XP et Windows 2000

Guide de l'utilisateur MacBook 13 pouces Mi 2010

Guide de l’utilisateur iPhone (Pour les logiciels iOS 4.2 et 4.3)

Guide-de-l-utilisateur-iPod-touch-pour-le-logiciel-ios-4-3-APPLE

Guide-de-l-utilisateur-iPad-2-pour-le-logiciel-ios-4-3-APPLE

Guide de déploiement en entreprise iPhone OS

Guide-de-l-administrateur-Apple-Remote-Desktop-3-1

Guide-de-l-utilisateur-Apple-Xserve-Diagnostics-Version-3X103

Guide-de-configuration-AirPort-Extreme-802.11n-5e-Generation

Guide-de-configuration-AirPort-Extreme-802-11n-5e-Generation

Guide-de-l-utilisateur-Capteur-Nike-iPod

Guide-de-l-utilisateur-iMac-21-5-pouces-et-27-pouces-mi-2011-APPLE

Guide-de-l-utilisateur-Apple-Qadministrator-4

Guide-d-installation-Apple-TV-3-eme-generation

User-Guide-iPad-For-ios-5-1-Software

Key-Value Observing Programming GuideContents Introduction to Key-Value Observing Programming Guide 4 At a Glance 4 Registering for Key-Value Observing 7 Registering as an Observer 7 Receiving Notification of a Change 8 Removing an Object as an Observer 10 KVO Compliance 11 Automatic Change Notification 11 Manual Change Notification 12 Registering Dependent Keys 15 To-one Relationships 15 To-many Relationships 16 Key-Value Observing Implementation Details 19 Document Revision History 20 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 2Listings Registering for Key-Value Observing 7 Listing 1 Registering the inspector as an observer of the openingBalance property 7 Listing 2 Implementation of observeValueForKeyPath:ofObject:change:context: 9 Listing 3 Removing the inspector as an observer of openingBalance 10 KVO Compliance 11 Listing 1 Examples of method calls that cause KVO change notifications to be emitted 11 Listing 2 Example implementation of automaticallyNotifiesObserversForKey: 12 Listing 3 Example accessor method implementing manual notification 13 Listing 4 Testing the value for change before providing notification 13 Listing 5 Nesting change notifications for multiple keys 13 Listing 6 Implementation of manual observer notification in a to-many relationship 14 Registering Dependent Keys 15 Listing 1 Example implementation of keyPathsForValuesAffectingValueForKey: 15 Listing 2 Example implementation of the keyPathsForValuesAffecting naming convention 16 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 3Key-value observing is a mechanism that allows objects to be notified of changes to specified properties of other objects. Important: In order to understand key-value observing, you must first understand key-value coding. At a Glance Key-value observing provides a mechanism that allows objects to be notified of changes to specific properties of other objects. It is particularly useful for communication between model and controller layers in an application. (In OS X, the controller layer binding technology relies heavily on key-value observing.) A controller object typically observes properties of model objects, and a view object observes properties of model objects through a controller. In addition, however, a model object may observe other model objects (usually to determine when a dependent value changes) or even itself (again to determine when a dependent value changes). You can observe properties including simple attributes, to-one relationships, and to-many relationships. Observers of to-many relationships are informed of the type of change made—as well as which objects are involved in the change. There are three steps to setting up an observer of a property. Understanding these three steps provides a clear illustration of how KVO works. 1. First, see whether you have a scenario where key-value observing could be beneficial, for example, an object that needs to be notified when any changes are made to a specific property in another object. BankObject @property int accountBalance PersonObject For example, a PersonObject will want to be aware of any changes made to their accountBalance in the BankObject. 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 4 Introduction to Key-Value Observing Programming Guide2. The PersonObject must register as an observer of the BankObject’s accountBalance property by sending an addObserver:forKeyPath:options:context: message. BankObject PersonObject Connection established [bankInstance addObserver:personInstance forKeyPath:@"accountBalance" options:NSKeyValueObservingOptionNew context:NULL]; Note: The addObserver:forKeyPath:options:context:method establishes a connection between the instances of the objects that you specify. A connection is not established between the two classes, but rather between the two specified instances of the objects. 3. In order to respond to change notifications, the observer must implement the observeValueForKeyPath:ofObject:change:context: method. This method implementation defines how the observer responds to change notifications. It is in this method that you can customize your response to a change in one of the observed properties. BankObject PersonObject Connection established -(void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { //custom implementation //be sure to call the superclass’ implementation //if the superclass implements it } “Registering for Key-Value Observing” (page 7) describes how to register and receive observation notifications. Introduction to Key-Value Observing Programming Guide At a Glance 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 54. The observeValueForKeyPath:ofObject:change:context: method is automatically invoked when the value of an observed property is changed in a KVO-compliant manner, or if a key upon which it depends is changed. BankObject PersonObject Automatically notifies person Person can react accordingly in customized method [bankInstance setAccountBalance:50]; “Registering Dependent Keys” (page 15) explains how to specify that the value of a key is dependent on the value of another key. KVO’s primary benefit is that you don’t have to implement your own scheme to send notifications every time a property changes. Its well-defined infrastructure has framework-level support that makes it easy to adopt—typically you do not have to add any code to your project. In addition, the infrastructure is already full-featured, which makes it easy to support multiple observers for a single property, as well as dependent values. “KVO Compliance” (page 11) describes the difference between automatic and manual key-value observing, and how to implement both. Unlike notifications that use NSNotificationCenter, there is no central object that provides change notification for all observers. Instead, notifications are sent directly to the observing objects when changes are made. NSObject provides this base implementation of key-value observing, and you should rarely need to override these methods. “Key-Value Observing Implementation Details ” (page 19) describes how key-value observing is implemented. Introduction to Key-Value Observing Programming Guide At a Glance 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 6In order to receive key-value observing notifications for a property, three things are required: ● The observed class must be key-value observing compliant for the property that you wish to observe. ● You must register the observing object with the observed object, using the method addObserver:forKeyPath:options:context:. ● The observing class must implement observeValueForKeyPath:ofObject:change:context:. Important: Not all classes are KVO-compliant for all properties. You can ensure your own classes are KVO-compliant by following the steps described in “KVO Compliance” (page 11). Typically properties in Apple-supplied frameworks are only KVO-compliant if they are documented as such. Registering as an Observer In order to be notified of changes to a property, an observing object must first register with the object to be observed by sending it an addObserver:forKeyPath:options:context: message, passing the observer object and the key path of the property to be observed. The options parameter specifies the information that is provided to the observer when a change notification is sent. Using the option NSKeyValueObservingOptionOld specifies that the original object value is provided to the observer as an entry in the change dictionary. Specifying the NSKeyValueObservingOptionNew option provides the new value as an entry in the change dictionary. To receive both values, you would bitwise OR the option constants. The example in Listing 1 demonstrates registering an inspector object for the property openingBalance. Listing 1 Registering the inspector as an observer of the openingBalance property - (void)registerAsObserver { /* Register 'inspector' to receive change notifications for the "openingBalance" property of the 'account' object and specify that both the old and new values of "openingBalance" should be provided in the observe… method. 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 7 Registering for Key-Value Observing*/ [account addObserver:inspector forKeyPath:@"openingBalance" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) context:NULL]; } When you register an object as an observer, you can also provide a context pointer. The context pointer is provided to the observer when observeValueForKeyPath:ofObject:change:context: is invoked. The context pointer can be a C pointer or an object reference. The context pointer can be used as a unique identifier to determine the change that is being observed, or to provide some other data to the observer. Note: The key-value observing addObserver:forKeyPath:options:context: method does not maintain strong references to the observing object, the observed objects, or the context. You should ensure that you maintain strong references to the observing, and observed, objects, and the context as necessary. Receiving Notification of a Change When the value of an observed property of an object changes, the observer receives an observeValueForKeyPath:ofObject:change:context: message. All observers must implement this method. The observer is provided the object and key path that triggered the observer notification, a dictionary containing details about the change, and the context pointer that was provided when the observer was registered. The change dictionary entry NSKeyValueChangeKindKey provides information about the type of change that occurred. If the value of the observed object has changed, the NSKeyValueChangeKindKey entry returns NSKeyValueChangeSetting. Depending on the options specified when the observer was registered, the NSKeyValueChangeOldKey and NSKeyValueChangeNewKey entries in the change dictionary contain the values of the property before, and after, the change. If the property is an object, the value is provided directly. If the property is a scalar or a C structure, the value is wrapped in an NSValue object (as with key-value coding). Registering for Key-Value Observing Receiving Notification of a Change 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 8If the observed property is a to-many relationship, the NSKeyValueChangeKindKey entry also indicates whether objects in the relationship were inserted, removed, or replaced by returning NSKeyValueChangeInsertion, NSKeyValueChangeRemoval, or NSKeyValueChangeReplacement, respectively. The change dictionary entry for NSKeyValueChangeIndexesKey is an NSIndexSet object specifying the indexes in the relationship that changed. If NSKeyValueObservingOptionNew or NSKeyValueObservingOptionOld are specified as options when the observer is registered, the NSKeyValueChangeOldKey and NSKeyValueChangeNewKey entries in the change dictionary are arrays containing the values of the related objects before, and after, the change. The example in Listing 2 shows the observeValueForKeyPath:ofObject:change:context: implementation for an inspector that reflects the old and new values of the property openingBalance, as registered in Listing 1 (page 7). Listing 2 Implementation of observeValueForKeyPath:ofObject:change:context: - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if ([keyPath isEqual:@"openingBalance"]) { [openingBalanceInspectorField setObjectValue: [change objectForKey:NSKeyValueChangeNewKey]]; } /* Be sure to call the superclass's implementation *if it implements it*. NSObject does not implement the method. */ [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } Registering for Key-Value Observing Receiving Notification of a Change 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 9Removing an Object as an Observer You remove a key-value observer by sending the observed object a removeObserver:forKeyPath: message, specifying the observing object and the key path. The example in Listing 3 removesthe inspector as an observer of openingBalance. Listing 3 Removing the inspector as an observer of openingBalance - (void)unregisterForChangeNotification { [observedObject removeObserver:inspector forKeyPath:@"openingBalance"]; } If the context is an object, you must keep a strong reference to it until removing the observer. After receiving a removeObserver:forKeyPath: message, the observing object will no longer receive any observeValueForKeyPath:ofObject:change:context: messagesfor the specified key path and object. Registering for Key-Value Observing Removing an Object as an Observer 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 10In order to be considered KVO-compliant for a specific property, a class must ensure the following: ● The class must be key-value coding compliant for the property, as specified in “Ensuring KVC Compliance”. KVO supports the same data types as KVC. ● The class emits KVO change notifications for the property. ● Dependent keys are registered appropriately (see “Registering Dependent Keys” (page 15)). There are two techniques for ensuring the change notifications are emitted. Automatic support is provided by NSObject and is by default available for all properties of a class that are key-value coding compliant. Typically, if you follow standard Cocoa coding and naming conventions, you can use automatic change notifications—you don’t have to write any additional code. Manual change notification provides additional control over when notifications are emitted, and requires additional coding. You can control automatic notifications for properties of your subclass by implementing the class method automaticallyNotifiesObserversForKey:. Automatic Change Notification NSObject provides a basic implementation of automatic key-value change notification. Automatic key-value change notification informs observers of changes made using key-value compliant accessors, as well as the key-value coding methods. Automatic notification is also supported by the collection proxy objects returned by, for example, mutableArrayValueForKey:. The examples shown in Listing 1 result in any observers of the property name to be notified of the change. Listing 1 Examples of method calls that cause KVO change notifications to be emitted // Call the accessor method. [account setName:@"Savings"]; // Use setValue:forKey:. [account setValue:@"Savings" forKey:@"name"]; 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 11 KVO Compliance// Use a key path, where 'account' is a kvc-compliant property of 'document'. [document setValue:@"Savings" forKeyPath:@"account.name"]; // Use mutableArrayValueForKey: to retrieve a relationship proxy object. Transaction *newTransaction = <#Create a new transaction for the account#>; NSMutableArray *transactions = [account mutableArrayValueForKey:@"transactions"]; [transactions addObject:newTransaction]; Manual Change Notification Manual change notification provides more granular control over how and when notifications are sent to observers. This can be useful to help minimize triggering notifications that are unnecessary, or to group a number of changes into a single notification. A class that implements manual notification must override the NSObject implementation of automaticallyNotifiesObserversForKey:. It is possible to use both automatic and manual observer notifications in the same class. For properties that perform manual notification, the subclass implementation of automaticallyNotifiesObserversForKey: should return NO. A subclassimplementation should invoke super for any unrecognized keys. The example in Listing 2 enables manual notification for the openingBalance property allowing the superclass to determine the notification for all other keys. Listing 2 Example implementation of automaticallyNotifiesObserversForKey: + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)theKey { BOOL automatic = NO; if ([theKey isEqualToString:@"openingBalance"]) { automatic = NO; } else { automatic = [super automaticallyNotifiesObserversForKey:theKey]; } return automatic; } KVO Compliance Manual Change Notification 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 12To implement manual observer notification, you invoke willChangeValueForKey: before changing the value, and didChangeValueForKey: after changing the value. The example in Listing 3 implements manual notifications for the openingBalance property. Listing 3 Example accessor method implementing manual notification - (void)setOpeningBalance:(double)theBalance { [self willChangeValueForKey:@"openingBalance"]; _openingBalance = theBalance; [self didChangeValueForKey:@"openingBalance"]; } You can minimize sending unnecessary notifications by first checking if the value has changed. The example in Listing 4 tests the value of openingBalance and only provides the notification if it has changed. Listing 4 Testing the value for change before providing notification - (void)setOpeningBalance:(double)theBalance { if (theBalance != _openingBalance) { [self willChangeValueForKey:@"openingBalance"]; _openingBalance = theBalance; [self didChangeValueForKey:@"openingBalance"]; } } If a single operation causes multiple keysto change you must nest the change notifications asshown in Listing 5. Listing 5 Nesting change notifications for multiple keys - (void)setOpeningBalance:(double)theBalance { [self willChangeValueForKey:@"openingBalance"]; [self willChangeValueForKey:@"itemChanged"]; _openingBalance = theBalance; _itemChanged = _itemChanged+1; [self didChangeValueForKey:@"itemChanged"]; [self didChangeValueForKey:@"openingBalance"]; } KVO Compliance Manual Change Notification 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 13In the case of an ordered to-many relationship, you must specify not only the key that changed, but also the type of change and the indexes of the objects involved. The type of change is an NSKeyValueChange that specifies NSKeyValueChangeInsertion, NSKeyValueChangeRemoval, or NSKeyValueChangeReplacement. The indexes of the affected objects are passed as an NSIndexSet object. The code fragment in Listing 6 demonstrates how to wrap a deletion of objects in the to-many relationship transactions. Listing 6 Implementation of manual observer notification in a to-many relationship - (void)removeTransactionsAtIndexes:(NSIndexSet *)indexes { [self willChange:NSKeyValueChangeRemoval valuesAtIndexes:indexes forKey:@"transactions"]; // Remove the transaction objects at the specified indexes. [self didChange:NSKeyValueChangeRemoval valuesAtIndexes:indexes forKey:@"transactions"]; } KVO Compliance Manual Change Notification 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 14There are many situations in which the value of one property depends on that of one or more other attributes in another object. If the value of one attribute changes, then the value of the derived property should also be flagged for change. How you ensure that key-value observing notifications are posted for these dependent properties depends on the cardinality of the relationship. To-one Relationships To trigger notifications automatically for a to-on relationship you should either override keyPathsForValuesAffectingValueForKey: or implement a suitable method that follows the pattern it defines for registering dependent keys. For example, the full name of a person is dependent on both the first and last names. A method that returns the full name could be written as follows: - (NSString *)fullName { return [NSString stringWithFormat:@"%@ %@",firstName, lastName]; } An application observing the fullName property must be notified when either the firstName or lastName properties change, as they affect the value of the property. One solution is to override keyPathsForValuesAffectingValueForKey: specifying that the fullName property of a person is dependent on the lastName and firstName properties. Listing 1 (page 15) shows an example implementation of such a dependency: Listing 1 Example implementation of keyPathsForValuesAffectingValueForKey: + (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key { NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key]; if ([key isEqualToString:@"fullName"]) { 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 15 Registering Dependent KeysNSArray *affectingKeys = @[@"lastName", @"firstName"]; keyPaths = [keyPaths setByAddingObjectsFromArray:affectingKeys]; } return keyPaths; } Your override should typically invoke super and return a set that includes any members in the set that result from doing that (so as not to interfere with overrides of this method in superclasses). You can also achieve the same result by implementing a class method that follows the naming convention keyPathsForValuesAffecting, where is the name of the attribute (first letter capitalized) that is dependent on the values. Using this pattern the code in Listing 1 (page 15) could be rewritten as a class method named keyPathsForValuesAffectingFullName as shown in Listing 2 (page 16). Listing 2 Example implementation of the keyPathsForValuesAffecting naming convention + (NSSet *)keyPathsForValuesAffectingFullName { return [NSSet setWithObjects:@"lastName", @"firstName", nil]; } You can't override the keyPathsForValuesAffectingValueForKey: method when you add a computed property to an existing class using a category, because you're not supposed to override methods in categories. In that case, implement a matching keyPathsForValuesAffecting class method to take advantage of this mechanism. Note: You cannot set up dependencies on to-many relationships by implementing keyPathsForValuesAffectingValueForKey:. Instead, you must observe the appropriate attribute of each of the objects in the to-many collection and respond to changes in their values by updating the dependent key yourself. The following section shows a strategy for dealing with this situation. To-many Relationships The keyPathsForValuesAffectingValueForKey: method does not support key-paths that include a to-many relationship. For example, suppose you have a Department object with a to-many relationship (employees) to a Employee, and Employee has a salary attribute. You might want the Department object have Registering Dependent Keys To-many Relationships 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 16a totalSalary attribute that is dependent upon the salaries of all the Employees in the relationship. You can not do this with, for example, keyPathsForValuesAffectingTotalSalary and returning employees.salary as a key. There are two possible solutions in both situations: 1. You can use key-value observing to register the parent (in this example, Department) as an observer of the relevant attribute of all the children (Employeesin this example). You must add and remove the parent as an observer as child objects are added to and removed from the relationship (see “Registering for Key-Value Observing” (page 7)). In the observeValueForKeyPath:ofObject:change:context: method you update the dependent value in response to changes, as illustrated in the following code fragment: - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if (context == totalSalaryContext) { [self updateTotalSalary]; } else // deal with other observations and/or invoke super... } - (void)updateTotalSalary { [self setTotalSalary:[self valueForKeyPath:@"employees.@sum.salary"]]; } - (void)setTotalSalary:(NSNumber *)newTotalSalary { if (totalSalary != newTotalSalary) { [self willChangeValueForKey:@"totalSalary"]; _totalSalary = newTotalSalary; [self didChangeValueForKey:@"totalSalary"]; } } - (NSNumber *)totalSalary { return _totalSalary; Registering Dependent Keys To-many Relationships 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 17} 2. If you're using Core Data, you can register the parent with the application's notification center as an observer of its managed object context. The parentshould respond to relevant change notifications posted by the children in a manner similar to that for key-value observing. Registering Dependent Keys To-many Relationships 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 18Automatic key-value observing is implemented using a technique called isa-swizzling. The isa pointer, as the name suggests, points to the object's class which maintains a dispatch table. This dispatch table essentially contains pointers to the methods the class implements, among other data. When an observer is registered for an attribute of an object the isa pointer of the observed object is modified, pointing to an intermediate class rather than at the true class. As a result the value of the isa pointer does not necessarily reflect the actual class of the instance. You should never rely on the isa pointer to determine class membership. Instead, you should use the class method to determine the class of an object instance. 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 19 Key-Value Observing Implementation DetailsThis table describes the changes to Key-Value Observing Programming Guide . Date Notes 2012-07-17 Updated to use new Objective-C features. ARCification 2011-03-08 Clarified terminology in "Registering Dependent Keys." 2009-08-14 Added links to some key Cocoa definitions. 2009-05-09 Corrected minor typo. 2009-05-06 Clarified Core Data requirement in Registering Dependent Keys. 2009-03-04 Updated Registering Dependent Keys chapter. 2006-06-28 Updated code examples. Clarified that you should not release objects before calling willChangeValueForKey: methods. Noted that Java is not supported. 2005-07-07 2004-08-31 Corrected minor typos. Clarified the need to nest manual key-value change notifications. 2004-03-20 Modified source example in “Registering Dependent Keys” (page 15). Corrected source example in “Registering for Key-Value Observing” (page 7). Added article “Key-Value Observing Implementation Details ” (page 19). 2004-02-22 2003-10-15 Initial publication of Key-Value Observing. 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 20 Document Revision HistoryApple Inc. © 2003, 2012 Apple Inc. All rights reserved. No part of this publication may be reproduced, stored in a retrievalsystem, or transmitted, in any form or by any means, mechanical, electronic, photocopying, recording, or otherwise, without prior written permission of Apple Inc., with the following exceptions: Any person is hereby authorized to store documentation on a single computer for personal use only and to print copies of documentation for personal use provided that the documentation contains Apple’s copyright notice. No licenses, express or implied, are granted with respect to any of the technology described in this document. Apple retains all intellectual property rights associated with the technology described in this document. This document is intended to assist application developers to develop applications only for Apple-labeled computers. Apple Inc. 1 Infinite Loop Cupertino, CA 95014 408-996-1010 Apple, the Apple logo, Cocoa, Mac, and Objective-C are trademarks of Apple Inc., registered in the U.S. and other countries. Java is a registered trademark of Oracle and/or its affiliates. Even though Apple has reviewed this document, APPLE MAKES NO WARRANTY OR REPRESENTATION, EITHER EXPRESS OR IMPLIED, WITH RESPECT TO THIS DOCUMENT, ITS QUALITY, ACCURACY, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.ASARESULT, THISDOCUMENT IS PROVIDED “AS IS,” AND YOU, THE READER, ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND ACCURACY. IN NO EVENT WILL APPLE BE LIABLE FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL,OR CONSEQUENTIAL DAMAGES RESULTING FROM ANY DEFECT OR INACCURACY IN THIS DOCUMENT, even if advised of the possibility of such damages. THE WARRANTY AND REMEDIES SET FORTH ABOVE ARE EXCLUSIVE AND IN LIEU OF ALL OTHERS, ORAL OR WRITTEN, EXPRESS OR IMPLIED. No Apple dealer, agent, or employee is authorized to make any modification, extension, or addition to this warranty. Some states do not allow the exclusion or limitation of implied warranties or liability for incidental or consequential damages, so the above limitation or exclusion may not apply to you. This warranty gives you specific legal rights, and you may also have other rights which vary from state to state. Location Awareness Programming GuideContents Making Your App Location-Aware 7 At a Glance 8 Location Services Provide a Geographical Context for Apps 8 Heading Information Indicates the User’s Current Orientation 8 Maps Support Navigation and the Display of Geographically Relevant Content 8 Routing Apps Provide Directions to the User 9 How to Use This Document 9 See Also 9 Getting the User’s Location 10 Requiring the Presence of Location Services in Order to Run 10 Getting the User’s Current Location 11 Determining Whether Location Services Are Available 11 Starting the Standard Location Service 12 Starting the Significant-Change Location Service 13 Receiving Location Data from a Service 14 Monitoring Shape-Based Regions 15 Determining the Availability of Region Monitoring 15 Defining a Region to Be Monitored 16 Handling Boundary-Crossing Events for a Region 17 Testing Your App’s Region Monitoring Support 18 Getting Location Events in the Background 18 Tips for Conserving Battery Power 18 Getting Direction-Related Events 20 Adding a Requirement for Direction-Related Events 20 Getting Heading-Related Events 21 Getting Course Information While the User Is Moving 23 Geocoding Location Data 24 About Geocoder Objects 24 Converting Coordinates Into Place Name Information 25 Getting Placemark Information using CLGeocoder 25 Getting Placemark Information from the Reverse Geocoder 26 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 2Converting Place Names Into Coordinates 29 Displaying Maps 30 Understanding Map Geometry 30 Map Coordinate Systems 31 Converting Between Coordinate Systems 32 Adding a Map View to Your User Interface 33 Configuring the Properties of a Map 34 Setting the Visible Portion of the Map 34 Zooming and Panning the Map Content 34 Displaying the User’s Current Location on the Map 35 Responding to User Interactions with a Map 36 Annotating Maps 37 Adding Annotations to a Map 38 Checklist for Adding an Annotation to the Map 39 Defining a Custom Annotation Object 40 Using the Standard Annotation Views 41 Defining a Custom Annotation View 42 Creating Annotation Views from Your Delegate Object 44 Managing the Map’s Annotation Objects 46 Marking Your Annotation View as Draggable 46 Displaying Overlays on a Map 47 Checklist for Adding an Overlay to the Map 49 Using the Standard Overlay Objects and Views 50 Defining a Custom Overlay Object 51 Defining a Custom Overlay View 52 Creating Overlay Views from Your Delegate Object 55 Managing the Map’s Overlay Objects 56 Using Overlays as Annotations 56 Providing Directions 58 Asking the Maps App to Display Directions 58 Registering as a Routing App 58 Configuring Your App to Accept Direction Requests 59 Declaring the Supported Geographic Coverage for Directions 60 Handling Direction Requests 62 Legacy Map Techniques 64 Creating Draggable Annotations in Earlier Versions of iOS 64 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 3 ContentsDocument Revision History 69 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 4 ContentsFigures, Tables, and Listings Getting the User’s Location 10 Listing 1-1 Starting the standard location service 12 Listing 1-2 Starting the significant-change location service 13 Listing 1-3 Processing an incoming location event 14 Listing 1-4 Creating and registering a region based on a Map Kit overlay 16 Getting Direction-Related Events 20 Listing 2-1 Initiating the delivery of heading events 21 Listing 2-2 Processing heading events 22 Geocoding Location Data 24 Listing 3-1 Geocoding a location using CLGeocoder 25 Listing 3-2 Geocoding a location using MKReverseGeocoder 27 Displaying Maps 30 Figure 4-1 Mapping spherical data to a flat surface 31 Table 4-1 Map coordinate system conversion routines 32 Annotating Maps 37 Figure 5-1 Displaying an annotation in a map 38 Figure 5-2 Displaying an overlay on a map 48 Figure 5-3 Using a custom overlay view to draw 55 Listing 5-1 Creating a simple annotation object 40 Listing 5-2 Implementing the MyCustomAnnotation class 41 Listing 5-3 Creating a standard annotation view 42 Listing 5-4 Declaring a custom annotation view 42 Listing 5-5 Initializing a custom annotation view 43 Listing 5-6 Creating annotation views 44 Listing 5-7 Creating a polygon overlay object 50 Listing 5-8 Creating a polygon view for rendering a shape 51 Listing 5-9 Drawing a gradient in a custom overlay view 53 Providing Directions 58 Table 6-1 Keys and values for the directions request document type 59 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 5Listing 6-1 A sample GeoJSON file 61 Listing 6-2 Handling a directions request URL 63 Legacy Map Techniques 64 Listing A-1 The BullseyeAnnotationView class 64 Listing A-2 Tracking the view’s location 66 Listing A-3 Handling the final touch events 67 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 6 Figures, Tables, and ListingsUsing location-based information in your apps is a way to keep the user connected to the surrounding world. Whether you use thisinformation for practical purposes(such as navigation) or for entertainment, location-based information can improve the overall user experience. Location-based information in iOS comprises two pieces: location services and maps. Location services are provided by the Core Location framework, which provides Objective-C interfaces for obtaining information about the user’s location and heading. Maps are provided by the Map Kit framework, which supports both the display and annotation of maps similar to those found in the Maps app. 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 7 Making Your App Location-AwareAt a Glance Map and location services provide a way for you to enhance user interactions. By incorporating geographic data into your apps, you can orient the user to the surrounding environment or help the user stay connected to other people nearby. Location Services Provide a Geographical Context for Apps Location services is all about mobility and the fact that your app is running on a device that can go anywhere. Knowing the user’s geographic location can help you improve the quality of the information you offer, and in some cases it might even be at the heart of your app. Apps that offer navigation features use location services to monitor the user’s position and generate updates. And many other types of apps use location as a way of connecting nearby users socially. Relevant Chapters: “Getting the User’s Location” (page 10), “Geocoding Location Data” (page 24) Heading Information Indicates the User’s Current Orientation Heading services complement the basic location services by providing more precise information about which way a device is pointed. The most obvious use for this technology is for implementing a compass but this technology is also used to support augmented reality, games, and navigational apps. And even on devices that do not have a magnetometer—the hardware used to get precise heading information—information about the user’s course and speed are still available for apps that need it. Relevant Chapters: “Getting Direction-Related Events” (page 20) Maps Support Navigation and the Display of Geographically Relevant Content Maps are a way to visualize geographical data in a way that is easy to understand. The Map Kit framework provides standard views that you can incorporate into your app and use to display information tied to specific geographic points. In addition, this framework provides the means to layer custom information on top of the map and have it scroll along with the rest of the map content. Making Your App Location-Aware At a Glance 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 8Relevant Chapters: “Displaying Maps” (page 30), “Annotating Maps” (page 37) Routing Apps Provide Directions to the User A routing app is an app that is able to receive coordinates from the Maps app and use those coordinates to provide point-to-point directions to the user. Apps that provide navigation capabilities can declare themselves as a routing app with minimal additional effort. In addition to driving and walking directions, routing apps can support many other modes of transport, including taxi, airplane, and many public transportation options. Relevant Chapters: “Providing Directions” (page 58) How to Use This Document You do not have to read this entire document to use each of the technologies. The services provided by the Core Location and Map Kit frameworks are separate and can be used independent of other services. Therefore, the beginning of each chapter introduces the terminology and information you need to understand the corresponding technology followed by examples and task-related steps on how to use it. The only exception is the “Annotating Maps” (page 37) chapter, which builds on the information presented in the “Displaying Maps” (page 30) chapter. See Also For information about the classes of the Core Location framework, see Core Location Framework Reference . For information about the classes of the Map Kit framework, see Map Kit Framework Reference . Making Your App Location-Aware How to Use This Document 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 9Apps use location data for a wide variety of purposes, ranging from social networking to turn-by-turn navigation services. They get location data by using the classes of the Core Location framework. This framework provides several services that you can use to get and monitor the device’s current location: ● The significant-change location service provides a low-power way to get the current location and be notified of changes to that location. (iOS 4.0 and later). ● The standard location service offers a more configurable way to get the current location. ● Region monitoring lets you monitor boundary crossings for a defined area. (iOS 4.0 and later). To use the features of the Core Location framework, you must link your app to CoreLocation.framework in your Xcode project. To access the classes and headers of the framework, include an #import statement at the top of any relevant source files. For general information about the classes of the Core Location framework, see Core Location Framework Reference . Requiring the Presence of Location Services in Order to Run If your app relies on location services to function properly, you should include the UIRequiredDeviceCapabilities key in the app’s Info.plist file. You use this key to specify the location services that must be present in order for your app to run. The App Store uses the information in this key from preventing users from downloading apps to devices that do not contain the listed features. The value for the UIRequiredDeviceCapabilities is an array of strings indicating the features that your app requires. There are two strings relevant to location services: ● Include the location-services string if you require location services in general. ● Include the gps string if your app requires the accuracy offered only by GPS hardware. 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 10 Getting the User’s LocationImportant: If your app uses location services but is able to operate successfully without them, do not include the corresponding strings in the UIRequiredDeviceCapabilities key. For more information about the UIRequiredDeviceCapabilities key, see Information Property List Key Reference . Getting the User’s Current Location The Core Location framework lets you locate the current position of the device and use that information in your app. The framework uses information obtained from the built-in cellular, Wi-Fi, or GPS hardware to triangulate a location fix for the device. It reports that location to your code and, depending on how you configure the service, also provides periodic updates as it receives new or improved data. There are two different services you can use to get the user’s current location: ● The standard location service is a configurable, general-purpose solution and is supported in all versions of iOS. ● The significant-change location service offers a low-power location service for devices with cellular radios. This service is available only in iOS 4.0 and later and can also wake up an app that is suspended or not running. Gathering location data is a power-intensive operation. It involves powering up the onboard radios and querying the available cell towers, Wi-Fi hotspots, or GPS satellites, which can take severalseconds. Leaving the standard location service running for extended periods can drain the device’s battery. (The significant-change location service drastically reduces battery drain by monitoring only cell tower changes, but the service works only on devices with cellular radios.) For most apps, it is usually sufficient to establish an initial position fix and then acquire updates only periodically after that. If you are sure you need regular position updates, you should use the significant-change location service where you can; otherwise, you should configure the parameters of the standard location service in a way that minimizes its impact on battery life. Determining Whether Location Services Are Available Every iOS-based device is capable of supporting location services in some form but there are still situations where location services may not be available: ● The user can disable location services in the Settings app. ● The user can deny location services for a specific app. ● The device might be in Airplane mode and unable to power up the necessary hardware. Getting the User’s Location Getting the User’s Current Location 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 11For these reasons, it is recommended that you always call the locationServicesEnabled class method of CLLocationManager before attempting to start either the standard or significant-change location services. (In iOS 3.x and earlier, check the value of the locationServicesEnabled property instead.) If this class method returns YES, you can start location services as planned. If it returns NO and you attempt to start location services anyway, the system promptsthe user to confirm whether location servicesshould be reenabled. Given that location services are very likely to be disabled on purpose, the user might not welcome this prompt. Starting the Standard Location Service The standard location service is the most common way to get the user’s current location because it is available on all devices and in all versions of iOS. Before using this service, you configure it by specifying the desired accuracy of the location data and the distance that must be traveled before reporting a new location. When you start the service, it uses the specified parameters to determine which radios to enable and then proceeds to report location events to your app. To use the standard location service, create an instance of the CLLocationManager class and configure its desiredAccuracy and distanceFilter properties. To begin receiving location notifications, assign a delegate to the object and call the startUpdatingLocation method. As location data becomes available, the location manager notifies its assigned delegate object. If a location update has already been delivered, you can also get the most recent location data directly from the CLLocationManager object without waiting for a new event to be delivered. Listing 1-1 shows a sample method that configures a location manager for use. This method is part of a class that caches its location manager object in a member variable for later use. (The class also conforms to the CLLocationManagerDelegate protocol and so acts as the delegate for the location manager.) Because the app does not need precise location data, it configures the location service to report the general area of the user and notify it only when the user moves a significant distance, which in this case is half a kilometer. Listing 1-1 Starting the standard location service - (void)startStandardUpdates { // Create the location manager if this object does not // already have one. if (nil == locationManager) locationManager = [[CLLocationManager alloc] init]; locationManager.delegate = self; locationManager.desiredAccuracy = kCLLocationAccuracyKilometer; Getting the User’s Location Getting the User’s Current Location 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 12// Set a movement threshold for new events. locationManager.distanceFilter = 500; [locationManager startUpdatingLocation]; } The code for receiving location updates from this service is shown in “Receiving Location Data from a Service” (page 14). Starting the Significant-Change Location Service In iOS 4.0 and later, you can use the significant-change location service to receive location events. This service offers a significant powersavings and provides accuracy that is good enough for most apps. It usesthe device’s cellular radio to determine the user’s location and report changes in that location, allowing the system to manage power usage much more aggressively than it could otherwise. This service is also capable of waking up an app that is currently suspended or not running in order to deliver new location data. To use the significant-change location service, create an instance of the CLLocationManager class, assign a delegate to it, and call the startMonitoringSignificantLocationChanges method as shown in Listing 1-2. Aslocation data becomes available, the location manager notifiesits assigned delegate object. If a location update has already been delivered, you can also get the most recent location data directly from the CLLocationManager object without waiting for a new event to be delivered. Listing 1-2 Starting the significant-change location service - (void)startSignificantChangeUpdates { // Create the location manager if this object does not // already have one. if (nil == locationManager) locationManager = [[CLLocationManager alloc] init]; locationManager.delegate = self; [locationManager startMonitoringSignificantLocationChanges]; } Getting the User’s Location Getting the User’s Current Location 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 13As with the standard location service, location data is delivered to the delegate object as described in “Receiving Location Data from a Service” (page 14). If you leave thisservice running and your app issubsequently suspended or terminated, the service automatically wakes up your app when new location data arrives. At wake-up time, your app is put into the background and given a small amount of time to process the location data. Because your app is in the background, it should do minimal work and avoid any tasks (such as querying the network) that might prevent it from returning before the allocated time expires. If it does not, your app may be terminated. Receiving Location Data from a Service Whether you use the standard location service or the significant-change location service to get location events, the way you receive those events is the same. In iOS 6 and later, the location manager reports events to the locationManager:didUpdateLocations: method of its delegate when they become available. (In earlier versions of the system, it reports eventsto the locationManager:didUpdateToLocation:fromLocation: method.) If there is an error retrieving an event, the location manager calls the locationManager:didFailWithError: method of its delegate instead. Listing 1-3 shows the delegate method for receiving location events. Because the location manager object sometimes returns cached events, it is recommended that you check the timestamp of any location events you receive. (It can take several seconds to obtain a rough location fix, so the old data simply serves as a way to reflect the last known location.) In this example, the method throws away any events that are more than fifteen seconds old under the assumption that fairly recent events are likely to be good enough. If you were implementing a navigation app, you might want to lower the threshold. Listing 1-3 Processing an incoming location event // Delegate method from the CLLocationManagerDelegate protocol. - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations { // If it's a relatively recent event, turn off updates to save power CLLocation* location = [locations lastObject]; NSDate* eventDate = location.timestamp; NSTimeInterval howRecent = [eventDate timeIntervalSinceNow]; if (abs(howRecent) < 15.0) { // If the event is recent, do something with it. NSLog(@"latitude %+.6f, longitude %+.6f\n", location.coordinate.latitude, location.coordinate.longitude); Getting the User’s Location Getting the User’s Current Location 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 14} } In addition to a location object’s timestamp, you can also use the accuracy reported by that object as a means of determining whether you want to accept an event. As it receives more accurate data, the location service may return additional events, with the accuracy values reflecting the improvements accordingly. Throwing away less accurate events means your app wastes less time on events that cannot be used effectively anyway. Monitoring Shape-Based Regions Apps can use region monitoring to be notified when the user crosses geographic boundaries. You can use this capability to generate alerts when the user gets close to a specific location. For example, upon approaching a specific dry cleaners, an app could notify the user to pick up any clothes that had been dropped off and are now ready. In iOS, regions associated with your app are tracked at all times, including when your app is not running. If a region boundary is crossed while an app is not running, that app is relaunched into the background to handle the event. Similarly, if the app is suspended when the event occurs, it is woken up and given a short amount of time to handle the event. Determining the Availability of Region Monitoring Before attempting to monitor any regions, your app should check to see if region monitoring is supported on the current device. There are several reasons why region monitoring might not be available: ● The device may not have the hardware needed to support region monitoring. ● The user may have disabled location services in the Settings app. ● The device might be in Airplane mode and unable to power up the necessary hardware. For these reasons, it is recommended that you always call the regionMonitoringAvailable and regionMonitoringEnabled class methods of CLLocationManager before attempting to monitor regions. The regionMonitoringAvailable method lets you know whether the underlying hardware supportsregion monitoring. If it returns NO, there is no chance that your app will ever be able to use region monitoring on the device. If region monitoring is available, the regionMonitoringEnabled method reports whether the feature is currently enabled. If region monitoring is available but not enabled when you attempt to monitor a region, the system promptsthe user to confirm whether region monitoring should be reenabled. Given that the feature is likely to be disabled on purpose, the user might not welcome this prompt. Getting the User’s Location Monitoring Shape-Based Regions 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 15Defining a Region to Be Monitored To begin monitoring a region, you must define the region and register it with the system. Regions are defined using the CLRegion class, which currently supports the creation of circular regions. Each region you create must include both the data that definesthe desired geographic area and a unique identifierstring. (The identifier string is required and is the only guaranteed way for your app to identify regions later.) To register a region, you call the startMonitoringForRegion:desiredAccuracy: method of your CLLocationManager object. Listing 1-4 shows a sample method that creates a new region based on a circular Map Kit overlay. The overlay’s center point and radius form the boundary for the region, although if the radius is too large to be monitored, it is reduced automatically. After registering the region, the region object itself can be released. Core Location stores the data associated with a region but does not typically store the region object itself. Listing 1-4 Creating and registering a region based on a Map Kit overlay - (BOOL)registerRegionWithCircularOverlay:(MyCircle*)overlay andIdentifier:(NSString*)identifier { // Do not create regions if support is unavailable or disabled. if ( ![CLLocationManager regionMonitoringAvailable] || ![CLLocationManager regionMonitoringEnabled] ) return NO; // If the radius is too large, registration fails automatically, // so clamp the radius to the max value. CLLocationDegrees radius = overlay.radius; if (radius > self.locManager.maximumRegionMonitoringDistance) radius = self.locManager.maximumRegionMonitoringDistance; // Create the region and start monitoring it. CLRegion* region = [[CLRegion alloc] initCircularRegionWithCenter:overlay.coordinate radius:radius identifier:identifier]; [self.locManager startMonitoringForRegion:region desiredAccuracy:kCLLocationAccuracyHundredMeters]; [region release]; Getting the User’s Location Monitoring Shape-Based Regions 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 16return YES; } Monitoring of a region begins immediately after registration. However, do not expect to receive an event right away. Only boundary crossings can generate an event. Thus, if at registration time the user’s location is already inside the region, the location manager does not generate an event. Instead, you must wait for the user to cross the region boundary before an event is generated and sent to the delegate. You should always be judicious when specifying the set of regions to monitor. Regions are a shared system resource and the total number of regions available systemwide is limited. For this reason, Core Location limits the number of regions that may be simultaneously monitored by a single app. To work around these limits, you should consider registering only those regions in the user’s immediate vicinity. As the user’s location changes, you can remove regions that are now farther way and add regions coming up on the user’s path. If you attempt to register a region and space is unavailable, the location manager calls the locationManager:monitoringDidFailForRegion:withError: method of its delegate with the kCLErrorRegionMonitoringFailure error code. Handling Boundary-Crossing Events for a Region Every time the user’s current location crosses a boundary region, the system generates an appropriate region event for your app. If your app is already running, these events go directly to the delegates of any current location manager objects. If your app is not running, the system launches it in the background so that it can respond. Apps can implement the following methods to handle boundary crossings: ● locationManager:didEnterRegion: ● locationManager:didExitRegion: The system does not report boundary crossings until the boundary plus a designated cushion distance is exceeded. You specify the desired cushion distance for a region when you register it using the startMonitoringForRegion:desiredAccuracy: method. This cushion value prevents the system from generating numerous entered and exited events in quick succession while the user is traveling close the edge of the boundary. When a region boundary is crossed, the most likely response is to alert the user of the proximity to the target item. If your app is running in the background, you can use local notifications to alert the user; otherwise, you can simply post an alert. Getting the User’s Location Monitoring Shape-Based Regions 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 17Testing Your App’s Region Monitoring Support When testing your region monitoring code in iOS Simulator or on a device, realize that region events may not happen immediately after a region boundary is crossed. To prevent spurious notifications, iOS does not deliver region notifications until certain threshold conditions are met. Specifically, the user’s location must cross the region boundary and move away from that boundary by a minimum distance and remain at that minimum distance for at least 20 seconds before the notifications are reported. The specific threshold distances are determined by the hardware and the location technologiesthat are currently available. For example, if Wi-Fi is disabled, region monitoring is significantly less accurate. However, for testing purposes, you can assume that the minimum distance is approximately 200 meters. Getting Location Events in the Background If your app needs location updates delivered whether the app is in the foreground or background, there are multiple options for doing so. The preferred option is to use the significant location change service to wake your app at appropriate times to handle new events. However, if your app needs to use the standard location service, you can declare your app as needing background location services. An app should request background location services only if the absence of those services would impair its ability to operate. In addition, any app that requests background location services should use those services to provide a tangible benefit to the user. For example, a turn-by-turn navigation app would be a likely candidate for background location services because of its need to track the user’s position and report when it is time to make the next turn. The process for configuring a background location app is described in “App States and Multitasking” in iOS App Programming Guide . Tips for Conserving Battery Power Receiving and transmitting data using the radios of an iOS-based device require more power than any other operation on the device. Because Core Location relies on these radios to determine the user’s location, you should use location services judiciously in your apps. Most apps do not need location services to be running all the time, and so turning off those services is the simplest way to save power. ● Turn off location services when you are not using them. This may seem obvious but it is worth repeating. With the exception of navigation apps that offer turn-by-turn directions, most apps do not need location services to be on all the time. Turn location services on just long enough to get a location fix and then turn them off. Unless the user is in a moving vehicle, the current location should not change frequently enough to be an issue. And you can always start location services again later if needed. Getting the User’s Location Getting Location Events in the Background 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 18● Use the significant-change location service instead ofthe standard location service whenever possible. The significant-change location service providessignificant powersavings while still allowing you to leave location services running. This is highly recommended for apps that need to track changes in the user’s location but do not need the higher precision offered by the standard location services. ● Use lower-resolution values forthe desired accuracy unless doing so would impair your app. Requesting a higher accuracy than you need causes Core Location to power up additional hardware and waste power for precision you are not using. Unless your app really needs to know the user’s position within a few meters, do not put the values kCLLocationAccuracyBest or kCLLocationAccuracyNearestTenMeters in the desiredAccuracy property. And remember that specifying a value of kCLLocationAccuracyThreeKilometers does not prevent the location service from returning better data. Most of the time, Core Location can return location data with an accuracy within a hundred meters or so using Wi-FI and cellular signals. ● Turn off location events if the accuracy does not improve over a period of time. If your app is not receiving events with the desired level of accuracy, you should look at the accuracy of events you do receive and see if it is improving or staying about the same over time. If accuracy is not improving, it could be because the desired accuracy is simply not available at the moment. Turning off location services and trying again later prevents your app from wasting power. Getting the User’s Location Tips for Conserving Battery Power 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 19Core Location supports two different ways to get direction-related information: ● Devices with a magnetometer can report the direction in which a device is pointing, also known as its heading. ● Devices with GPS hardware can report the direction in which a device is moving, also known as its course. Remember that heading and course information do not represent the same information. The heading of a device reflects the actual orientation of the device relative to true north or magnetic north. The course of the device represents the direction of travel and does not take into account the device orientation. Depending on your app, you might prefer one over the other or use a combination of the two. For example, a navigation app might toggle between course and heading information depending on the user’s current speed. At walking speeds, heading information would be more useful for orienting the user to the current environment, whereas in a car, course information provides the general direction of the car’s movement. Adding a Requirement for Direction-Related Events If your app requires some form of direction-related information in order to function properly, you should include the UIRequiredDeviceCapabilities key in the app’s Info.plist file. This key contains an array of strings indicating the features that your app requires of the underlying iOS-based device. The App Store usesthisinformation to prevent usersfrom installing apps on a device without the minimum required hardware. For direction-related events, there are two relevant strings you can associate with this key: ● magnetometer—Include this string if your app requires the presence of heading information. ● gps—Include this string if your app requires the presence of course-related information. Important: If your app uses heading or course events but is able to operate successfully without them, do not include the corresponding string value with the UIRequiredDeviceCapabilities key. In both cases, you should also include the location-services string in the array. For more information about the UIRequiredDeviceCapabilities key, see Information Property List Key Reference . 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 20 Getting Direction-Related EventsGetting Heading-Related Events Heading events are available to apps running on a device that contains a magnetometer. A magnetometer measures nearby magnetic fields emanating from the Earth and usesthem to determine the precise orientation of the device. Although a magnetometer can be affected by local magnetic fields, such as those emanating from fixed magnetsfound in audio speakers, motors, and many other types of electronic devices, Core Location is smart enough to filter out fields that move with the device. Heading values can be reported relative either to magnetic north or true north on the map. Magnetic north represents the point on the Earth’s surface from which the planet’s magnetic field emanates. This location is not the same asthe North Pole, which representstrue north. Depending on the location of the device, magnetic north may be good enough for many purposes, but the closer to the poles you get, the less useful this value becomes. The steps for receiving heading events are as follows: 1. Create a CLLocationManager object. 2. Determine whether heading events are available by calling the headingAvailable class method. (In iOS 3.x and earlier, check the value of the headingAvailable property instead.) 3. Assign a delegate to the location manager object. 4. If you want true north values, start location services. 5. Call the startUpdatingHeading method to begin the delivery of heading events. Listing 2-1 shows a custom method that configures a location manager and starts the delivery of heading events. In this case, the object is a view controller that displays the current heading to the user. Because the view controller displaysthe true north heading value, itstartslocation updatesin addition to heading updates. This code runs in iOS 4.0 and later Listing 2-1 Initiating the delivery of heading events - (void)startHeadingEvents { if (!self.locManager) { CLLocationManager* theManager = [[[CLLocationManager alloc] init] autorelease]; // Retain the object in a property. self.locManager = theManager; locManager.delegate = self; } Getting Direction-Related Events Getting Heading-Related Events 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 21// Start location services to get the true heading. locManager.distanceFilter = 1000; locManager.desiredAccuracy = kCLLocationAccuracyKilometer; [locManager startUpdatingLocation]; // Start heading updates. if ([CLLocationManager headingAvailable]) { locManager.headingFilter = 5; [locManager startUpdatingHeading]; } } The object you assign to the delegate property must conform to the CLLocationManagerDelegate protocol. When a new heading event arrives, the location manager object calls the locationManager:didUpdateHeading: method to deliver that event to your app. Upon receiving a new event, you should check the headingAccuracy property to ensure that the data you just received is valid, as shown in Listing 2-2. In addition, if you are using the true heading value, you should also check to see if it contains a valid value before using it. Listing 2-2 Processing heading events - (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading { if (newHeading.headingAccuracy < 0) return; // Use the true heading if it is valid. CLLocationDirection theHeading = ((newHeading.trueHeading > 0) ? newHeading.trueHeading : newHeading.magneticHeading); self.currentHeading = theHeading; [self updateHeadingDisplays]; } Getting Direction-Related Events Getting Heading-Related Events 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 22Getting Course Information While the User Is Moving Devices that include GPS hardware can generate information indicating the device’s current course and speed. Course information is used to indicate the direction in which the device is moving and does not necessarily reflect the orientation of the device itself. As a result, it is primarily intended for apps that provide navigation information while the user is moving. The actual course and speed information is returned to your app in the same CLLocation objects you use to get the user’s position. When you start location updates, Core Location automatically provides course and speed information when it is available. The framework uses the incoming location events to compute the current direction of motion. For more information on how to start location updates, see “Getting the User’s Location” (page 10) Getting Direction-Related Events Getting Course Information While the User Is Moving 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 23Location data is usually returned as a pair of numerical values representing the latitude and longitude of the corresponding point on the globe. These coordinates offer a precise and easy way to specify location data in your code but they are not very intuitive for users. Instead of global coordinates, users are more likely to understand a location that is specified using information they are more familiar with such as street, city, state, and country information. For situations where you want to display a user friendly version of a location, you can use a geocoder object to obtain that information. About Geocoder Objects A geocoder object uses a network service to convert between latitude and longitude values and a user-friendly placemark, which is a collection of data such as the street, city, state, and country information. Reverse geocoding is the process of converting a latitude and longitude into a placemark. Forward geocoding is the process of converting place name information into a latitude and longitude value. Reverse geocoding is supported in all versions of iOS but forward geocoding is supported only in iOS 5.0 and later. Because geocodersrely on a network service, a live network connection must be present in order for a geocoding request to succeed. If a device is in Airplane mode or the network is currently not configured, the geocoder cannot connect to the service it needs and must therefore return an appropriate error. Here are some rules of thumb for creating geocoding requests: ● Send at most one geocoding request for any one user action. ● If the user performs multiple actions that involve geocoding the same location, reuse the results from the initial geocoding request instead of starting individual requests for each action. ● When you want to update the location automatically (such as when the user is moving), reissue the geocoding request only when the user's location has moved a significant distance and after a reasonable amount of time has passed. For example, in a typical situation, you should not send more than one geocoding request per minute. ● Do notstart a geocoding request at a time when the user will notsee the resultsimmediately. For example, do not start a request if your app is in the background or was interrupted and is currently in the inactive state. 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 24 Geocoding Location DataConverting Coordinates Into Place Name Information Note: In iOS 5.0, MKReverseGeocoder and MKReverseGeocoderDelegate are deprecated so use CLGeocoder for all new app development. In iOS, you can use either the CLGeocoder or MKReverseGeocoder class to handle reverse-geocoding requests. The CLGeocoder is the preferred class to use and is available in iOS 5.0 and later. However, if your app must run on earlier versions of iOS, you can use the MKReverseGeocoder class. Getting Placemark Information using CLGeocoder To initiate a reverse-geocoding request using the CLGeocoder class, create an instance of the class and call the reverseGeocodeLocation:completionHandler: method. The geocoder object initiates the reverse geocoding request asynchronously and delivers the results to the block object you provide. The block object is executed whether the request succeeds or fails. In the event of a failure, an error object is passed to the block indicating the reason for the failure. Note: The same CLGeocoder object can be used to initiate any number of geocoding requests but only one request at a time may be active for a given geocoder. “Converting Coordinates Into Place Name Information” shows an example of how to reverse geocode a point on the map. The only code specific to the geocoding request are the first few lines, which allocate the geocoder object as needed and call the reverseGeocodeLocation:completionHandler: method to start the reverse-geocoding operation. (The geocoder variable represents a member variable used to store the geocoder object.) The rest of the code isspecific to the sample app itself. In this case, the sample app storesthe placemark with a custom annotation object (defined by the MapLocation class) and adds a button to the callout of the corresponding annotation view. Listing 3-1 Geocoding a location using CLGeocoder @implementation MyGeocoderViewController (CustomGeocodingAdditions) - (void)geocodeLocation:(CLLocation*)location forAnnotation:(MapLocation*)annotation { if (!geocoder) geocoder = [[CLGeocoder alloc] init]; [theGeocoder reverseGeocodeLocation:location completionHandler: Geocoding Location Data Converting Coordinates Into Place Name Information 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 25^(NSArray* placemarks, NSError* error){ if ([placemarks count] > 0) { annotation.placemark = [placemarks objectAtIndex:0]; // Add a More Info button to the annotation's view. MKPinAnnotationView* view = (MKPinAnnotationView*)[map viewForAnnotation:annotation]; if (view && (view.rightCalloutAccessoryView == nil)) { view.canShowCallout = YES; view.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure]; } } }]; } @end The advantage of using a block object in a sample like this is that information (such as the annotation object) can be easily captured and used as part of the completion handler. Without blocks, the process of wrangling data variables becomes much more complicated. Getting Placemark Information from the Reverse Geocoder For apps running on iOS 4.1 and earlier, you must perform reverse-geocoding requests using the MKReverseGeocoder class of the Map Kit framework. This class uses a delegate-based approach for geocoding a single location. This means that you can use a single instance of the MKReverseGeocoder class only once. In addition, the Google terms of service require that the MKReverseGeocoder class be used in conjunction with a Google map. To initiate a reverse geocoding request, create an instance of the MKReverseGeocoder class, assign an appropriate object to the delegate property, and call the start method. If the query completessuccessfully, your delegate’s reverseGeocoder:didFindPlacemark: method is called and passed an MKPlacemark object with the results. If there is a problem reverse geocoding the location, the reverseGeocoder:didFailWithError: method is called instead. Geocoding Location Data Converting Coordinates Into Place Name Information 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 26Listing 3-2 shows the code required to use a reverse geocoder. Upon successful completion of the geocoding operation, the code adds a button to the annotation view’s callout so that it can display the placemark information. Because the annotation is not automatically available to the delegate, the custom annotationForCoordinate: method is included to find the appropriate annotation object from the map view. Listing 3-2 Geocoding a location using MKReverseGeocoder @implementation MyGeocoderViewController (CustomGeocodingAdditions) - (void)geocodeLocation:(CLLocation*)location forAnnotation:(MapLocation*)annotation { MKReverseGeocoder* theGeocoder = [[MKReverseGeocoder alloc] initWithCoordinate:location.coordinate]; theGeocoder.delegate = self; [theGeocoder start]; } // Delegate methods - (void)reverseGeocoder:(MKReverseGeocoder*)geocoder didFindPlacemark:(MKPlacemark*)place { MapLocation* theAnnotation = [map annotationForCoordinate:place.coordinate]; if (!theAnnotation) return; // Associate the placemark with the annotation. theAnnotation.placemark = place; // Add a More Info button to the annotation's view. MKPinAnnotationView* view = (MKPinAnnotationView*)[map viewForAnnotation:annotation]; if (view && (view.rightCalloutAccessoryView == nil)) { view.canShowCallout = YES; view.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure]; } Geocoding Location Data Converting Coordinates Into Place Name Information 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 27} - (void)reverseGeocoder:(MKReverseGeocoder*)geocoder didFailWithError:(NSError*)error { NSLog(@"Could not retrieve the specified place information.\n"); } @end @implementation MKMapView (GeocoderAdditions) - (MapLocation*)annotationForCoordinate:(CLLocationCoordinate2D)coord { // Iterate through the map view's list of coordinates // and return the first one whose coordinate matches // the specified value exactly. id theObj = nil; for (id obj in [self annotations]) { if (([obj isKindOfClass:[MapLocation class]])) { MapLocation* anObj = (MapLocation*)obj; if ((anObj.coordinate.latitude == coord.latitude) && (anObj.coordinate.longitude == coord.longitude)) { theObj = anObj; break; } } } return theObj; } Geocoding Location Data Converting Coordinates Into Place Name Information 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 28@end Converting Place Names Into Coordinates In iOS 5.0 and later, you use the CLGeocoder class to initiate forward-geocoding requests using either a dictionary of Address Book information or a simple string. There is no designated format for string-based requests; delimiter characters are welcome, but not required, and the geocoder server treats the string as case-insensitive. Therefore, any of the following strings would yield results: ● "Apple Inc” ● "1 Infinite Loop” ● "1 Infinite Loop, Cupertino, CA USA” The more information you can provide to the forward geocoder, the better the results returned to you. The geocoder object parses the information you give it and, if it finds a match, returns some number of placemark objects. The number of returned placemark objects depends greatly on the specificity of the information provided. Thus, providing street, city, province, and country information is much more likely to return a single address than just street and city information. The completion handler block you pass to the geocoder should therefore be prepared to handle multiple placemarks, as shown in the following example: [geocoder geocodeAddressString:@"1 Infinite Loop" completionHandler:^(NSArray* placemarks, NSError* error){ for (CLPlacemark* aPlacemark in placemarks) { // Process the placemark. } }]; Geocoding Location Data Converting Place Names Into Coordinates 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 29Introduced in iOS 3.0, the Map Kit framework lets you embed a fully functional map interface into your app. The map support provided by this framework includes many of the features normally found in the Maps app. You can display standard street-level map information, satellite imagery, or a combination of the two. You can zoom and pan the map programmatically, and the framework provides automatic support for the touch events that let users zoom and pan the map. You can also annotate the map with custom information. To use the features of the Map Kit framework, you must linking your app to MapKit.framework in your Xcode project. To access the classes and headers of the framework, include an #import statement at the top of any relevant source files. For general information about the classes of the Map Kit framework, see Map Kit Framework Reference . Important: The Map Kit framework uses Google services to provide map data. Use of the framework and its associated interfaces binds you to the Google Maps/Google Earth API terms of service. You can find these terms of service at http://code.google.com/apis/maps/iphone/terms.html. Understanding Map Geometry A map view contains a flattened representation of a spherical object, namely the Earth. In order to use maps effectively, you need to understand a little bit about how to specify pointsin a map view, and how those points translate to points on the Earth’s surface. Understanding map coordinate systems is especially important if you plan to place custom content, such as overlays, on top of the map. 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 30 Displaying MapsMap Coordinate Systems In order to understand the coordinate systems used by Map Kit, it helpsto understand how the three-dimensional surface of the Earth is mapped to a two-dimensional map. Figure 4-1 shows how the surface of the Earth can be mapped to a two-dimensional surface. Figure 4-1 Mapping spherical data to a flat surface Map Kit uses a Mercator map projection, which is a specific type of cylindrical map projection like the one shown in Figure 4-1 (page 31). In a cylindrical map projection, the coordinates of a sphere are mapped onto the surface of a cylinder, which is then unwrapped to generate a flat map. In such a projection, the longitude lines that normally converge at the poles become parallel instead, causing land masses to be distorted as you move away from the equator. The advantage of a Mercator projection is that the map content is scaled in a way that benefits general navigation. Specifically, on a Mercator map projection, a straight line drawn between any two points on the map yields a course heading that can be used in actual navigation on the surface of the Earth. The projection used by Map Kit uses the Prime Meridian as its central meridian. How you specify data points on a map depends on how you intend to use them. Map Kit supports three basic coordinate systems for specifying map data points: Displaying Maps Understanding Map Geometry 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 31● A map coordinate is a latitude and longitude on the spherical representation of the Earth. Map coordinates are the primary way of specifying locations on the globe. You specify individual map coordinate values using the CLLocationCoordinate2D structure. You can specify areas using the MKCoordinateSpan and MKCoordinateRegion structures. ● A map point is an x and y value on the Mercator map projection. Map points are used for many map-related calculationsinstead of map coordinates because they simplify the mathematicsinvolved in the calculations. In your app, you use map points primarily when specifying the shape and position of custom map overlays. You specify individual map points using the MKMapPoint structure. You can specify areas using the MKMapSize and MKMapRect structures. ● A point is a graphical unit associated with the coordinate system of a UIView object. Map points and map coordinates must be mapped to points before drawing custom content in a view. You specify individual points using the CGPoint structure. You can specify areas using the CGSize and CGRect structures. In most situations, the coordinate system you should use is predetermined by the Map Kit interfaces you are using. When it comes to storing actual data in files or inside your app, map coordinates are precise, portable, and the best option forstoring location data. Core Location also uses map coordinates when specifying location values. Converting Between Coordinate Systems Although you normally specify points on the map using latitude and longitude values, there may be times when you need to convert to and from other coordinate systems. For example, you typically use map points when specifying the shape of overlays. Table 4-1 lists the conversion routines you use to convert from one coordinate system to another. Most of these conversionsrequire a view object because they involve converting to or from points. Table 4-1 Map coordinate system conversion routines Convert from Convert to Conversion routines convertCoordinate: toPointToView: (MKMapView) convertRegion: toRectToView: (MKMapView) Map coordinates Points Map coordinates Map points MKMapPointForCoordinate MKCoordinateForMapPoint MKCoordinateRegionForMapRect Map points Map coordinates pointForMapPoint: (MKOverlayView) rectForMapRect: (MKOverlayView) Map points Points Displaying Maps Understanding Map Geometry 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 32Convert from Convert to Conversion routines convertPoint: toCoordinateFromView: (MKMapView) convertRect: toRegionFromView: (MKMapView) Points Map coordinates mapPointForPoint: (MKOverlayView) mapRectForRect: (MKOverlayView) Points Map points Adding a Map View to Your User Interface The MKMapView class is a self-contained interface for presenting map data in your app. This class provides support for displaying map data, for managing user interactions, and for hosting custom content provided by your app. You should never subclass MKMapView but should only embed it as-is into your app’s view hierarchy. You should also assign a delegate object to the map. The map view reports all relevant interactions to its delegate so that it has a chance to respond appropriately. You can add a map view to your app programmatically or using Interface Builder: ● To add a map using Interface Builder, drag a Map view object to the appropriate view or window. ● To add a map programmatically, create an instance of the MKMapView class, initialize it using the initWithFrame: method, and then add it as a subview to your view hierarchy. Because it is a view, you can manipulate a map view in the same ways you manipulate other views. You can change its size and position in your view hierarchy, you can configure its autoresizing behaviors, and you can add subviews to it. Unlike a view, you never handle touch events directly in a map view. The map view itself is an opaque container for a complex view hierarchy that handles the display of map-related data and all interactions with that data. Any subviews you add to the map view retain the position specified by their frame property and do not scroll with the map contents. If you want content to remain fixed relative to a specific map coordinate (and thus scroll with the map itself), you must use annotations or overlays as described in “Annotating Maps” (page 37). New maps are configured to accept user interactions and display map data only. You can configure the map to display satellite imagery or a mixture of satellite and map data by changing the Type attribute of the map in Interface Builder or changing the value in the mapType property. If you want to limit user interactions, you can change the values in the zoomEnabled and scrollEnabled properties as well. If you want to respond to user interactions, you should do so using a delegate as described in “Responding to User Interactions with a Map” (page 36). Displaying Maps Adding a Map View to Your User Interface 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 33Configuring the Properties of a Map The MKMapView class has a handful of properties that you can configure programmatically. These properties control important information such as which part of the map is currently visible and what user interactions are allowed. Setting the Visible Portion of the Map The region property of the MKMapView class controls the currently visible portion of the map. When it is first created, a map’s visible region is typically set to the entire world. In other words, the region encompasses the area that shows as much of the map as possible. You can change this region at any time by assigning a new value to the region property. This property contains an MKCoordinateRegion structure, which has the following definition: typedef struct { CLLocationCoordinate2D center; MKCoordinateSpan span; } MKCoordinateRegion; The interesting part of an MKCoordinateRegion structure is the span. The span is analogous to the width and height values of a rectangle but is specified using map coordinates and thus is measured in degrees, minutes, and seconds. One degree of latitude is equivalent to approximately 111 kilometers but longitudinal distances vary with the latitude. At the equator, one degree of longitude is equivalent to approximately 111 kilometers but at the poles this value is zero. If you prefer to specify the span using meters, you can use the MKCoordinateRegionMakeWithDistance to create a region data structure using meter values instead of degrees. The value you assign to the region property (or set using the setRegion:animated: method) is usually not the same value that is eventually stored by that property. Setting the span of a region nominally defines the rectangle you want to view but also implicitly sets the zoom level for the map view itself. The map view cannot display arbitrary zoom levels and must adjust any regions you specify to match the zoom levels it supports. It chooses the zoom level that allows your entire region to be visible while still filling as much of the screen as possible. It then adjust the region property accordingly. To find out the resulting region without actually changing the value in the region property, you can use the regionThatFits: method of the map view. Zooming and Panning the Map Content Zooming and panning allow you to change the visible portion of the map at any time: Displaying Maps Configuring the Properties of a Map 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 34● To pan the map (but keep the same zoom level), change the value in the centerCoordinate property of the map view or call the setCenterCoordinate:animated: method. ● To change the zoom level (and optionally pan the map), change the value in the region property of the map view or call the setRegion:animated: method. If you only want to pan the map, you should only do so by modifying the centerCoordinate property. Attempting to pan the map by changing the region property usually causes a change in the zoom level as well, because changing any part of the region causes the map view to evaluate the zoom level needed to display that region appropriately. Changesto the current latitude almost always cause the zoom level to change and other changes might cause a different zoom level to be chosen as well. Using the centerCoordinate property (or the setCenterCoordinate:animated: method) lets the map view know that it should leave the zoom level unchanged and update the span as needed. For example, to pan the map to the left by half the current map width, you could use the following code to find the coordinate at the left edge of the map and use that as the new center point, as shown here: CLLocationCoordinate2D mapCenter = myMapView.centerCoordinate; mapCenter = [myMapView convertPoint: CGPointMake(1, (myMapView.frame.size.height/2.0)) toCoordinateFromView:myMapView]; [myMapView setCenterCoordinate:mapCenter animated:YES]; To zoom the map, modify the span of the visible map region. To zoom in, assign a smaller value to the span. To zoom out, assign a larger value. In other words if the current span is one degree, specifying a span of two degrees zooms out by a factor of two: MKCoordinateRegion theRegion = myMapView.region; // Zoom out theRegion.span.longitudeDelta *= 2.0; theRegion.span.latitudeDelta *= 2.0; [myMapView setRegion:theRegion animated:YES]; Displaying the User’s Current Location on the Map Map Kit includes built-in support for displaying the user’s current location on the map. To show this location, set the showsUserLocation property of your map view object to YES. Doing so causes the map view to use Core Location to find the user’s location and add an annotation of type MKUserLocation to the map. Displaying Maps Configuring the Properties of a Map 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 35The addition of the MKUserLocation annotation object to the map is reported by the delegate in the same way that custom annotations are. If you want to associate a custom annotation view with the user’s location, you should return that view from your delegate object’s mapView:viewForAnnotation: method. If you want to use the default annotation view, you should return nil from that method instead. Responding to User Interactions with a Map The MKMapView class reports significant map-related events to its associated delegate object. The delegate object is an object that conforms to the MKMapViewDelegate protocol. You provide this object in situations where you want to respond to the following types of events: ● Changes to the visible region of the map ● The loading of map tiles from the network ● Changes in the user’s location ● Changes associated with annotations and overlays. For information about handling changes associated with annotations and overlays,see “Annotating Maps” (page 37). Displaying Maps Responding to User Interactions with a Map 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 36The MKMapView class implements an opaque view hierarchy for displaying a scrollable map. Although the map itself is scrollable, any subviews you add to a map view remain fixed in place and do not scroll. If you want to affix content to the map itself, and thus have that content scroll along with the rest of the map, you must use annotations and overlays. Annotations are used to display content that can be defined by a single coordinate point. By contrast, overlays are used to display content that is defined by any number of points and may constitute one or more contiguous or noncontiguousshapes. For example, you use annotationsto represent information such asthe user’s current location, a specific address, or a single point of interest. You use overlays to present more complex information such as traffic information, the boundaries of parks, lakes, cities, states, countries, or other bounded areas. Map Kit separates the data associated with an annotation or overlay from its visual presentation on the map. This separation allows the map to manage visible annotations and overlays much more efficiently and means that you can add hundreds of annotations and overlays to a map and still expect reasonable performance. 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 37 Annotating MapsAdding Annotations to a Map Annotations offer a way to highlightspecific coordinates on the map and provide additional information about them. You can use annotationsto call outspecific addresses, points of interest, and other types of destinations. When displayed on a map, annotations typically have some sort of image to identify their location and may also have a callout bubble providing information and links to more content. Figure 5-1 shows an annotation that uses a custom image to highlight a particular location. Figure 5-1 Displaying an annotation in a map In order to display an annotation on a map, your app must provide two distinct objects: ● An object that conforms to the MKAnnotation protocol and manages the data for the annotation. (This object is the annotation object.) ● A view (derived from the MKAnnotationView class) used to draw the visual representation of the annotation on the map surface. (This is the annotation view.) Annotation objects are typically small data objects that store the map coordinate data and any other relevant information about the annotation, such as a title string. Because annotations are defined using a protocol, you can turn any class in your app into an annotation object. In practice, it is good to keep annotation objects lightweight, especially if you intend to add large numbers of them to the map. The map view keeps a reference to the annotation objects you add to it and uses the data in those objects to determine when to display the corresponding view. Map Kit provides some standard annotation views and you can also define custom annotation views if you want. However, you do not add annotation views directly to the map surface. Instead, you provide an annotation view when asked for it and let the map view incorporate that view into its opaque view hierarchy. You provide the annotation view using your map view delegate object. Annotating Maps Adding Annotations to a Map 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 38The annotations you create are typically anchored to a single map coordinate that does not change. However, you can change the coordinate for an annotation programmatically as needed and can implement support to allow the user to drag annotations around the map. In iOS 4.0 and later, support for dragging annotations is even incorporated into the Map Kit classes; implementing thissupport in prior versions of the operating system requires some additional custom code on your part. Checklist for Adding an Annotation to the Map The steps for implementing and using annotations in your map-based app are shown below. These steps assume that your app incorporates an MKMapView object somewhere in its interface. 1. Define an appropriate annotation object using one of the following options: ● Use the MKPointAnnotation class to implement a simple annotation. This type of annotation contains properties for specifying the title and subtitle strings to display in the annotation’s onscreen callout bubble. ● Define a custom object that conforms to the MKAnnotation protocol, as described in “Defining a Custom Annotation Object” (page 40). This type of annotation can store any type of data you want. 2. Define an annotation view to present the data on screen. How you define your annotation view depends on your needs and may be one of the following: ● If the annotation can be represented by a static image, create an instance of the MKAnnotationView class and assign the image to its image property; see “Using the Standard Annotation Views” (page 41). ● If you want to use a standard pin annotation, create an instance of the MKPinAnnotationView class; see “Using the Standard Annotation Views” (page 41). ● If a static image is insufficient for representing your annotation, subclass MKAnnotationView and implement the custom drawing code needed to present it. For information about how to implement custom annotation views, see “Defining a Custom Annotation View” (page 42). 3. Implement the mapView:viewForAnnotation: method in your map view delegate. Your implementation of this method should dequeue an existing annotation view if one exists or create a new one. If your app supports multiple types of annotations, you must include logic in this method to create a view of the appropriate type for the provided annotation object. For more information about implementing this method, see “Creating Annotation Views from Your Delegate Object” (page 44). 4. Add your annotation object to the map view using the addAnnotation: or addAnnotations: method. When you add an annotation to a map view, the map view displays the corresponding annotation view whenever the coordinate for the annotation is in the visible map rectangle. If you want to hide annotations selectively, you must manually remove them from the map view yourself. You can add and remove annotations at any time. Annotating Maps Adding Annotations to a Map 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 39All annotations are drawn at the same scale every time, regardless of the map’s current zoom level. If your map contains many annotations, this could result in your annotation views overlapping each other as the user zooms out. To counter this behavior, you can add and remove annotations based on the map’s current zoom level. For example, a weather app might display information only for major cities when the map is zoomed out to show the entire state. Asthe user zoomsin, the app could then add new annotations containing weather information for smaller cities and regions. Implementing the logic necessary to add and remove annotations is your responsibility. For more information about how to manage the annotations of a map view effectively, see “Managing the Map’s Annotation Objects” (page 46). Defining a Custom Annotation Object The most important part of an annotation is the annotation object, which is an object that conforms to the MKAnnotation protocol. If all you want to do is associate a title with a map coordinate, you can use the MKPointAnnotation classfor your annotation object. However, if you need to represent additional information with the annotation, you need to define a custom annotation object. A custom annotation object consists of a map coordinate and whatever other data you want to associate with the annotation. Listing 5-1 shows the minimal code needed to declare a custom annotation class. The coordinate property declaration isfrom the MKAnnotation protocol and must be included in all annotation classes. Because this is a simple annotation, it also includes an initializer method, which is used to set the value of the coordinate property, since it is read-only. Your own declaration would likely also include methods and properties defining the additional annotation data. Listing 5-1 Creating a simple annotation object @interface MyCustomAnnotation : NSObject { CLLocationCoordinate2D coordinate; } @property (nonatomic, readonly) CLLocationCoordinate2D coordinate; - (id)initWithLocation:(CLLocationCoordinate2D)coord; // Other methods and properties. @end Annotating Maps Adding Annotations to a Map 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 40The implementation for your custom class must provide an implementation for the coordinate property and a way to set its value. Because coordinate is a declared property, you can synthesize the code needed to implement it easily enough using the @synthesize keyword. All that remains is to implement the code for the custom initWithLocation: method, which is shown in Listing 5-2. Listing 5-2 Implementing the MyCustomAnnotation class @implementation MyCustomAnnotation @synthesize coordinate; - (id)initWithLocation:(CLLocationCoordinate2D)coord { self = [super init]; if (self) { coordinate = coord; } return self; } @end Important: When you implement the coordinate property in your class, it is recommended that you synthesize its creation. If you choose to implement the methodsfor this property yourself, or if you manually modify the variable underlying that property in other parts of your class after the annotation has been added to the map, be sure to send out notifications when you do. Map Kit uses KVO notifications to detect changes to the coordinate, title, and subtitle properties of your annotations and make any needed changes to the map display. If you do not send out KVO notifications, the position of your annotations may not be updated properly on the map. For more information about how to implement KVO-compliant accessor methods, see Key-Value Observing Programming Guide . For an example of an annotation object that is based on a Core Data object, see the sample code project WeatherMap . Using the Standard Annotation Views Using one of the standard annotation views is the easiest way to present annotations on your map. The MKAnnotationView class is a concrete view that defines the basic behavior for all annotation views. The MKPinAnnotationView class is a subclass of MKAnnotationView that displays one of the standard system pin images at the associated annotation’s coordinate point. Annotating Maps Adding Annotations to a Map 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 41The MKAnnotationView class is perfect for situations where you have a static image that you want to display for an annotation. After creating an instance of this class, assign your custom image to the image property of the object. When the annotation is displayed, the image is displayed centered over the target map coordinate. If you do not want the image to be centered on the map coordinate, you can use the centerOffset property to move the center point horizontally and vertically in any direction. Listing 5-3 shows an example of how to create an annotation view with a custom image and offset. Listing 5-3 Creating a standard annotation view MKAnnotationView* aView = [[[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"MyCustomAnnotation"] autorelease]; aView.image = [UIImage imageNamed:@"myimage.png"]; aView.centerOffset = CGPointMake(10, -20); You create the standard annotation views in your delegate’s mapView:viewForAnnotation: method. For more information about how to implement this method, see “Creating Annotation Views from Your Delegate Object” (page 44). Defining a Custom Annotation View If a static image is insufficient for representing your annotation, you can subclass MKAnnotationView and draw content dynamically in one of two ways. You can continue to use the image property of MKAnnotationView but change the image at regular intervals, or you can also override the view’s drawRect: method and draw your content dynamically every time. As with any custom drawing you do in a view, you should always consider performance before choosing an approach. Custom drawing gives you the most flexibility but if most of your content is fixed, using images may still be faster. If you choose to define a custom annotation view, you subclass like any other view. The only difference is that instead of subclassing UIView, you subclass MKAnnotationView as shown in Listing 5-4. Listing 5-4 Declaring a custom annotation view #import #import @interface MyCustomAnnotationView : MKAnnotationView { // Custom data members Annotating Maps Adding Annotations to a Map 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 42} // Custom properties and methods. @end When drawing content using the drawRect: method, you must always remember to specify a nonzero frame size for your annotation view shortly after initialization. The default initialization method for annotation views does not take a frame rectangle as a parameter. Instead, it uses the image you specify in the image property to set that frame size later. If you do not set an image, though, you must set the frame property of the view explicitly in order for your rendered content to be visible, as shown in Listing 5-5. Because the view draws in only part of its frame, it also sets its opaque property to NO so that the remaining map content shows through. If you do not do this, the drawing system fills your view with the current background color before calling your drawRect: method. Listing 5-5 Initializing a custom annotation view - (id)initWithAnnotation:(id )annotation reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier]; if (self) { // Set the frame size to the appropriate values. CGRect myFrame = self.frame; myFrame.size.width = 40; myFrame.size.height = 40; self.frame = myFrame; // The opaque property is YES by default. Setting it to // NO allows map content to show through any unrendered // parts of your view. self.opaque = NO; } return self; } Annotating Maps Adding Annotations to a Map 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 43In all other respects, drawing custom content in an annotation view is the same as it is in any view. The system calls your view’s drawRect: method as needed to redraw portions of the view that need it and you can force a redraw operation by calling the setNeedsDisplay or setNeedsDisplayInRect: method of your view at any time. If you want to animate the contents of your view, you need to set up a timer to fire at periodic intervals and update your view. For information on how to set up timers, see Timer Programming Topics. For information about how views draw content in iOS, see View Programming Guide for iOS . Creating Annotation Views from Your Delegate Object When it needs an annotation view, the map view calls the mapView:viewForAnnotation: method of its delegate object. If you do not implement this method, or if you implement it and always return nil, the map view uses a default annotation view, which is typically a pin annotation view. If you want to return annotation views other than the default ones, you need to override the method and create your views there. Before trying to create a new view in your mapView:viewForAnnotation: method, you should always check to see if a similar annotation view already exists. Like table views, the map view has the option of caching unused annotation views that it is not using. When it does this, it makes the unused views available from the dequeueReusableAnnotationViewWithIdentifier: method. If this method returns a value other than nil, you should update the view’s attributes and return it. If the method returns nil, just create a new instance of the appropriate annotation view class. In both cases, it is your responsibility to take the annotation passed to this method and assign it to your annotation view. You should also use this method to update the view before returning it. Listing 5-6 shows a sample implementation of the mapView:viewForAnnotation: method. This method provides pin annotation views for custom annotation objects. If an existing pin annotation view already exists, this method associates the annotation object with that view. If no view is in the reuse queue, this method creates a new one, setting up the basic properties of the view and configuring an accessory view for the annotation’s callout. If the map is currently showing the user’s location, this method returns nil for any MKUserLocation objects so that the map uses the default annotation view. Listing 5-6 Creating annotation views - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id )annotation { // If it's the user location, just return nil. if ([annotation isKindOfClass:[MKUserLocation class]]) return nil; Annotating Maps Adding Annotations to a Map 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 44// Handle any custom annotations. if ([annotation isKindOfClass:[MyCustomAnnotation class]]) { // Try to dequeue an existing pin view first. MKPinAnnotationView* pinView = (MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:@"CustomPinAnnotationView"]; if (!pinView) { // If an existing pin view was not available, create one. pinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"CustomPinAnnotation"] autorelease]; pinView.pinColor = MKPinAnnotationColorRed; pinView.animatesDrop = YES; pinView.canShowCallout = YES; // Add a detail disclosure button to the callout. UIButton* rightButton = [UIButton buttonWithType: UIButtonTypeDetailDisclosure]; [rightButton addTarget:self action:@selector(myShowDetailsMethod:) forControlEvents:UIControlEventTouchUpInside]; pinView.rightCalloutAccessoryView = rightButton; } else pinView.annotation = annotation; return pinView; } return nil; } Annotating Maps Adding Annotations to a Map 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 45Managing the Map’s Annotation Objects If your app works with more than a few annotations, you might need to think about how you manage those objects. The map view does not make any distinction between active and inactive annotations; it considers all annotation objectsit knows about to be active. As a result, it alwaystriesto display a corresponding annotation view when the given coordinate point is on the screen. If the coordinatesfor two annotations are close together, this could lead to overlap between the corresponding annotation views. And if your map includes hundreds of annotations, zooming out far enough could lead to a visually unappealing mass of annotation views. Even worse, the views may be so close together that the user cannot access some of them. The only way to eliminate annotation overcrowding is to remove some of the annotation objects from the map view. This typically involves implementing the mapView:regionWillChangeAnimated: and mapView:regionDidChangeAnimated: methods to detect changes in the map zoom level. During a zoom change, you can add or remove annotations as needed based on their proximity to one another. You might also consider other criteria (such as the user’s current location) to eliminate some annotations. In iOS 4.0 and later, Map Kit includes numerous functions to make determining the proximity of map points easier. If you convert the map coordinate of your annotation to the map point coordinate space, you can use the MKMetersBetweenMapPoints method to get absolute distances between two points. You can also use each coordinate as the center of a map rectangle and use the MKMapRectIntersectsRect function to find any intersections. For a complete list of functions, see Map Kit Functions Reference . Marking Your Annotation View as Draggable In iOS 4.0 and later, annotation views provide built-in dragging support. This support makes it very easy to drag annotations around the map and to ensure that the annotation data is updated accordingly. To implement minimal support for dragging, you must do the following: ● In your annotation objects, implement the setCoordinate: method to allow the map view to update the annotation’s coordinate point. ● When creating your annotation view, set its draggable property to YES. When the user touches and holds a draggable annotation view, the map view begins a drag operation for it. As the drag operation progresses, the map view calls the mapView:annotationView:didChangeDragState:fromOldState: method of its delegate to notify it of changes to the drag state of your view. You can use this method to affect or respond to the drag operation. If you want to animate your view during a drag operation, you can do that by implementing a custom dragState method in your annotation view. As the map view processes drag-related touch events, it updates the dragState property of the affected annotation view. Implementing a custom dragState method gives Annotating Maps Adding Annotations to a Map 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 46you a chance to intercept these changes and perform additional actions, such as animate the appearance of your view. For example, the MKPinAnnotationView class raises the pin off the map when a drag operation starts and drops the pin back down on the map when it ends. If you need to support draggable annotations in earlier versions of iOS, you must implement the support for it yourself. For information and sample code showing how to do it, see “Legacy Map Techniques” (page 64). Displaying Overlays on a Map Overlays offer a way to layer content over an arbitrary region of the map. Whereas annotations are always defined by a single map coordinate, overlays are typically defined by multiple coordinates. You can use these coordinates to create contiguous or noncontiguous sets of lines, rectangles, circles, and other shapes, which Annotating Maps Displaying Overlays on a Map 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 47can then be filled or stroked with color. For example, you might use overlays to layer traffic information on top of roadways, highlight the boundaries of a park, or show city, state, and national borders. Figure 5-2 shows a filled and stroked overlay covering the state of Colorado. Figure 5-2 Displaying an overlay on a map In order to display an overlay on a map, your app must provide two distinct objects: ● An object that conforms to the MKOverlay protocol and manages the data points for the overlay. (This object is the overlay object.) ● A view (derived from the MKOverlayView class) used to draw the visual representation of the overlay on the map surface. (This is the overlay view.) Annotating Maps Displaying Overlays on a Map 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 48Overlay objects are typically small data objects that store the points that define the overlay and any other relevant information, such as a title string. Because overlays are defined using a protocol, you can turn any class in your app into an overlay object. In addition, Map Kit defines several concrete overlay objects for specifying different types of standard shapes. The map view keeps a reference to the overlay objects you add to it and uses the data in those objects to determine when to display a corresponding view. Map Kit provides standard overlay views that are capable of drawing any shapes represented by the concrete overlay objects. Like annotations, you do not add overlay views directly to the map surface. Instead, you provide an overlay view when asked for it and let the map view incorporate that view into its opaque view hierarchy. You provide the annotation view using your map view delegate object. Once defined, the position of an overlay on the map typically never changes. Although it is possible to create draggable overlays, doing so israre and you would need to implement the code to track the dragging operation and update the overlay coordinate points yourself. Checklist for Adding an Overlay to the Map Here are the steps for implementing and using overlays in your map-based app. These steps assume that your app incorporates an MKMapView object somewhere in its interface. 1. Define an appropriate overlay data object using one of the following options: ● Use the MKCircle, MKPolygon, or MKPolyline class as-is. ● Subclass MKShape or MKMultiPoint to create overlays that provide app-specific behaviors or use custom shapes. ● Use an existing class from your app and make it conform to the MKOverlay protocol. 2. Define an overlay view to present on the screen using one of the following options: ● For standard shapes, use the MKCircleView, MKPolygonView, or MKPolylineView to represent the annotation. You can customize many of the drawing attributes of the final shape using these classes. ● For custom shapes descended from MKShape, define an appropriate subclass of MKOverlayPathView to render the shape. ● For all other custom shapes and overlays, subclass MKOverlayView and implement your custom drawing code. 3. Implement the mapView:viewForOverlay: method in your map view delegate. 4. Add your overlay data object to the map view using the addOverlay: method or one of many others. Annotating Maps Displaying Overlays on a Map 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 49Unlike annotations, rendered overlays are automatically scaled to match the current zoom level of the map. Scaling the overlay is necessary because overlays generally highlight boundaries, roads, and other content that also scales during zooming. In addition, you can rearrange their Z-ordering of overlays in a map to ensure that specific overlays are always displayed on top of others. Using the Standard Overlay Objects and Views If all you want to do is highlight a specified map region, the standard overlay classes are the easiest way to do it. The standard overlay classes include MKCircle, MKPolygon, and MKPolyline. These classes define the basic shape of the overlay and are used in conjunction with the MKCircleView, MKPolygonView, or MKPolylineView classes, which handle the rendering of that shape on the map surface. Listing 5-7 shows an example of how you would create the rectangular polygon shown in Figure 5-2 (page 48). This polygon consists of four map coordinates that correspond to the four corners of the state of Colorado. After creating the polygon, all you have to do is add it to the map using the addOverlay: method. Listing 5-7 Creating a polygon overlay object // Define an overlay that covers Colorado. CLLocationCoordinate2D points[4]; points[0] = CLLocationCoordinate2DMake(41.000512, -109.050116); points[1] = CLLocationCoordinate2DMake(41.002371, -102.052066); points[2] = CLLocationCoordinate2DMake(36.993076, -102.041981); points[3] = CLLocationCoordinate2DMake(36.99892, -109.045267); MKPolygon* poly = [MKPolygon polygonWithCoordinates:points count:4]; poly.title = @"Colorado"; [map addOverlay:poly]; In order for an overlay can be shown on the map, the mapView:viewForOverlay: method of your map view delegate needs to provide an appropriate overlay view. For the standard overlay shapes, you can do this by creating a view that matches the type of shape you want to display. Listing 5-8 shows an implementation of this method that creates the polygon view used to cover the state of Colorado. In this example, the method sets the colors to use for rendering the shape and the border width. Annotating Maps Displaying Overlays on a Map 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 50Listing 5-8 Creating a polygon view for rendering a shape - (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id )overlay { if ([overlay isKindOfClass:[MKPolygon class]]) { MKPolygonView* aView = [[[MKPolygonView alloc] initWithPolygon:(MKPolygon*)overlay] autorelease]; aView.fillColor = [[UIColor cyanColor] colorWithAlphaComponent:0.2]; aView.strokeColor = [[UIColor blueColor] colorWithAlphaComponent:0.7]; aView.lineWidth = 3; return aView; } return nil; } It is important to remember that the standard overlay views are there to simply fill and stroke the shape represented by the overlay. If you want to display additional information, you need to create a custom overlay view to do the necessary drawing. You should avoid adding subviews to an existing overlay in an attempt to render any extra content. Any subviews you add to an overlay are scaled along with the overlay itself and made to fit the zoom level of the map. Unless your subviews contain content that also scales well, the results would probably not look very good. Defining a Custom Overlay Object The job of an overlay object is to manage the coordinate data and any additional information associated with the overlay. Map Kit provides a couple of options for defining custom overlays. You can subclass MKShape or MKMultiPoint to define new types of shape-based overlays or you can adopt the MKOverlay protocol into one of your app’s existing classes. The choice between the two techniques depends mostly on whether you already have a class with the data you want. If you do, you should incorporate the protocol into your existing class; otherwise, subclass MKShape or MKMultiPoint to create a custom shape subclass. Whether you subclass or adopt the MKOverlay protocol, the work you have to do in any custom overlay object is the same. The main job of an overlay object is to vend two key pieces of information: ● A coordinate defining the center point of the overlay Annotating Maps Displaying Overlays on a Map 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 51● A bounding rectangle that completely encompasses the overlay’s content Of the two pieces of information, the bounding rectangle isthe one that is most important to the overlay itself. The map view uses the bounding rectangle specified by an overlay object as its cue for when to add the corresponding overlay view to the map. (If you add the overlay to the map as an annotation as well, the coordinate value similarly determines when the corresponding annotation view should be added to the map.) The bounding rectangle itself must be specified using map points, not map coordinates. You can convert between the two coordinate systems using the Map Kit functions. Most of the real work involved with displaying an overlay isincurred by the corresponding overlay view object. The overlay object simply defines where on the map the overlay should be placed, whereas the overlay view defines the final appearance of the overlay, including what information (if any) is displayed for the overlay. The creation of custom overlay views is described further in “Defining a Custom Overlay View” (page 52). Defining a Custom Overlay View If you want to do more than draw the boundaries or fill the content of your overlay shape, you need to create a custom overlay view. Custom overlays give you the opportunity to draw any content you want. For example, if you are drawing a traffic overlay, you could use a custom overlay view to color-code each roadway based on its conditions. You can also use custom drawing code to animate your overlay’s appearance. To create a custom overlay view, you mustsubclass MKOverlayView. (If you simply want to modify the drawing behavior of an existing shape-based overlay, you can subclass MKOverlayPathView instead.) In your custom implementation, you should implement the following methods: ● drawMapRect:zoomScale:inContext: to draw your custom content ● canDrawMapRect:zoomScale: if your drawing code depends on content that might not always be available The canDrawMapRect:zoomScale: method is for situations where your content may not always be ready to draw. For example, a traffic overlay would need to download the needed traffic data from the network before it could draw. If you return NO from this method, the map view refrains from drawing your view until you signal that you are ready. You can do this by marking your view as dirty using either the setNeedsDisplayInMapRect: or setNeedsDisplayInMapRect:zoomScale: method. When your view is ready to draw, the map view calls the drawMapRect:zoomScale:inContext: method to do the actual drawing. Unlike drawing in a normal view, drawing in an overlay view involves some special considerations, including the following: Annotating Maps Displaying Overlays on a Map 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 52● Your drawing code should never use the view’s bounds or frame as reference points for drawing. Instead, it should use the map points associated with the overlay object to define shapes. Immediately before drawing, it should then convert those map points to points (CGPoint and so on) using the conversion routines found in the MKOverlayView class. Also, you typically do not apply the zoom scale value passed to this method directly to your content. Instead, you provide it only when a Map Kit function or method specifically requires it. As long as you specify content using map points and convert to points, your content should be scaled to the correct size automatically. ● If you use UIKit classes and functions to draw, you must explicitly set up and clean up the drawing environment. Before issuing any calls, call the UIGraphicsPushContext function to make the context passed to your method the current context. When you are done drawing, call UIGraphicsPopContext to remove that context. ● Remember that the map view may tile large overlays and render each tile on a separate thread. Your drawing code should therefore not attempt to modify variables or other data unless it can do so in a thread-safe manner. Listing 5-9 shows the drawing code used to fill the bounding rectangle of an overlay using a gradient. When drawing gradients, it is especially important to contain the drawing operation by applying a clipping rectangle to the desired drawing area. The view’s frame is actually larger than the overlay’s bounding rectangle, so without a clipping rectangle, the gradient would render outside the expected area. Because the bounding rectangle of the overlay definesthe actualshape in this case, this method simply clipsto the bounding rectangle. For more complex overlays, you would want to clip to the path representing your overlay. The results of this drawing code are shown in Figure 5-3 (page 55). Listing 5-9 Drawing a gradient in a custom overlay view - (void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context { // Get the overlay bounding rectangle. MKMapRect theMapRect = [self.overlay boundingMapRect]; CGRect theRect = [self rectForMapRect:theMapRect]; // Clip the context to the bounding rectangle. CGContextAddRect(context, theRect); CGContextClip(context); // Set up the gradient color and location information. Annotating Maps Displaying Overlays on a Map 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 53CGColorSpaceRef myColorSpace = CGColorSpaceCreateDeviceRGB(); CGFloat locations[4] = {0.0, 0.33, 0.66, 1.0}; CGFloat components[16] = {0.0, 0.0, 1.0, 0.5, 1.0, 1.0, 1.0, 0.8, 1.0, 1.0, 1.0, 0.8, 0.0, 0.0, 1.0, 0.5}; // Create the gradient. CGGradientRef myGradient = CGGradientCreateWithColorComponents(myColorSpace, components, locations, 4); CGPoint start, end; start = CGPointMake(CGRectGetMidX(theRect), CGRectGetMinY(theRect)); end = CGPointMake(CGRectGetMidX(theRect), CGRectGetMaxY(theRect)); // Draw. CGContextDrawLinearGradient(context, myGradient, start, end, 0); // Clean up. CGColorSpaceRelease(myColorSpace); CGGradientRelease(myGradient); } Annotating Maps Displaying Overlays on a Map 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 54Figure 5-3 shows the results of drawing custom content over the overlay for the state of Colorado. In this case, the overlay view fills its content with a custom gradient. Figure 5-3 Using a custom overlay view to draw Creating Overlay Views from Your Delegate Object When it needs an overlay view, the map view calls the mapView:viewForOverlay: method of its delegate object. If you do not implement this method, or if you implement it and always return nil, the map view does not display anything for the specified overlay. Therefore, you must implement this method and return a valid overlay view for any overlays you want displayed on the map. For the most part, every overlay is different. Although you should always create your overlay views in your mapView:viewForOverlay: method, you may need to be a little more creative in how you configure those views. If all of your views share the same drawing attributes, you can implement this method in a way similar Annotating Maps Displaying Overlays on a Map 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 55to the one shown in Listing 5-8 (page 51). However, if each overlay uses different colors or drawing attributes, you should find a way to initialize that information using the annotation object, rather than having a large decision tree in this method. Because overlays are typically different from one another, the map view does not recycle those views when they are removed from the map. Instead of dequeueing an existing overlay view, you must create a new overlay view every time. Managing the Map’s Overlay Objects If your app works with more than one overlay, you might need to think about how to manage those objects. Like annotations, the overlays associated with a map are always displayed when any portion of the overlay intersects the visible portion of the map. Unlike annotations, overlays scale proportionally with the map and therefore do not automatically overlap one another. This means, you are less likely to have to remove overlays and add them later to prevent overcrowding. In cases where the bounding rectangles of two overlays do overlap, you can either remove one of the overlays or arrange their Z-order to control which one appears on top. The overlays property of the MKMapView class stores the registered overlays in an ordered array. The order of the objects in this array matches the Z-order of the objects at render time, with the first object in the array representing the bottom of the Z-order. To place an overlay on top of all other overlays, you add it to the end of this array. You can also insert objects at different pointsin the array and exchange the position of two objects in the array using the map view’s methods. If you decide to implement some type of overlap-detection algorithm for overlays, one place to do so is in the mapView:didAddOverlayViews: method of your map view delegate. When this method is called, you can use the MKMapRectIntersectsRect function to see if the added overlay intersects the bounds of any other overlays. If there is an overlap, use whatever custom logic is needed to choose which one should be placed on top in the rendering tree and exchange positions as needed. (Because the map view is an interface item, any modifications to the overlays array should be synchronized and performed on the app’s main thread. The actual comparisons may occur on a different thread, though.) Using Overlays as Annotations The MKOverlay protocol conforms to the MKAnnotation protocol. As a result, all overlay objects are also annotation objects and can be treated as one or both in your code. If you opt to treat an overlay object as both, you are responsible for managing that object in two places. If you want to display both an overlay view Annotating Maps Using Overlays as Annotations 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 56and annotation view for it, you must implement both the mapView:viewForOverlay: and mapView:viewForAnnotation: methodsin your app delegate. It also meansthat you must add and remove the object from both the overlays and annotations arrays of your map. Annotating Maps Using Overlays as Annotations 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 57In iOS 6 and later, Map Kit offerssupport for providing map-based directionsto the user. Apps can be a provider of directions or they can use the Maps app itself to provide directions. Appsthat consume direction information do so by sending an appropriate request to the Maps app, which then handles the task of displaying that information to the user. However, if you are implementing a navigation app of your own, you can register your app as a routing app—that is, a provider of directions. When the Maps app receives direction requests from the user (or other apps), it can then forward those requests to your app for display. Asking the Maps App to Display Directions Map Kit provides a way for you to display specific map locations or turn-by-turn directions using the Maps app. This support allows apps to use the Maps app in situations where you might not want to display the map data yourself. For example, if your app does not have its own turn-by-turn navigation services, you can ask Maps to provide the information for you. To generate a direction request, use the openMapsWithItems:launchOptions: or openInMapsWithLaunchOptions: method of MKMapItem. These methods let you send map items to the Maps app so that it can display them. If you include the MKLaunchOptionsDirectionsModeKey key with the launch options you pass to these methods, Maps attempts to display directions from the start and end points you specify. For information about how to use these methods, see MKMapItem Class Reference . Registering as a Routing App Apps that are able to display point-to-point directions can register as a routing app and make those directions available to the Maps app and to all other apps on a user’s device by extension. Registering as a routing app improves the user experience by giving other apps a means to access routing information from your app, thus avoiding the need for every app to provide its own routing directions. It is also a great way to get your app in front of the user. Maps always displays appropriate suggestions from the App Store as options for displaying directions. To register your app as a directions provider, you must do the following: 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 58 Providing Directions● Configure your app’s Info.plist with the keys needed to indicate the type of directions your app offers and the handlers you use to process incoming directions requests. ● Declare the map regions that your app supports using a geographic coverage file (specified using a GeoJSON file). ● Process direction request URLs when they are sent to your app. Configuring Your App to Accept Direction Requests To enable directions support for your app, you must configure the following support for your app target in Xcode: ● Enable directions support for your app. ● Configure a special document type to handle requests for directions. You enable directions support in the Maps section of your target’s Summary tab. In addition to enabling directions, you also specify the types of directions (pedestrian, car, subway, and so on) your app is able to provide. Enabling directions support adds the MKDirectionsApplicationSupportedModes key to your app’s Info.plist file and sets the value of the key to the transportation modes you select. These keys act as a signal to the system (and to iTunes Connect) that your app provides directions and has an associated GeoJSON file. (For more information about specifying the GeoJSON file, see “Declaring the Supported Geographic Coverage for Directions” (page 60).) In addition to declaring the types of directions your app supports, you need to declare support for a special document type. The Maps app uses this document type to send URLs with direction requests to your app. To add the document type, use the Xcode document type editor, located in the Info tab of your target. After adding a new document type, use the information in Table 6-1 to set the values for the type. You should use the values in this table exactly as they appear here. Table 6-1 Keys and values for the directions request document type Xcode field Value Description The value in this field can be anything you want, but you are encouraged to use the suggested value. Name MKDirectionsRequest The value of this key is a custom UTI type used to identify direction requests. The value of this key must be exactly as shown here. Types com.apple.maps.directionsrequest Providing Directions Registering as a Routing App 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 59The changes you make in the document types editor cause Xcode to add a corresponding entry to the CFBundleDocumentTypes key in your app’s Info.plist file. For more information about your app’s Info.plist file and the keys you put into it, see Information Property List Key Reference . Declaring the Supported Geographic Coverage for Directions Apps must declare the geographic regions for which they are capable of providing directions. Declaring the supported regions prevents the system from sending requests that your app is unable to handle. For example, if your app provides subway route information only for New York, you would not want it to receive requests to provide directions in London. To declare your app’s supported regions, you must create a GeoJSON file, which is a type of JavaScript Object Notation (JSON) file. This is your app’s geographic coverage file and it contains a set of map coordinates that define the boundaries of one or more geographic regions. The format of thisfile is part of a public specification, the details of which you can obtain at http://geojson.org/geojson-spec.html. Your geographic coverage file is used by the Maps app and the App Store, but not by your app. Uploading it to iTunes Connect makes it possible for Maps to look up apps on the App Store that are capable of providing directions in the target region. It can then provide the user with that information in case the user wants to download one of those apps. Because you upload it to iTunes Connect, you can also update the file at any time without submitting a new version of your app. Specifying the Geographic Coverage File Contents The geographic coverage file for an iOS app must contain a single MultiPolygon shape that defines the boundaries of the supported geographic regions. A single multi polygon may contain any number of child polygons, each of which defines the boundaries around a single geographic region. Each polygon contains four or more coordinate valuesthat define the boundaries of the polygon. Per the GeoJSON specification, every polygon must represent a closed region—that is, the first and last coordinate values must always be identical. Therefore, you must specify at least four points to define a triangular region, which is the simplest possible shape. Of course, you can use include more points to define more complex polygons. Listing 6-1 shows an example of a geographic coverage file that specifies two separate regions: one around San Francisco and one around Chicago. Note that the set of coordinates for each region are surrounded by whatseem to be an extra set of brackets. In each case, the first open bracket marksthe beginning of the overall polygon shape, the second open bracket defines the beginning of the exterior bounding polygon, and the third open bracket marks the beginning of the first coordinate. After closing the exterior bounding polygon, you could add additional sets of points that define holes in the polygonal region. Providing Directions Registering as a Routing App 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 60Listing 6-1 A sample GeoJSON file { "type": "MultiPolygon", "coordinates": [ [[[-122.7, 37.3], [-121.9, 37.3], [-121.9, 37.9], [-122.7, 37.9], [-122.7, 37.3]]], [[[-87.9, 41.5], [-87.3, 41.5], [-87.3, 42.1], [-87.9, 42.1], [-87.9, 41.5]]] ] } Use the following guidelines to help you when defining the regions for your app: ● Keep your regions simple and do not try to trace precise routes around a given geographic area. Although you can technically use hundreds of coordinates to define a region, doing so is inefficient and usually unnecessary. The system has to determine whether a given point is inside one of your polygons. Using a shape that contains hundreds of points is far less efficient than specifying a rectangular polygon around the region. ● Only specify regions for which you can provide useful directions to the user. ● Use only MultiPolygon shape in your app’s coverage file. Although the GeoJSON specification supports other types of shapes, only MultiPolygon shapes are supported for routing apps. ● Do not include comments in your coverage file. ● All coordinates must be specified as a longitude followed by a latitude value. ● The polygonsin your coverage files must not include holes. Although holes are supported by the GeoJSON specification, they are not supported in Apple’s maps implementation. Uploading Your GeoJSON File to iTunes Connect When you upload your app to iTunes Connect, the server checks your app’s Info.plist file for the presence of the MKDirectionsApplicationSupportedModes key. If that key is present, the iTunes Connect page for your app includes a space for uploading your geographic coverage file. You must upload the file before your app can be approved. See “Uploading Icons, Screenshots, and Routing Files for Your App” in iTunes Connect Developer Guide for more information. Debugging Your App’s Geographic Coverage File During development, you use the scheme options of your Xcode project to specify the geographic coverage file to use during testing. When you run your app in the simulator, Xcode transfers this file to the simulator or device so that the Maps app knows about the regions your app supports. The content of this file should be identical to the file you plan to upload to iTunes Connect. Providing Directions Registering as a Routing App 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 61To specify the geographic coverage file for testing, do the following: 1. Open the scheme editor for your project. 2. Select the Run (Debug) scheme for your project. 3. In the Options tab, select your coverage file from the Routing App Coverage File popup menu. After installing your app on the device or simulator, exit your app and launch the Maps app to specify the start and end points for directions. Your app should appear if its geographic coverage file is valid and contains the two specified points. If it does not, check the pointsfor your geographical regionsto make sure they are correct. Note: If you are running in the simulator and the Maps does not display your app as one of the possible options, check the Console app for any possible error messages. Mapsreports any problems it encounters when reading your app’s GeoJSON to the console output rather than to Xcode. Handling Direction Requests The system sends direction requests to your app using URLs. When the user asks the Maps app for directions and chooses your app, Maps creates a URL with the start and end points and asks your app to open it. You handle the opening of this URL in your app’s application:openURL:sourceApplication:annotation: method, just like you would for other URLs. But the steps you take to processthe URL are a little more prescribed. When your app receives a URL to open, it should perform the following steps in its application:openURL:sourceApplication:annotation: method: 1. Call the isDirectionsRequestURL: class method of MKDirectionsRequest to check whether the URL is a directions request URL. If it is a directions request, proceed with the remaining steps. 2. Create an MKDirectionsRequest object using the provided URL. 3. Obtain the start and end points of the route from the MKDirectionsRequest object. The start and end points are specified as MKMapItem objects, which contain the geographic coordinate of the location and possibly additional information. If the MKMapItem object represents the user’s current location, you need to use Core Location to retrieve the actual coordinate location data yourself. 4. Compute and display the route using your custom routing technology. Because the preceding steps are the same for every app, you can include code in your application:openURL:sourceApplication:annotation: method similar to that shown in Listing 6-2. The most important addition you must make is to compute the route information and display it in your app. If your app handles other URL types, you would also include code for processing those URLs separately. Providing Directions Registering as a Routing App 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 62Listing 6-2 Handling a directions request URL - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { if ([MKDirectionsRequest isDirectionsRequestURL:url]) { MKDirectionsRequest* directionsInfo = [[MKDirectionsRequest alloc] initWithContentsOfURL:url]; // TO DO: Plot and display the route using the // source and destination properties of directionsInfo. return YES; } else { // Handle other URL types... } return NO; } For additional information about using the MKDirectionsRequest class, see MKDirectionsRequest Class Reference . Providing Directions Registering as a Routing App 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 63Creating Draggable Annotations in Earlier Versions of iOS If you want to support draggable annotationsin iOS 3.x, you must implement the code for tracking drag-related touches yourself. Although they live in a special layer above the map content, annotation views are full-fledged views capable of receiving touch events. You can use these events to detect hits within the view and initiate a drag operation. Note: Because maps are displayed in a scrolling interface, there is typically a short delay between the time the user touches your custom view and the time corresponding events are delivered. This delay gives the underlying scroll view a chance to determine whether the touch event is part of a scrolling gesture. The following sequence of code listings shows you how to implement a user-movable annotation view in iOS 3.x. In this example, the annotation view displays a bulls-eye image directly over the annotation’s coordinate point and includes a custom accessory view for displaying details about the target. Listing A-1 shows the definition of the BullseyeAnnotationView class. The class includes some additional member variables that it uses during tracking to move the view correctly. It also stores a pointer to the map view itself, the value for which is set by the code in the mapView:viewForAnnotation: method when it creates or reinitializes the annotation view. The map view object is needed when event tracking is finished to adjust the map coordinate of the annotation object. Listing A-1 The BullseyeAnnotationView class @interface BullseyeAnnotationView : MKAnnotationView { BOOL isMoving; CGPoint startLocation; CGPoint originalCenter; MKMapView* map; } 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 64 Legacy Map Techniques@property (assign,nonatomic) MKMapView* map; - (id)initWithAnnotation:(id )annotation; @end @implementation BullseyeAnnotationView @synthesize map; - (id)initWithAnnotation:(id )annotation { self = [super initWithAnnotation:annotation reuseIdentifier:@"BullseyeAnnotation"]; if (self) { UIImage* theImage = [UIImage imageNamed:@"bullseye32.png"]; if (!theImage) return nil; self.image = theImage; self.canShowCallout = YES; self.multipleTouchEnabled = NO; map = nil; UIButton* rightButton = [UIButton buttonWithType: UIButtonTypeDetailDisclosure]; [rightButton addTarget:self action:@selector(myShowAnnotationAddress:) forControlEvents:UIControlEventTouchUpInside]; self.rightCalloutAccessoryView = rightButton; } return self; } @end Legacy Map Techniques Creating Draggable Annotations in Earlier Versions of iOS 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 65When a touch event first arrives in a bulls-eye view, the touchesBegan:withEvent: method of that class records information about the initial touch event, as shown in Listing A-2. It uses this information later in its touchesMoved:withEvent: method to adjust the position of the view. All location information is stored in the coordinate space of the superview. Listing A-2 Tracking the view’s location @implementation BullseyeAnnotationView (TouchBeginMethods) - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { // The view is configured for single touches only. UITouch* aTouch = [touches anyObject]; startLocation = [aTouch locationInView:[self superview]]; originalCenter = self.center; [super touchesBegan:touches withEvent:event]; } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { UITouch* aTouch = [touches anyObject]; CGPoint newLocation = [aTouch locationInView:[self superview]]; CGPoint newCenter; // If the user's finger moved more than 5 pixels, begin the drag. if ( (abs(newLocation.x - startLocation.x) > 5.0) || (abs(newLocation.y - startLocation.y) > 5.0) ) isMoving = YES; // If dragging has begun, adjust the position of the view. if (isMoving) { newCenter.x = originalCenter.x + (newLocation.x - startLocation.x); newCenter.y = originalCenter.y + (newLocation.y - startLocation.y); self.center = newCenter; } Legacy Map Techniques Creating Draggable Annotations in Earlier Versions of iOS 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 66else // Let the parent class handle it. [super touchesMoved:touches withEvent:event]; } @end When the userstops dragging an annotation view, you need to adjust the coordinate of the original annotation to ensure the view remains in the new position. Listing A-3 shows the touchesEnded:withEvent: method forthe BullseyeAnnotationView class. Thismethod usesthemapmember variable to convertthe pixel-based point into a map coordinate value. Because the coordinate property of an annotation is normally read-only, the annotation object in this case implements a custom changeCoordinate method to update the value it stores locally and reports using the coordinate property. If the touch event was canceled for some reason, the touchesCancelled:withEvent: method returns the annotation view to its original position. Listing A-3 Handling the final touch events @implementation BullseyeAnnotationView (TouchEndMethods) - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { if (isMoving) { // Update the map coordinate to reflect the new position. CGPoint newCenter = self.center; BullseyeAnnotation* theAnnotation = self.annotation; CLLocationCoordinate2D newCoordinate = [map convertPoint:newCenter toCoordinateFromView:self.superview]; [theAnnotation changeCoordinate:newCoordinate]; // Clean up the state information. startLocation = CGPointZero; originalCenter = CGPointZero; isMoving = NO; } else [super touchesEnded:touches withEvent:event]; } Legacy Map Techniques Creating Draggable Annotations in Earlier Versions of iOS 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 67- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { if (isMoving) { // Move the view back to its starting point. self.center = originalCenter; // Clean up the state information. startLocation = CGPointZero; originalCenter = CGPointZero; isMoving = NO; } else [super touchesCancelled:touches withEvent:event]; } @end Legacy Map Techniques Creating Draggable Annotations in Earlier Versions of iOS 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 68This table describes the changes to Location Awareness Programming Guide . Date Notes 2012-09-19 Added information about how to support custom routing directions. 2011-10-12 Added information about the new Core Location geocoders. 2010-05-20 Added information about region monitoring. Added information about creating overlays. Expanded the existing information about maps and annotations. Updated the location-related sections to cover new technologies for obtaining the user’s location. 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 69 Document Revision HistoryApple Inc. © 2012 Apple Inc. All rights reserved. No part of this publication may be reproduced, stored in a retrievalsystem, or transmitted, in any form or by any means, mechanical, electronic, photocopying, recording, or otherwise, without prior written permission of Apple Inc., with the following exceptions: Any person is hereby authorized to store documentation on a single computer for personal use only and to print copies of documentation for personal use provided that the documentation contains Apple’s copyright notice. No licenses, express or implied, are granted with respect to any of the technology described in this document. Apple retains all intellectual property rights associated with the technology described in this document. This document is intended to assist application developers to develop applications only for Apple-labeled computers. Apple Inc. 1 Infinite Loop Cupertino, CA 95014 408-996-1010 Apple, the Apple logo, Chicago, iTunes, New York, Objective-C, and Xcode are trademarks of Apple Inc., registered in the U.S. and other countries. App Store is a service mark of Apple Inc. Java is a registered trademark of Oracle and/or its affiliates. iOS is a trademark or registered trademark of Cisco in the U.S. and other countries and is used under license. Even though Apple has reviewed this document, APPLE MAKES NO WARRANTY OR REPRESENTATION, EITHER EXPRESS OR IMPLIED, WITH RESPECT TO THIS DOCUMENT, ITS QUALITY, ACCURACY, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.ASARESULT, THISDOCUMENT IS PROVIDED “AS IS,” AND YOU, THE READER, ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND ACCURACY. IN NO EVENT WILL APPLE BE LIABLE FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL,OR CONSEQUENTIAL DAMAGES RESULTING FROM ANY DEFECT OR INACCURACY IN THIS DOCUMENT, even if advised of the possibility of such damages. THE WARRANTY AND REMEDIES SET FORTH ABOVE ARE EXCLUSIVE AND IN LIEU OF ALL OTHERS, ORAL OR WRITTEN, EXPRESS OR IMPLIED. No Apple dealer, agent, or employee is authorized to make any modification, extension, or addition to this warranty. Some states do not allow the exclusion or limitation of implied warranties or liability for incidental or consequential damages, so the above limitation or exclusion may not apply to you. This warranty gives you specific legal rights, and you may also have other rights which vary from state to state. Shark User Guide (Legacy)Contents Introduction 12 Overview 12 Philosophy 12 Organization of This Document 13 Getting Started with Shark 16 Main Window 16 Mini Configuration Editors 18 Perform Sampling 18 Session Windows and Files 19 Session Files 20 Session Information Sheet 21 Session Report 22 Advanced Settings Drawer 22 Shark Preferences 23 Time Profiling 28 Statistical Sampling 28 Taking a Time Profile 30 Profile Browser 31 Heavy View 35 Tree View 35 Profile Display Preferences 37 Chart View 39 Advanced Chart View Settings 42 Code Browser 45 Assembly Browser 48 Advanced Code Browser Settings 50 ISA Reference Window 54 Tips and Tricks 56 Example: Optimizing MPEG-2 using Time Profiles 58 Base 58 Vectorization 60 Retired Document | 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 2System Tracing 63 Tracing Methodology 63 Basic Usage 64 Interpreting Sessions 66 Summary View In-depth 67 Trace View In-depth 73 Timeline View In-depth 77 Sign Posts 90 Tips and Tricks 93 Other Profiling and Tracing Techniques 97 Time Profile (All Thread States) 97 Malloc Trace 101 Using a Malloc Trace 102 Advanced Display Options 105 Static Analysis 107 Using Shark with Java Programs 108 Java Tracing Techniques 109 Linking Shark with the Java Virtual Machine 110 Event Counting and Profiling Overview 111 Timed Counters: The Performance Counter Spreadsheet 111 Event-Driven Counters: Correlating Events with Your Code 119 Advanced Profiling Control 122 Process Attach 122 Process Launch 122 Batch Mode 125 Windowed Time Facility (WTF) 125 WTF with System Trace 127 Unresponsive Application Measurements 128 Command Line Shark 129 Basic Methodology 130 Common Options 131 Target Selection 132 Reports 133 Custom Configurations 133 More Information 134 Interprocess Remote Control 134 Programmatic Control 134 Command Line Remote Control 137 Retired Document | 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 3 ContentsNetwork/iPhone Profiling 138 Using Shared Profiling Mode 141 Mac OS X Firewall Considerations 143 Advanced Session Management and Data Mining 145 Automatic Symbolication Troubleshooting 145 Symbol Lookup 145 Debugging Information 146 Manual Session Symbolication 146 Managing Sessions 150 Comparing Sessions 150 Merging Sessions 151 Data Mining 151 Callstack Data Mining 152 Perf Count Data Mining 157 Example: Using Data Mining with a Time Profile 158 A Performance Problem... 158 Taking Samples 160 High Level Analysis 162 Analysis Via Source Navigation 163 Introduction To Focusing 168 Dig Deeper by Charging Costs 173 Example: Graphical Analysis using Chart View with a Malloc Trace 176 Taking Samples 176 Graphical Analysis of a Malloc Trace 179 Custom Configurations 183 The Config Editor 184 Simple Timed Samples and Counters Config Editor 186 Malloc Data Source PlugIn Editor 189 Static Analysis Data Source PlugIn Editor 190 Java Trace Data Source PlugIn Editor 191 Sampler Data Source PlugIn Editor 192 System Trace Data Source PlugIn Editor 193 All Thread States Data Source PlugIn Editor 194 Analysis and Viewer PlugIn Summary 195 Counter Spreadsheet Analysis PlugIn Editor 196 Using the Editor 196 Spreadsheet Configuration Example 199 Retired Document | 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 4 ContentsHardware Counter Configuration 202 Configuring the Sampling Technique: The Sampling Tab 202 Common Elements in Performance Counter Configuration Tabs 206 Counter Control 206 Privilege Level Filtering 207 Process Marking 207 MacOS X OS-Level Counters Configuration 208 Intel CPU Performance Counter Configuration 209 PowerPC G3/G4/G4+ CPU Performance Counter Configuration 211 PowerPC G5 (970) Performance Counter Configuration 213 PowerPC North Bridge Counter Configuration 221 U1.5/U2 North Bridges 222 U3 North Bridge 223 U4 (Kodiak) North Bridge 226 ARM11 CPU Performance Counter Configuration 229 Command Reference 230 Menu Reference 230 Shark 230 File 230 Edit 231 Format 233 Config 233 Sampling 234 Data Mining 235 Window 235 Help 236 Alphabetical Reference 236 Miscellaneous Topics 242 Code Analysis with the G5 (PPC970) Model 242 Supervisor Space Sampling Guidelines 243 Intel Core Performance Counter Event List 246 Intel Core 2 Performance Counter Event List 252 PPC 750 (G3) Performance Counter Event List 263 PPC 7400 (G4) Performance Counter Event List 265 Retired Document | 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 5 ContentsPPC 7450 (G4+) Performance Counter Event List 271 PPC 970 (G5) Performance Counter Event List 282 UniNorth-2 (U1.5/2) Performance Counter Event List 315 UniNorth-3 (U3) Performance Counter Event List 318 Kodiak (U4) Performance Counter Event List 322 ARM11 Performance Counter Event List 326 Document Revision History 328 Retired Document | 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 6 ContentsFigures, Tables, and Listings Getting Started with Shark 16 Figure 1-1 Main Window 16 Figure 1-2 Process Target 17 Figure 1-3 Mini Configuration Editor 18 Figure 1-4 Session Inspector Panel 21 Figure 1-5 Sample Window with Advanced Settings Drawer visible at right 23 Figure 1-6 Shark Preferences — Appearance 24 Figure 1-7 Shark Preferences — Sampling 25 Figure 1-8 Shark Preferences — Sessions 26 Figure 1-9 Shark Preferences — Search Paths 27 Time Profiling 28 Figure 2-1 Execution Before Sampling 29 Figure 2-2 Sampling Results 29 Figure 2-3 Time Profile mini-configuration editor 31 Figure 2-4 The Profile Browser 32 Figure 2-5 Tuning Advice 33 Figure 2-6 Callstack Table 34 Figure 2-7 Heavy Profile View Detail 35 Figure 2-8 Tree Profile View 36 Figure 2-9 Profile Analysis Preferences 37 Figure 2-10 Chart View 40 Figure 2-11 Advanced Settings for the Chart View 44 Figure 2-12 Code Browser 45 Figure 2-13 Hot Spot Scrollbar 47 Figure 2-14 Assembly Browser 50 Figure 2-15 Advanced Settings for the Code Browser 53 Figure 2-16 x86 Asm Browser Advanced Settings 54 Figure 2-17 ARM Asm Browser Advanced Settings 54 Figure 2-18 ISA Reference Window 55 Figure 2-19 Original Time Profile, with Tuning Advice 59 Figure 2-20 Code Browser with Vectorization Hint 61 Figure 2-21 Time Profile after Vectorizing IDCT 61 Table 2-1 MPEG-2 Performance Improvement 61 Retired Document | 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 7System Tracing 63 Figure 3-1 Time Profile vs. System Trace Comparison 64 Figure 3-2 System Trace Mini Config Editor 65 Figure 3-3 Summary View 67 Figure 3-4 Summary View: Scheduler 68 Figure 3-5 Summary View: System Calls 69 Figure 3-6 Summary View: VM Faults 71 Figure 3-7 Summary View Advanced Settings Drawer 72 Figure 3-8 Trace View: Scheduler 74 Figure 3-9 Trace View: System Calls 75 Figure 3-10 Trace View: VM Faults 77 Figure 3-11 Timeline View 78 Figure 3-12 Timeline View: Thread Run Intervals 79 Figure 3-13 Thread Run Interval Inspector 79 Figure 3-14 Timeline View: System Calls 81 Figure 3-15 System Call Inspector 82 Figure 3-16 Timeline View: VM Faults 83 Figure 3-17 VM Fault Inspector 84 Figure 3-18 Interrupt Inspector 85 Figure 3-19 Sign Post Inspector 86 Figure 3-20 Timeline View Advanced Settings Drawer 89 Listing 3-1 ~/Library/Application Support/Shark/KDebugCodes/myFirstSignPosts 90 Listing 3-2 signPostExample.c 92 Listing 3-3 testKernelSignPost.c 92 Other Profiling and Tracing Techniques 97 Figure 4-1 Time Profile (All Thread States) mini configuration editor 98 Figure 4-2 Time Profile (All Thread States) session, heavy view 99 Figure 4-3 Time Profile (All Thread States) session, tree view 100 Figure 4-4 Malloc Trace mini configuration editor 102 Figure 4-5 Malloc Trace session, profile browser 103 Figure 4-6 Malloc Trace session, chart view 104 Figure 4-7 Enabling Malloc Trace Advanced Options 105 Figure 4-8 Additional Malloc Trace Charts 106 Figure 4-9 Static Analysis mini configuration editor 108 Figure 4-10 How Shark-for-Java differs from regular Shark configurations 109 Figure 4-11 Performance Counter Spreadsheet 114 Figure 4-12 Counters Menu 115 Figure 4-13 Performance Counter Spreadsheet: Advanced Settings 116 Retired Document | 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 8 Figures, Tables, and ListingsFigure 4-14 Chart View with additional timed counter graphs 121 Advanced Profiling Control 122 Figure 5-1 Process Attach 122 Figure 5-2 Launch Process Panel 123 Figure 5-3 Batch Mode 125 Figure 5-4 Normal Profiling Workflow 126 Figure 5-5 Windowed Time Facility Workflow 126 Figure 5-6 The Windowed Time Facility Timeline 128 Figure 5-7 Unresponsive Application Triggering 129 Figure 5-8 Samples Taken for Towers of Hanoi N=10..20 137 Figure 5-9 Network/iPhone Manager 139 Figure 5-10 Command Line Shark in Network Profiling Mode 142 Figure 5-11 Sharing Firewall Warning Dialog 143 Figure 5-12 Firewall Sharing Preferences, while adding a new port range for Shark 144 Listing 5-1 Towers of Hanoi Source Code 135 Listing 5-2 Instrumented Towers of Hanoi 135 Advanced Session Management and Data Mining 145 Figure 6-1 Session Inspector: Symbols 147 Figure 6-2 Symbolication Dialog 148 Figure 6-3 Before Symbolication 149 Figure 6-4 After Symbolication 150 Figure 6-5 Example Callstacks 153 Figure 6-6 Heavy View 153 Figure 6-7 Tree View 154 Figure 6-8 Data Mining Advanced Settings 155 Figure 6-9 Contextual Data Mining Menu 157 Figure 6-10 Perf Count Data Mining Palette 158 Figure 6-11 Example Shapes 159 Figure 6-12 Example Shapes, Replicated 160 Figure 6-13 Sampling a Specific Process 161 Figure 6-14 Default Profile View 161 Figure 6-15 Navigation Via the Call-Stack Pane 163 Figure 6-16 Navigation Via the Call-Stack Pane with Tree View 163 Figure 6-17 Source View: SKTGraphicView selectAll 164 Figure 6-18 Source View: NSObject 165 Figure 6-19 Source View: SKTGraphicView selectGraphic 166 Figure 6-20 Source View: SKTGraphicView invalidateGraphic 167 Figure 6-21 Tree view before focusing 168 Retired Document | 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 9 Figures, Tables, and ListingsFigure 6-22 Data Mining Contextual Menu 168 Figure 6-23 After Focus Symbol -[SKTGraphicView drawRect:] 169 Figure 6-24 After focus and expansion 170 Figure 6-25 Source View: SKTGraphic drawInView:isSelected: 171 Figure 6-26 Source View: SKGraphic drawHandlesInView: 172 Figure 6-27 Source View: SKGraphic drawHandleAtPoint:inView: 173 Figure 6-28 Heavy View of Focused Sketch 174 Figure 6-29 Expanded Heavy View of Focused Sketch 174 Figure 6-30 After Charge Library libRIP.A.dylib 175 Figure 6-31 After Flatten Library 175 Figure 6-32 Malloc Trace Main Window 177 Figure 6-33 Result of Malloc Sampling 178 Figure 6-34 Chart View 179 Figure 6-35 Place to Select 180 Figure 6-36 Graph View with Call-Stack Pane 182 Custom Configurations 183 Figure 7-1 Main Configuration Menu 183 Figure 7-2 Config Editor 186 Figure 7-3 Simple Timed Samples and Counters Data Source - Sampling Tab 187 Figure 7-4 Simple Timed Samples and Counters Data Source - Counter Settings 188 Figure 7-5 Malloc Data Source - Sampling Settings 189 Figure 7-6 Static Analysis Data Source - Settings 190 Figure 7-7 Java Trace Data Source - Sampling Settings 191 Figure 7-8 Sampler Data Source - Settings 192 Figure 7-9 System Trace Data Source - Settings 193 Figure 7-10 All Thread States Data Source - Settings 194 Figure 7-11 Counter Spreadsheet Analysis 196 Figure 7-12 Choosing a counter-based starting configuration 199 Figure 7-13 Enabling two performance counters 200 Figure 7-14 Performance Spreadsheet: Shortcut Equation 201 Hardware Counter Configuration 202 Figure 8-1 Timed Samples & Counters Data Source - Advanced Sampling Tab 203 Figure 8-2 A typical set of performance counter controls 206 Figure 8-3 Process Marker 208 Figure 8-4 MacOS X Performance Counters Configuration 209 Figure 8-5 Intel Core 2 Configuration Tab 211 Figure 8-6 PowerPC G4+ Configuration Tab (G3 and G4 are similar) 213 Figure 8-7 PowerPC 970 Processor Performance Counters Configuration 215 Retired Document | 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 10 Figures, Tables, and ListingsFigure 8-8 PowerPC 970 IMC (IFU) Configuration Tab 217 Figure 8-9 PowerPC 970 IMC (IDU) Configuration Tab 221 Figure 8-10 U1.5/U2 Configuration Tab 223 Figure 8-11 U3 Memory Configuration Tab 225 Figure 8-12 U3 API Configuration Tab 226 Figure 8-13 U4 (Kodiak) Memory Configuration Tab 227 Figure 8-14 U4 (Kodiak) API Configuration Tab 228 Figure 8-15 ARM11 Counter Configuration Tab 229 Miscellaneous Topics 242 Figure B-1 PPC970 Resource Modeling 243 Figure B-2 Timer Sampling in the Kernel 244 Figure B-3 CPU PMI Sampling in the Kernel 245 Retired Document | 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 11 Figures, Tables, and ListingsImportant: This document may not represent best practices for current development. Links to downloads and other resources may no longer be valid. Overview Shark is a tool for performance understanding and optimization. Why is it called “Shark?” Performance tuning requires a hunter’s mentality, and no animal is as pure in this quest as a shark. A shark is also an expert in his field — one who uses all potential resources to achieve his goals. The name “Shark” embodies the spirit and emotion you should have when tuning your code. To help you analyze the performance of your code, Shark allows you to profile the entire system (kernel and drivers as well as applications). At the simplest level, Shark profiles the system while your code is running to see where time is being spent. It can also produce profiles of hardware and software performance events such as cache misses, virtual memory activity, memory allocations, function calls, or instruction dependency stalls. This information is an invaluable first step in your performance tuning effort so you can see which parts of your code or the system are the bottlenecks. In addition to showing you where time is being spent, Shark can give you advice on how to improve your code. Shark is capable of identifying many common performance pitfalls and visually presents the costs of these problems to you. Philosophy The first and most important step when optimizing your code is to determine what to optimize. In a program of moderate complexity, there can be thousands of different code paths. Optimizing all of them is normally impractical due to deadlines and limited programmer resources. There are also more subtle tradeoffs between optimized code and portability and maintenance that limit candidates for optimization. Here are a few general guidelines for finding a good candidate for optimization: 1. It should be time-critical. This is generally any operation that is perceptibly slow; the user has to wait for the computer to finish doing something before continuing. Optimizing functionality that is already faster than the user can perceive is usually unnecessary. Retired Document | 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 12 Introduction2. It must be relevant. Optimizing functionality that is rarely used is usually counter-productive. 3. It shows up as a hot spot in a time profile. If there is no obvious hot spot in your code or you are spending a lot of time in system libraries, performance is more likely to improve through high-level improvements (architectural changes). Low-level optimizationstypically focus on a single segment of code and make it a better match to the hardware and software systemsit is being run on. Examples of low-level optimizationsinclude using vector or cache hint instructions. High-level optimizations include algorithmic or other architectural changes to your program. Examples of high-level optimizations include data structure choice (for example, switching from a linked list to a hash-table) or replacing calls to computationally expensive functions with a cache or lookup table. Remember, it is critical to profile before investing your time and effort in optimization. Sadly, many programmers invest prodigious amounts of effort optimizing what their intuition tellsthem isthe performance-criticalsection of code only to realize no performance improvement. Profiling quickly reveals that bottlenecks often lie far from where programmers might assume they are. Using Shark, you can focus your optimization efforts on both algorithmic changes and tuning performance-critical code. Often, even small changesto a critical piece of code can yield large overall performance improvements. By default, Shark creates a profile of execution behavior by periodically interrupting each processor in the system and sampling the currently running process, thread, and instruction address as well as the function callstack. Along with this contextual information, Shark can record the values of hardware and software performance counters. Each counter is capable of counting a wide variety of performance events. In the case of processor and memory controller counters, these include detailed, low-level information that is otherwise impossible to know without a simulator. The overhead for sampling with Shark is extremely low because all sample collection takes place in the kernel and is based on hardware interrupts. A typical sample incurs an overhead on the order of 20µs. This overhead can be significantly larger if callstack recording is enabled and a virtual memory fault is incurred while saving the callstack. Time profiles generated by Shark are statistical in nature; they give a representative view of what wasrunning on the system during a sampling session . Samples can include all of the processes running on the system from both user and supervisor code, or samples can be limited to a specific process or execution state. Shark’s sampling period can be an arbitrary time interval (timer sampling). Shark also has the ability to use a performance event as the sampling trigger (event sampling). Using event sampling, it is possible to associate performance events such as cache misses or instruction stalls with the code that caused them. Additionally, Shark can generate exact profiles for specific function calls or memory allocations. Organization of This Document This manual is organized into four major sections, each consisting of two or three chapters, plus several appendices. Here is a brief “roadmap” to help you orient yourself: Introduction Organization of This Document Retired Document | 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 13● Getting Started with Shark— This introduction and “Getting Started with Shark” (page 16) are designed to give you an overall introduction to Shark. After covering some basic philosophy here, “Getting Started with Shark” (page 16) describes basic ways to use Shark to sample your applications, features of the Session windows that open after you sample your applications, and the use of Shark’s global preferences. ● Profiling Configurations— Three chapters discuss Shark’s default Configurations — its methods of collecting samples from your system or applications — and presentation of the sampled results in Session windows. These chapters are probably the most important ones. “Time Profiling” (page 28) discusses Time Profiling , the most frequently used configuration, which gives a statistical profile of processor utilization. System Tracing , discussed in “System Tracing” (page 63), provides an exact trace of user-kernel transitions, and is useful both to debug interactions between your program and the underlying system and to provide a “microscope” to examine multithreaded programming issues in detail. After the complete chapters devoted to these two configurations, the remainder are covered in “Other Profiling and Tracing Techniques” (page 97). Time Profile (All Thread States) is a variant of Time Profile that also samples blocked threads, and as a result is a good way to get an overview of locking behavior in multithreaded applications. Malloc Trace allows you to examine memory allocation and deallocation activity in detail. Shark can apply Static Analysis to your application in order to quickly examine rarely-traversed code paths. Equivalents for Time Profile , Malloc Trace , and an exact Call Trace , all customized for use with Java applications, are also available. Finally, the chapter gives an overview of Shark’s extensive performance counter recording and analysis capabilities. ● Advanced Techniques—Shark’s basic techniquesforsampling and analysis are sufficient for most purposes, but with complex applications you may need more sophisticated techniques. “Advanced Profiling Control” (page 122) covers waysto start and stop Shark’ssampling very precisely, allowing you to carefully control what issampled, in advance. You can also learn how to control Shark remotely from other machines or even to control Shark running on iOS devices attached to your machine in this chapter. “Advanced Session Management and Data Mining” (page 145) looks at Shark’s symbol management and data mining techniques, which are ways to very precisely select subsets of your samples for examination after they are taken. ● Custom Configurations— Shark is not just limited to its default configurations. If you want to save your own custom settings for a configuration or create a new one from scratch, then you will want to check out chapters “Custom Configurations” (page 183) and “Hardware Counter Configuration” (page 202). The first describes how you may make adjustments to the existing configurations, while the latter covers the many options relating to the use of hardware performance counters. Because there are so many different possible combinations of performance counters, only a limited number of the possibilities are covered by the default configurations. Hence, thisislikely to be the main area where the use of custom configurations will be necessary for typical Shark users. ● Appendices— The first appendix, “Command Reference” (page 230), provides a brief reference to Shark’s menu commands. The second, “Miscellaneous Topics” (page 242), describes several minor, miscellaneous options that do not really fit in anywhere else or are of interest only to a small minority of Shark users. The Introduction Organization of This Document Retired Document | 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 14remainder of the appendices (“Intel Core Performance Counter Event List” (page 246), “Intel Core 2 Performance Counter Event List” (page 252), “PPC 750 (G3) Performance Counter Event List” (page 263), “PPC 7400 (G4) Performance Counter Event List” (page 265), “PPC 7450 (G4+) Performance Counter Event List” (page 271),“PPC 970 (G5) Performance Counter Event List” (page 282),“UniNorth-2 (U1.5/2) Performance Counter Event List” (page 315), “UniNorth-3 (U3) Performance Counter Event List” (page 318), and “Kodiak (U4) Performance Counter Event List” (page 322)) provide a reference for the performance counters that you can measure with Shark. Introduction Organization of This Document Retired Document | 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 15Starting to use Shark is a relatively simple process. You only need to choose one or two items from menus and press a big “Start” button in order to start sampling your applications. This chapter describes these basic steps and a few other general Shark features, such as its preferences. Main Window Figure 1-1 Main Window After launching Shark, you will be presented with Shark’s main window, as illustrated in Figure 1-1. The default sampling configuration istimer-based sampling (Time Profile ) of everything running on the system. By default, the Time Profile configuration uses a 1 ms timer as the trigger for sampling and will record for 30 seconds (30,000 samples per processor). Opening the Sampling Configuration menu (#1) allows you to select from various built-in profiling configurations. Here is a list: ● Time Profile— This configuration, the default, performs timer-based sampling, interrupting your system after a regular interval and taking a sample of what is executing. It is a great starting point, as it allows you to very quickly see what code in your application is actually executing most frequently. Knowing this isthe firststep to successfully optimizing CPU-bound applications. See “Time Profiling” (page 28) for more information. ● System Trace—This configuration records an exact trace of callsinto the Mac OS X kernel by your program, and which threads are running. It is useful for examining your program’s interactions with Mac OS X and for visualizing how your threads are interacting in multithreaded programs. System Trace is discussed in depth in “System Tracing” (page 63). ● Time Profile (All Thread States)— This variation on time profiling also records the state of all blocked, inactive threads. As a result, it’s a great way to see how much and why your threads are blocked. This is quite helpful in the development of multithreaded programs that do a lot of synchronization. This configuration is described in “Time Profile (All Thread States)” (page 97). Retired Document | 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 16 Getting Started with Shark● Malloc Trace— If your program allocates and deallocates a lot of memory, performance can suffer and the odds of accidental memory leaks increase. Shark can help you find and analyze these allocations. “Malloc Trace” (page 101) talks about this more. ● Static Analysis— Shark can provide some basic optimization hints without actually running code. See “Static Analysis” (page 107) for more information. ● Java Profiling— Because Java programs run within the Java Virtual Machine (JVM), normally sampling them with Shark produces little useful information. However, Shark also includes several configurations that simulate the normal Time Profile , Malloc Trace , and even an exact trace of method calls, but while collecting information about what the JVM is executing instead of the native machine. A full description of these options and how to attach Shark to your Java programs is given in “Using Shark with Java Programs” (page 108). ● Hardware Measurements— The L2 cache miss and Processor Bandwidth (x86 systems) or Memory Bandwidth (PowerPC systems) configurations measure memory system activity using counters built into the hardware. They are a great way to see how your program is being slowed because of poor cache memory use. See “Event Counting and Profiling Overview” (page 111) for an overview of Shark’s counter measurement capabilities. These built-in configurations are adequate for sampling most applications. After you have used Shark for awhile, however, you may decide that you would like to sample something in your application that is not covered by the built-in collection of options. In particular, you may want to perform hardware measurements using countersthat are not used by the default hardware measurement configurations. The processfor building your own configurations is described in “Custom Configurations” (page 183). This process is complex enough that you should probably familiarize yourself with Shark before attempting the creation of configurations. By default, Shark samples your entire system, as indicated by the “Everything” item selected for you in the Target pop-up menu (#2). Popping open this menu allows you to select a specific process or file (Figure 1-2). You may also choose different targets using the keyboard: Command-1 for everything, Command-2 for an executing process, and Command-3 for a file. For a Time Profile , it is unnecessary to select a specific target, but others like Malloc Trace and Static Analysis require you to target a specific process or file. If you select the “Process” target, you can also choose to launch a new process. See “Process Attach” (page 122) and “Process Launch” (page 122) for full instructions on the process attaching and launching target selection techniques. Figure 1-2 Process Target Getting Started with Shark Main Window Retired Document | 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 17Mini Configuration Editors Each configuration typically has a few parameters that are frequently modified. Shark allows you to edit these easily using themini configuration editors associated with each configuration. You can enablemini configuration editors by selecting the Config ShowMini Config Editor menu item(Command-Shift-C). Mostmini configuration editors are similar to the one depicted in “Shark Preferences,” but all have small configuration-specific variations. The selection of controls available in each min configuration editor are described in the chapters associated with each type of configuration. Figure 1-3 Mini Configuration Editor Perform Sampling After you choose what you would like to sample (or trace, with some configurations) and how, then actually using Shark to sample your program is extremely simple. There are two main ways to start sampling: 1. Click the Start button (#3 in “Main Window”). 2. Press the current “Hot Key” (Option-Esc , by default). Shark will emit a brief tone and the Shark icon in the dock will turn bright red to let you know that Shark is now actively sampling. At this point, you should exercise your program appropriately to trigger the execution of code that you want to measure. Sometimes this may require no active input on your part, but if you are measuring something like user interface performance then you may need to manually perform several steps while Shark samples. Getting Started with Shark Perform Sampling Retired Document | 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 18 Drawing and Printing Guide for iOSContents About Drawing and Printing in iOS 7 At a Glance 7 Custom UI Views Allow Greater Drawing Flexibility 8 Apps Can Draw Into Offscreen Bitmaps or PDFs 10 Apps Have a Range of Options for Printing Content 10 It’s Easy to Update Your App for High-Resolution Screens 11 See Also 11 iOS Drawing Concepts 12 The UIKit Graphics System 12 The View Drawing Cycle 13 Coordinate Systems and Drawing in iOS 13 Points Versus Pixels 16 Obtaining Graphics Contexts 18 Color and Color Spaces 20 Drawing with Quartz and UIKit 20 Configuring the Graphics Context 21 Creating and Drawing Paths 23 Creating Patterns, Gradients, and Shadings 24 Customizing the Coordinate Space 24 Applying Core Animation Effects 27 About Layers 27 About Animations 28 Accounting for Scale Factors in Core Animation Layers 28 Drawing Shapes Using Bézier Paths 30 Bézier Path Basics 30 Adding Lines and Polygons to Your Path 31 Adding Arcs to Your Path 32 Adding Curves to Your Path 34 Creating Oval and Rectangular Paths 35 Modifying the Path Using Core Graphics Functions 35 Rendering the Contents of a Bézier Path Object 36 Doing Hit-Detection on a Path 38 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 2Drawing and Creating Images 40 Drawing Images 40 Creating New Images Using Bitmap Graphics Contexts 41 Generating PDF Content 45 Creating and Configuring the PDF Context 45 Drawing PDF Pages 48 Creating Links Within Your PDF Content 50 Printing 52 Printing in iOS is Designed to be Simple and Intuitive 52 The Printing User Interface 52 How Printing Works in iOS 56 The UIKit Printing API 57 Printing Support Overview 58 Printing Workflow 59 Printing Printer-Ready Content 61 Using Print Formatters and Page Renderers 63 Setting the Layout Properties for the Print Job 63 Using a Print Formatter 65 Using a Page Renderer 69 Testing the Printing of App Content 73 Common Printing Tasks 73 Testing for Printing Availability 73 Specifying Print-Job Information 74 Specifying Paper Size, Orientation, and Duplexing Options 75 Integrating Printing Into Your User Interface 76 Responding to Print-Job Completion and Errors 79 Improving Drawing Performance 80 Supporting High-Resolution Screens In Views 82 Checklist for Supporting High-Resolution Screens 82 Drawing Improvements That You Get for Free 82 Updating Your Image Resource Files 83 Loading Images into Your App 83 Using an Image View to Display Multiple Images 84 Updating Your App’s Icons and Launch Images 85 Drawing High-Resolution Content Using OpenGL ES or GLKit 85 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 3 ContentsLoading Images 88 System Support for Images 89 UIKit Image Classes and Functions 89 Other Image-Related Frameworks 90 Supported Image Formats 90 Maintaining Image Quality 91 Document Revision History 92 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 4 ContentsFigures, Tables, and Listings About Drawing and Printing in iOS 7 Figure I-1 You can combine custom views with standard views, and even draw things offscreen. 7 iOS Drawing Concepts 12 Figure 1-1 The relationship between drawing coordinates, view coordinates, and hardware coordinates 14 Figure 1-2 Default coordinate systems in iOS 15 Figure 1-3 A one-point line centered at a whole-numbered point value 17 Figure 1-4 Appearance of one-point-wide lines on standard and retina displays 18 Figure 1-5 Arc rendering in Core Graphics versus UIKit 26 Table 1-1 Core graphics functions for modifying graphics state 21 Drawing Shapes Using Bézier Paths 30 Figure 2-1 Shape drawn with methods of the UIBezierPath class 32 Figure 2-2 An arc in the default coordinate system 33 Figure 2-3 Curve segments in a path 34 Listing 2-1 Creating a pentagon shape 31 Listing 2-2 Creating a new arc path 33 Listing 2-3 Assigning a new CGPathRef to a UIBezierPath object 35 Listing 2-4 Mixing Core Graphics and UIBezierPath calls 36 Listing 2-5 Drawing a path in a view 37 Listing 2-6 Testing points against a path object 38 Drawing and Creating Images 40 Listing 3-1 Drawing a scaled-down image to a bitmap context and obtaining the resulting image 42 Listing 3-2 Drawing to a bitmap context using Core Graphics functions 43 Generating PDF Content 45 Figure 4-1 Creating a link destination and jump point 51 Listing 4-1 Creating a new PDF file 46 Listing 4-2 Drawing page-based content 48 Printing 52 Figure 5-1 System item action button—used for printing 53 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 5Figure 5-2 Printer-options popover view (iPad) 53 Figure 5-3 Printer-options sheet (iPhone) 54 Figure 5-4 Print Center 55 Figure 5-5 Print Center: detail of print job 56 Figure 5-6 Printing architecture 57 Figure 5-7 Relationships of UIKit printing objects 57 Figure 5-8 The layout of a multi-page print job 65 Table 5-1 Deciding how to print app content 58 Listing 5-1 Printing a single PDF document with capability for page-range selection 62 Listing 5-2 Printing an HTML document (without header information) 66 Listing 5-3 Printing the contents of a web view 68 Listing 5-4 Drawing the header and footer of a page 71 Listing 5-5 Enabling or disabling a print button based on availability of printing 74 Listing 5-6 Setting properties of a UIPrintInfo object and assigning it to the printInfo property 74 Listing 5-7 Setting the printing orientation to match image dimension 75 Listing 5-8 Implementing the printInteractionController:choosePaper: method 76 Listing 5-9 Presenting printing options based upon current device type 77 Listing 5-10 Implementing a completion-handler block 79 Improving Drawing Performance 80 Table A-1 Tips for improving drawing performance 80 Supporting High-Resolution Screens In Views 82 Listing B-1 Initializing a render buffer’s storage and retrieving its actual dimensions 85 Loading Images 88 Table C-1 Usage scenarios for images 88 Table C-2 Supported image formats 90 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 6 Figures, Tables, and ListingsThis document covers three related subjects: ● Drawing custom UI views. Custom UI views allow you to draw content that cannot easily be drawn with standard UI elements. For example, a drawing program might use a custom view for the user’s drawing, or an arcade game might use a custom view into which it draws sprites. ● Drawing into offscreen bitmap and PDF content. Whether you plan to display the images later, export them to a file, or print the images to an AirPrint-enabled printer, offscreen drawing lets you do so without interrupting the user’s workflow. ● Adding AirPrint support to your app. The iOS printing system lets you draw your content differently to fit on the page. Figure I-1 You can combine custom views with standard views, and even draw things offscreen. At a Glance The iOS native graphics system combines three major technologies: UIKit, Core Graphics, and Core Animation. UIKit provides views and some high-level drawing functionality within those views, Core Graphics provides additional (lower-level) drawing support within UIKit views, and Core Animation provides the ability to apply transformations and animation to UIKit views. Core Animation is also responsible for view compositing. 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 7 About Drawing and Printing in iOSCustom UI Views Allow Greater Drawing Flexibility This document describes how to draw into custom UI views using native drawing technologies. These technologies, which include the Core Graphics and UIKit frameworks, support 2D drawing. Before you consider using a custom UI view, you should make certain that you really need to do so. Native drawing is suitable for handling more complex 2D layout needs. However, because custom views are processor-intensive, you should limit the amount of drawing you do using native drawing technologies. As an alternative to custom drawing, an iOS app can draw things onscreen in several other ways. ● Using standard (built-in) views. Standard viewslet you draw common user-interface primitives, including lists, collections, alerts, images, progress bars, tables, and so on without the need to explicitly draw anything yourself. Using built-in views not only ensures a consistent user experience between iOS apps, but also saves you programming effort. If built-in views meet your needs, you should read ViewProgramming Guide for iOS . ● Using Core Animation layers. Core Animation lets you create complex, layered 2D views with animation and transformations. Core Animation is a good choice for animating standard views, or for combining views in complex ways to present the illusion of depth, and can be combined with custom-drawn views as described in this document. To learn more about Core Animation, read Core Animation Overview. ● Using OpenGL ES in a GLKit view or a custom view. The OpenGL ES framework provides a set of open-standard graphics libraries geared primarily toward game development or apps that require high frame rates, such as virtual prototyping apps and mechanical and architectural design apps. It conforms to the OpenGL ES 2.0 and OpenGL ES v1.1 specifications. To learn more about OpenGL drawing, read OpenGL ES Programming Guide for iOS . ● Using web content. The UIWebView class lets you display web-based user interfaces in an iOS app. To learn more about displaying web content in a web view, read Using UIWebView to display select document types and UIWebView Class Reference . Depending on the type of app you are creating, it may be possible to use little or no custom drawing code. Although immersive apps typically make extensive use of custom drawing code, utility and productivity apps can often use standard views and controls to display their content. The use of custom drawing code should be limited to situations where the content you display needsto change dynamically. For example, a drawing app typically needsto use custom drawing code to track the user’s drawing commands, and an arcade-style game may need to update the screen constantly to reflect the changing game environment. In those situations, you should choose an appropriate drawing technology and create a custom view class to handle events and update the display appropriately. About Drawing and Printing in iOS At a Glance 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 8On the other hand, if the bulk of your app’s interface is fixed, you can render the interface in advance to one or more image files and display those images at runtime using the UIImageView class. You can layer image views with other content as needed to build your interface. You can also use the UILabel class to display configurable text and include buttons or other controls to provide interactivity. For example, an electronic version of a board game can often be created with little or no custom drawing code. Because custom views are generally more processor-intensive (with less help from the GPU), if you can do what you need to do using standard views, you should always do so. Also, you should make your custom views as small as possible, containing only content that you cannot draw in any other way, use use standard views for everything else. If you need to combine standard UI elements with custom drawing, consider using a Core Animation layer to superimpose a custom view with a standard view so that you draw as little as possible. A Few Key Concepts Underpin Drawing With the Native Technologies When you draw content with UIKit and Core Graphics, you should be familiar with a few concepts in addition to the view drawing cycle. ● For the drawRect: method, UIKit creates a graphics context for rendering to the display. This graphics context contains the information the drawing system needs to perform drawing commands, including attributes such as fill and stroke color, the font, the clipping area, and line width. You can also create and draw into custom graphics context for bitmap images and PDF content. ● UIKit has a default coordinate system where the origin of drawing is at the top-left of a view; positive values extend downward and to the right of that origin. You can change the size, orientation, and position of the default coordinate system relative to the underlying view or window by modifying the current transformation matrix, which maps a view’s coordinate space to the device screen. ● In iOS, the logical coordinate space, which measures distances in points, is not equal to the device coordinate space, which measures in pixels. For greater precision, points are expressed in floating-point values. Relevant Chapter: “iOS Drawing Concepts” (page 12) UIKit, Core Graphics, and Core Animation Give Your App Many Tools For Drawing The UIKit and Core Graphics have many complementary graphics capabilitiesthat encompass graphics contexts, Bézier paths, images, bitmaps, transparency layers, colors, fonts, PDF content, and drawing rectangles and clipping areas. In addition, Core Graphics has functions related to line attributes, color spaces, pattern colors, gradients, shadings, and image masks. The Core Animation framework enables you to create fluid animations by manipulating and displaying content created with other technologies. About Drawing and Printing in iOS At a Glance 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 9Relevant Chapters: “iOS Drawing Concepts” (page 12), “Drawing Shapes Using Bézier Paths” (page 30), “Drawing and Creating Images” (page 40), “Generating PDF Content” (page 45) Apps Can Draw Into Offscreen Bitmaps or PDFs It is often useful for an app to draw content offscreen: ● Offscreen bitmap contexts are often used when scaling down photographs for upload, rendering content into an image file for storage purposes, or using Core Graphics to generate complex images for display. ● Offscreen PDF contexts are often used when drawing user-generated content for printing purposes. After you create an offscreen context, you can draw into it just as you would draw within the drawRect: method of a custom view. Relevant Chapters: “Drawing and Creating Images” (page 40), “Generating PDF Content” (page 45) Apps Have a Range of Options for Printing Content As of iOS 4.2, apps can print content wirelessly to supported printers using AirPrint. When assembling a print job, they have three ways to give UIKit the content to print: ● They can give the framework one or more objects that are directly printable; such objects require minimal app involvement. These are instances of the NSData, NSURL, UIImage, or ALAsset classes containing or referencing image data or PDF content. ● They can assign a print formatter to the print job. A print formatter is an object that can lay out content of a certain type (such as plain text or HTML) over multiple pages. ● They can assign a page renderer to the print job. A page renderer is usually an instance of a custom subclass of UIPrintPageRenderer that draws the content to be printed in part or in full. A page renderer can use one or more print formatters to help it draw and format its printable content. About Drawing and Printing in iOS At a Glance 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 10Relevant Chapter: “Printing” (page 52) It’s Easy to Update Your App for High-Resolution Screens Some iOS devices feature high-resolution screens, so your app must be prepared to run on these devices and on devices with lower-resolution screens. iOS handles much of the work required to handle the different resolutions, but your app must do the rest. Your tasksinclude providing specially named high-resolution images and modifying your layer- and image-related code to take the current scale factor into account. Relevant Appendix: “Supporting High-Resolution Screens In Views” (page 82) See Also For complete examples of printing, see the PrintPhoto , Recipes and Printing , and PrintWebView sample code projects. About Drawing and Printing in iOS See Also 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 11High-quality graphics are an important part of your app’s user interface. Providing high-quality graphics not only makes your app look good, but it also makes your app look like a natural extension to the rest of the system. iOS provides two primary paths for creating high-quality graphics in your system: OpenGL or native rendering using Quartz, Core Animation, and UIKit. This document describes native rendering. (To learn about OpenGL drawing, see OpenGL ES Programming Guide for iOS .) Quartz isthe main drawing interface, providing support for path-based drawing, anti-aliased rendering, gradient fill patterns, images, colors, coordinate-space transformations, and PDF document creation, display, and parsing. UIKit provides Objective-C wrappers for line art, Quartz images, and color manipulations. Core Animation provides the underlying support for animating changes in many UIKit view properties and can also be used to implement custom animations. This chapter provides an overview of the drawing process for iOS apps, along with specific drawing techniques for each of the supported drawing technologies. You will also find tips and guidance on how to optimize your drawing code for the iOS platform. Important: Not all UIKit classes are thread safe. Be sure to check the documentation before performing drawing-related operations on threads other than your app’s main thread. The UIKit Graphics System In iOS, all drawing to the screen—regardless of whether it involves OpenGL, Quartz, UIKit, or Core Animation—occurs within the confines of an instance of the UIView class or a subclass thereof. Views define the portion of the screen in which drawing occurs. If you use system-provided views, this drawing is handled for you automatically. If you define custom views, however, you must provide the drawing code yourself. If you use Quartz, Core Animation, and UIKit to draw, you use the drawing concepts described in the following sections. In addition to drawing directly to the screen, UIKit also allows you to draw into offscreen bitmap and PDF graphics contexts. When you draw in an offscreen context, you are not drawing in a view, which means that concepts such as the view drawing cycle do not apply (unless you then obtain that image and draw it in an image view or similar). 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 12 iOS Drawing ConceptsThe View Drawing Cycle The basic drawing model forsubclasses of the UIView classinvolves updating content on demand. The UIView class makes the update process easier and more efficient; however, by gathering the update requests you make and delivering them to your drawing code at the most appropriate time. When a view is first shown or when a portion of the view needs to be redrawn, iOS asks the view to draw its content by calling the view’s drawRect: method. There are several actions that can trigger a view update: ● Moving or removing another view that was partially obscuring your view ● Making a previously hidden view visible again by setting its hidden property to NO ● Scrolling a view off of the screen and then back onto the screen ● Explicitly calling the setNeedsDisplay or setNeedsDisplayInRect: method of your view System views are redrawn automatically. For custom views, you must override the drawRect: method and perform all your drawing inside it. Inside your drawRect: method, use the native drawing technologies to draw shapes, text, images, gradients, or any other visual content you want. The first time your view becomes visible, iOS passes a rectangle to the view’s drawRect: method that contains your view’s entire visible area. During subsequent calls, the rectangle includes only the portion of the view that actually needsto be redrawn. For maximum performance, you should redraw only affected content. After calling your drawRect: method, the view marks itself as updated and waits for new actions to arrive and trigger another update cycle. If your view displays static content, then all you need to do is respond to changes in your view’s visibility caused by scrolling and the presence of other views. If you want to change the contents of the view, however, you must tell your view to redraw its contents. To do this, call the setNeedsDisplay or setNeedsDisplayInRect: method to trigger an update. For example, if you were updating content several times a second, you might want to set up a timer to update your view. You might also update your view in response to user interactions or the creation of new content in your view. Important: Do not call your view’s drawRect: method yourself. That method should be called only by code built into iOS during a screen repaint. At other times, no graphics context exists, so drawing is not possible. (Graphics contexts are explained in the next section.) Coordinate Systems and Drawing in iOS When an app draws something in iOS, it has to locate the drawn content in a two-dimensional space defined by a coordinate system. This notion mightseem straightforward at first glance, but it isn’t. Appsin iOS sometimes have to deal with different coordinate systems when drawing. iOS Drawing Concepts The UIKit Graphics System 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 13In iOS, all drawing occurs in a graphics context. Conceptually, a graphics context is an object that describes where and how drawing should occur, including basic drawing attributes such as the colors to use when drawing, the clipping area, line width and style information, font information, compositing options, and so on. In addition, as shown in Figure 1-1 (page 14), each graphics context has a coordinate system. More precisely, each graphics context has three coordinate systems: ● The drawing (user) coordinate system. This coordinate system is used when you issue drawing commands. ● The view coordinate system (base space). This coordinate system is a fixed coordinate system relative to the view. ● The (physical) device coordinate system. This coordinate system represents pixels on the physical screen. Figure 1-1 The relationship between drawing coordinates, view coordinates, and hardware coordinates The drawing frameworks of iOS create graphics contexts for drawing to specific destinations—the screen, bitmaps, PDF content, and so on—and these graphics contexts establish the initial drawing coordinate system for that destination. This initial drawing coordinate system is known as the default coordinate system, and is a 1:1 mapping onto the view’s underlying coordinate system. Each view also has a current transformation matrix (CTM), a mathematical matrix that maps the points in the current drawing coordinate system to the (fixed) view coordinate system. The app can modify this matrix (as described later) to change the behavior of future drawing operations. Each of the drawing frameworks of iOS establishes a default coordinate system based on the current graphics context. In iOS, there are two main types of coordinate systems: iOS Drawing Concepts The UIKit Graphics System 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 14● An upper-left-origin coordinate system (ULO), in which the origin of drawing operationsis at the upper-left corner of the drawing area, with positive values extending downward and to the right. The default coordinate system used by the UIKit and Core Animation frameworks is ULO-based. ● A lower-left-origin coordinate system (LLO), in which the origin of drawing operations is at the lower-left corner of the drawing area, with positive values extending upward and to the right. The default coordinate system used by Core Graphics framework is LLO-based. These coordinate systems are shown in Figure 1-2. Figure 1-2 Default coordinate systems in iOS UIKit Core Graphics (0.0, 0.0) (0.0, 0.0) Note: The default coordinate system in OS X is LLO-based. Although the drawing functions and methods of the Core Graphics and AppKit frameworks are perfectly suited to this default coordinate system, AppKit provides programmatic support for flipping the drawing coordinate system to have an upper-left origin. Before calling your view’s drawRect: method, UIKit establishes the default coordinate system for drawing to the screen by making a graphics context available for drawing operations. Within a view’s drawRect: method, an app can set graphics-state parameters (such as fill color) and draw to the current graphics context without needing to refer to the graphics context explicitly. This implicit graphics context establishes a ULO default coordinate system. iOS Drawing Concepts The UIKit Graphics System 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 15Points Versus Pixels In iOS there is a distinction between the coordinates you specify in your drawing code and the pixels of the underlying device. When using native drawing technologies such as Quartz, UIKit, and Core Animation, the drawing coordinate space and the view’s coordinate space are both logical coordinate spaces, with distances measured in points. These logical coordinate systems are decoupled from the device coordinate space used by the system frameworks to manage the pixels onscreen. The system automatically maps points in the view’s coordinate space to pixels in the device coordinate space, but this mapping is not always one-to-one. This behavior leads to an important fact that you should always remember: One point does not necessarily correspond to one physical pixel. The purpose of using points (and the logical coordinate system) is to provide a consistent size of output that is device independent. For most purposes, the actualsize of a point isirrelevant. The goal of pointsisto provide a relatively consistentscale that you can use in your code to specify the size and position of views and rendered content. How points are actually mapped to pixels is a detail that is handled by the system frameworks. For example, on a device with a high-resolution screen, a line that is one point wide may actually result in a line that is two physical pixels wide. The result is that if you draw the same content on two similar devices, with only one of them having a high-resolution screen, the content appears to be about the same size on both devices. In iOS, the UIScreen, UIView, UIImage, and CALayer classes provide properties to obtain (and, in some cases, set) a scale factor that describes the relationship between points and pixels for that particular object. For example, every UIKit view has a contentScaleFactor property. On a standard-resolution screen, the scale factor is typically 1.0. On a high-resolution screen, the scale factor is typically 2.0. In the future, other scale factors may also be possible. (In iOS prior to version 4, you should assume a scale factor of 1.0.) Native drawing technologies, such as Core Graphics, take the current scale factor into account for you. For example, if one of your views implements a drawRect: method, UIKit automatically sets the scale factor for that view to the screen’sscale factor. In addition, UIKit automatically modifiesthe current transformation matrix of any graphics contexts used during drawing to take into account the view’s scale factor. Thus, any content you draw in your drawRect: method is scaled appropriately for the underlying device’s screen. Because of this automatic mapping, when writing drawing code, pixels usually don’t matter. However, there are times when you might need to change your app’s drawing behavior depending on how points are mapped to pixels—to download higher-resolution images on devices with high-resolution screens or to avoid scaling artifacts when drawing on a low-resolution screen, for example. iOS Drawing Concepts The UIKit Graphics System 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 16In iOS, when you draw things onscreen, the graphics subsystem uses a technique called antialiasing to approximate a higher-resolution image on a lower-resolution screen. The best way to explain this technique is by example. When you draw a black vertical line on a solid white background, if that line falls exactly on a pixel, it appears as a series of black pixels in a field of white. If it appears exactly between two pixels, however, it appears as two grey pixels side-by-side, as shown in Figure 1-3. Figure 1-3 A one-point line centered at a whole-numbered point value Positions defined by whole-numbered points fall at the midpoint between pixels. For example, if you draw a one-pixel-wide vertical line from (1.0, 1.0) to (10.0, 10.0), you get a fuzzy grey line. If you draw a two-pixel-wide line, you get a solid black line because it fully covers two pixels (one on either side of the specified point). As a rule, lines that are an odd number of physical pixels wide appear softer than lines with widths measured in even numbers of physical pixels unless you adjust their position to make them cover pixels fully. Where the scale factor comes into play is when determining how many pixels are covered by a one-point-wide line. iOS Drawing Concepts The UIKit Graphics System 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 17On a low-resolution display (with a scale factor of 1.0), a one-point-wide line is one pixel wide. To avoid antialiasing when you draw a one-point-wide horizontal or vertical line, if the line is an odd number of pixels in width, you must offset the position by 0.5 points to either side of a whole-numbered position. If the line is an even number of points in width, to avoid a fuzzy line, you must not do so. Figure 1-4 Appearance of one-point-wide lines on standard and retina displays On a high-resolution display (with a scale factor of 2.0), a line that is one point wide is not antialiased at all because it occupies two full pixels (from -0.5 to +0.5). To draw a line that covers only a single physical pixel, you would need to make it 0.5 points in thickness and offset its position by 0.25 points. A comparison between the two types of screens is shown in Figure 1-4. Of course, changing drawing characteristics based on scale factor may have unexpected consequences. A 1-pixel-wide line might look nice on some devices but on a high-resolution device might be so thin that it is difficult to see clearly. It is up to you to determine whether to make such a change. Obtaining Graphics Contexts Most of the time, graphics contexts are configured for you. Each view object automatically creates a graphics contextso that your code can start drawing immediately assoon as your custom drawRect: method is called. As part of this configuration, the underlying UIView class creates a graphics context (a CGContextRef opaque type) for the current drawing environment. If you want to draw somewhere other than your view (for example, to capture a series of drawing operations in a PDF or bitmap file), or if you need to call Core Graphics functions that require a context object, you must take additional steps to obtain a graphics context object. The sections below explain how. iOS Drawing Concepts The UIKit Graphics System 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 18For more information about graphics contexts, modifying the graphics state information, and using graphics contextsto create customcontent,seeQuartz 2DProgrammingGuide . For a list of functions used in conjunction with graphics contexts, see CGContext Reference , CGBitmapContext Reference , and CGPDFContext Reference . Drawing to the Screen If you use Core Graphics functions to draw to a view, either in the drawRect: method or elsewhere, you’ll need a graphics context for drawing. (The first parameter of many of these functions must be a CGContextRef object.) You can call the function UIGraphicsGetCurrentContext to get an explicit version of the same graphics context that’s made implicit in drawRect:. Because it’s the same graphics context, the drawing functions should also make reference to a ULO default coordinate system. If you want to use Core Graphics functions to draw in a UIKit view, you should use the ULO coordinate system of UIKit for drawing operations. Alternatively, you can apply a flip transform to the CTM and then draw an object in the UIKit view using Core Graphics native LLO coordinate system. “Flipping the Default Coordinate System” (page 25) discusses flip transforms in detail. The UIGraphicsGetCurrentContext function always returns the graphics context currently in effect. For example, if you create a PDF context and then call UIGraphicsGetCurrentContext, you’d receive that PDF context. You must use the graphics context returned by UIGraphicsGetCurrentContext if you use Core Graphics functions to draw to a view. Note: The UIPrintPageRenderer class declares several methods for drawing printable content. In a manner similar to drawRect:, UIKit installs an implicit graphics context for implementations of these methods. This graphics context establishes a ULO default coordinate system. Drawing to Bitmap Contexts and PDF Contexts UIKit provides functions for rendering images in a bitmap graphics context and for generating PDF content by drawing in a PDF graphics context. Both of these approachesrequire that you first call a function that creates a graphics context—a bitmap context or a PDF context, respectively. The returned object serves as the current (and implicit) graphics context for subsequent drawing and state-setting calls. When you finish drawing in the context, you call another function to close the context. Both the bitmap context and the PDF context provided by UIKit establish a ULO default coordinate system. Core Graphics has corresponding functions for rendering in a bitmap graphics context and for drawing in a PDF graphics context. The context that an app directly creates through Core Graphics, however, establishes a LLO default coordinate system. iOS Drawing Concepts The UIKit Graphics System 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 19Note: In iOS, it is recommended that you use the UIKit functions for drawing to bitmap contexts and PDF contexts. However, if you do use the Core Graphics alternatives and intend to display the rendered results, you will have to adjust your code to compensate for the difference in default coordinate systems. See “Flipping the Default Coordinate System” (page 25) for more information. For details, see “Drawing and Creating Images” (page 40) (for drawing to bitmap contexts) and “Generating PDF Content” (page 45) (for drawing to PDF contexts). Color and Color Spaces iOS supports the full range of color spaces available in Quartz; however, most apps should need only the RGB color space. Because iOS is designed to run on embedded hardware and display graphics onscreen, the RGB color space is the most appropriate one to use. The UIColor object provides convenience methods for specifying color values using RGB, HSB, and grayscale values. When creating colors in this way, you never need to specify the color space. It is determined for you automatically by the UIColor object. You can also use the CGContextSetRGBStrokeColor and CGContextSetRGBFillColor functions in the Core Graphics framework to create and set colors. Although the Core Graphics framework includes support for creating colors using other color spaces, and for creating custom color spaces, using those colors in your drawing code is not recommended. Your drawing code should always use RGB colors. Drawing with Quartz and UIKit Quartz is the general name for the native drawing technology in iOS. The Core Graphics framework is at the heart of Quartz, and is the primary interface you use for drawing content. This framework provides data types and functions for manipulating the following: ● Graphics contexts ● Paths ● Images and bitmaps ● Transparency layers ● Colors, pattern colors, and color spaces ● Gradients and shadings ● Fonts ● PDF content iOS Drawing Concepts Drawing with Quartz and UIKit 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 20UIKit builds on the basic features of Quartz by providing a focused set of classesfor graphics-related operations. The UIKit graphics classes are not intended as a comprehensive set of drawing tools—Core Graphics already providesthat. Instead, they provide drawing support for other UIKit classes. UIKitsupport includesthe following classes and functions: ● UIImage, which implements an immutable class for displaying images ● UIColor, which provides basic support for device colors ● UIFont, which provides font information for classes that need it ● UIScreen, which provides basic information about the screen ● UIBezierPath, which enables your app to draw lines, arcs, ovals, and other shapes. ● Functions for generating a JPEG or PNG representation of a UIImage object ● Functions for drawing to a bitmap graphics context ● Functions for generating PDF data by drawing to a PDF graphics context ● Functions for drawing rectangles and clipping the drawing area ● Functions for changing and getting the current graphics context For information about the classes and methods that comprise UIKit, see UIKit Framework Reference . For more information about the opaque types and functions that comprise the Core Graphics framework, see Core Graphics Framework Reference . Configuring the Graphics Context Before calling your drawRect: method, the view object creates a graphics context and sets it as the current context. This context exists only for the lifetime of the drawRect: call. You can retrieve a pointer to this graphics context by calling the UIGraphicsGetCurrentContext function. This function returns a reference to a CGContextRef type, which you pass to Core Graphics functions to modify the current graphics state. Table 1-1 lists the main functions you use to set different aspects of the graphics state. For a complete list of functions, see CGContext Reference . This table also lists UIKit alternatives where they exist. Table 1-1 Core graphics functions for modifying graphics state Graphics state Core Graphics functions UIKit alternatives CGContextRotateCTM None CGContextScaleCTM CGContextTranslateCTM CGContextConcatCTM Current transformation matrix (CTM) iOS Drawing Concepts Drawing with Quartz and UIKit 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 21Graphics state Core Graphics functions UIKit alternatives Clipping area CGContextClipToRect UIRectClip function CGContextSetLineWidth None CGContextSetLineJoin CGContextSetLineCap CGContextSetLineDash CGContextSetMiterLimit Line: Width, join, cap, dash, miter limit Accuracy of curve estimation CGContextSetFlatness None Anti-aliasing setting CGContextSetAllowsAntialiasing None CGContextSetRGBFillColor UIColor class CGContextSetRGBStrokeColor Color: Fill and stroke settings Alpha global value CGContextSetAlpha None (transparency) Rendering intent CGContextSetRenderingIntent None CGContextSetFillColorSpace UIColor class CGContextSetStrokeColorSpace Color space: Fill and stroke settings CGContextSetFont UIFont class CGContextSetFontSize CGContextSetCharacterSpacing Text: Font, font size, character spacing, text drawing mode The UIImage class and various drawing functions let you specify which blend mode to use. Blend mode CGContextSetBlendMode The graphics context contains a stack of saved graphics states. When Quartz creates a graphics context, the stack is empty. Using the CGContextSaveGState function pushes a copy of the current graphics state onto the stack. Thereafter, modifications you make to the graphics state affect subsequent drawing operations but do not affect the copy stored on the stack. When you are done making modifications, you can return to the previous graphics state by popping the saved state off the top of the stack using the iOS Drawing Concepts Drawing with Quartz and UIKit 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 22CGContextRestoreGState function. Pushing and popping graphics states in this manner is a fast way to return to a previous state and eliminates the need to undo each state change individually. It is also the only way to restore some aspects of the state, such as the clipping path, back to their original settings. For general information about graphics contexts and using them to configure the drawing environment, see “Graphics Contexts” in Quartz 2D Programming Guide . Creating and Drawing Paths A path is a vector-based shapes created from a sequence of lines and Bézier curves. UIKit includes the UIRectFrame and UIRectFill functions(among others) for drawing simple pathssuch asrectanglesin your views. Core Graphics also includes convenience functions for creating simple paths such as rectangles and ellipses. For more complex paths, you must create the path yourself using the UIBezierPath class of UIKit, or using the functions that operate on the CGPathRef opaque type in the Core Graphics framework. Although you can construct a path without a graphics context using either API, the pointsin the path still must refer to the current coordinate system (which either has a ULO or LLO orientation), and you still need a graphics context to actually render the path. When drawing a path, you must have a current context set. This context can be a custom view’s context (in drawRect:), a bitmap context, or a PDF context. The coordinate system determines how the path is rendered. UIBezierPath assumes a ULO coordinate system. Thus, if your view is flipped (to use LLO coordinates), the resulting shape may render differently than intended. For best results, you should alwaysspecify pointsrelative to the origin of the current coordinate system of the graphics context used for rendering. Note: Arcs are an aspect of paths that require additional work even if this “rule” is followed. If you create a path using Core Graphic functions that locate points in a ULO coordinate system, and then render the path in a UIKit view, the direction an arc “points” is different. See “Side Effects of Drawing with Different Coordinate Systems” (page 25) for more on this subject. For creating paths in iOS, it is recommended that you use UIBezierPath instead of CGPath functions unless you need some of the capabilities that only Core Graphics provides, such as adding ellipses to paths. For more on creating and rendering paths in UIKit, see “Drawing Shapes Using Bézier Paths” (page 30). For information on using UIBezierPath to draw paths, see “Drawing Shapes Using Bézier Paths” (page 30). For information on how to draw paths using Core Graphics, including information about how you specify the pointsfor complex path elements,see “Paths”inQuartz 2DProgramming Guide . Forinformation on the functions you use to create paths, see CGContext Reference and CGPath Reference . iOS Drawing Concepts Drawing with Quartz and UIKit 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 23Creating Patterns, Gradients, and Shadings The Core Graphics framework includes additional functions for creating patterns, gradients, and shadings. You use these typesto create non monochrome colors and use them to fill the paths you create. Patterns are created from repeating images or content. Gradients and shadings provide different ways to create smooth transitions from color to color. The details for creating and using patterns, gradients, and shadings are all covered in Quartz 2D Programming Guide . Customizing the Coordinate Space By default, UIKit creates a straightforward current transformation matrix that maps points onto pixels. Although you can do all of your drawing without modifying that matrix, sometimes it can be convenient to do so. When your view’s drawRect: method is first called, the CTM is configured so that the origin of the coordinate system matches the your view’s origin, its positive X axis extends to the right, and its positive Y axis extends down. However, you can change the CTM by adding scaling, rotation, and translation factors to it and thereby change the size, orientation, and position of the default coordinate system relative to the underlying view or window. Using Coordinate Transforms to Improve Drawing Performance Modifying the CTM is a standard technique for drawing content in a view because it allows you to reuse paths, which potentially reduces the amount of computation required while drawing. For example, if you want to draw a square starting at the point (20, 20), you could create a path that moves to (20, 20) and then draws the needed set of lines to complete the square. However, if you later decide to move that square to the point (10, 10), you would have to recreate the path with the new starting point. Because creating paths is a relatively expensive operation, it is preferable to create a square whose origin is at (0, 0) and to modify the CTM so that the square is drawn at the desired origin. In the Core Graphics framework, there are two ways to modify the CTM. You can modify the CTM directly using the CTM manipulation functions defined in CGContext Reference . You can also create a CGAffineTransform structure, apply any transformations you want, and then concatenate that transform onto the CTM. Using an affine transform lets you group transformations and then apply them to the CTM all at once. You can also evaluate and invert affine transforms and use them to modify point, size, and rectangle values in your code. For more information on using affine transforms, see Quartz 2D Programming Guide and CGAffineTransform Reference . iOS Drawing Concepts Drawing with Quartz and UIKit 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 24Flipping the Default Coordinate System Flipping in UIKit drawing modifiesthe backing CALayer to align a drawing environment having a LLOcoordinate system with the default coordinate system of UIKit. If you only use UIKit methods and function for drawing, you shouldn’t need to flip the CTM. However, if you mix Core Graphics or Image I/O function calls with UIKit calls, flipping the CTM might be necessary. Specifically, if you draw an image or PDF document by calling Core Graphics functions directly, the object is rendered upside-down in the view’s context. You must flip the CTM to display the image and pages correctly. To flip a object drawn to a Core Graphics context so that it appears correctly when displayed in a UIKit view, you must modify the CTM in two steps. You translate the origin to the upper-left corner of the drawing area, and then you apply a scale translation, modifying the y-coordinate by -1. The code for doing this looks similar to the following: CGContextSaveGState(graphicsContext); CGContextTranslateCTM(graphicsContext, 0.0, imageHeight); CGContextScaleCTM(graphicsContext, 1.0, -1.0); CGContextDrawImage(graphicsContext, image, CGRectMake(0, 0, imageWidth, imageHeight)); CGContextRestoreGState(graphicsContext); If you create a UIImage object initialized with a Core Graphics image object, UIKit performs the flip transform for you. Every UIImage object is backed by a CGImageRef opaque type. You can access the Core Graphics object through the CGImage property and do some work with the image. (Core Graphics has image-related facilities not available in UIKit.) When you are finished, you can recreate the UIImage object from the modified CGImageRef object. Note: You can use the Core Graphics function CGContextDrawImage to draw an image to any rendering destination. This function has two parameters, the first for a graphics context and the second for a rectangle that defines both the size of the image and its location in a drawing surface such as a view. When drawing an image with CGContextDrawImage, if you don’t adjust the current coordinate system to a LLO orientation, the image appears inverted in a UIKit view. Additionally, the origin of the rectangle passed into this function is relative to the origin of the coordinate system that is current when the function is called. Side Effects of Drawing with Different Coordinate Systems Some rendering oddities are brought to light when you draw an object with with reference to the default coordinate system of one drawing technology and then render it in a graphics context of the other. You may want to adjust your code to account for these side effects. iOS Drawing Concepts Drawing with Quartz and UIKit 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 25Arcs and Rotations If you draw an path with functionssuch as CGContextAddArc and CGPathAddArc and assume a LLOcoordinate system, then you need to flip the CTM to render the arc correctly in a UIKit view. However, if you use the same function to create an arc with points located in a ULO coordinate system and then render the path in a UIKit view, you’ll notice that the arc is an altered version of its original. The terminating endpoint of the arc now pointsin the opposite direction of what that endpoint would do were the arc created using the UIBezierPath class. For example, a downward-pointing arrow now points upward (as shown in Figure 1-5), and the direction in which the arc “bends” is also different. You must change the direction of Core Graphics-drawn arcsto account for the ULO-based coordinate system; this direction is controlled by the startAngle and endAngle parameters of those functions. Figure 1-5 Arc rendering in Core Graphics versus UIKit Arc specified in Core Graphics Arc rendered in UIKit y y x (0,0) (0,0) x You can observe the same kind of mirroring effect if you rotate an object (for example, by calling CGContextRotateCTM). If you rotate an object using Core Graphics calls that make reference to a ULO coordinate system, the direction of the object when rendered in UIKit is reversed. You must account for the different directions of rotation in your code; with CGContextRotateCTM, you do this by inverting the sign of the angle parameter (so, for example, a negative value becomes a positive value). Shadows The direction a shadow falls from its object is specified by an offset value, and the meaning of that offset is a convention of a drawing framework. In UIKit, positive x and y offsets make a shadow go down and to the right of an object. In Core Graphics, positive x and y offsets make a shadow go up and to the right of an object. Flipping the CTM to align an object with the default coordinate system of UIKit does not affect the object’s shadow, and so a shadow does not correctly track its object. To get it to track correctly, you must modify the offset values appropriately for the current coordinate system. iOS Drawing Concepts Drawing with Quartz and UIKit 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 26Note: Prior to iOS 3.2, Core Graphics and UIKit shared the same convention for shadow direction: positive offset values make the shadow go down and to the right of an object. Applying Core Animation Effects Core Animation is an Objective-C framework that provides infrastructure for creating fluid, real-time animations quickly and easily. Core Animation is not a drawing technology itself, in the sense that it does not provide primitive routines for creating shapes, images, or other types of content. Instead, it is a technology for manipulating and displaying content that you created using other technologies. Most apps can benefit from using Core Animation in some form in iOS. Animations provide feedback to the user about what is happening. For example, when the user navigates through the Settings app, screens slide in and out of view based on whether the user is navigating further down the preferences hierarchy or back up to the root node. This kind of feedback is important and provides contextual information for the user. It also enhances the visual style of an app. In most cases, you may be able to reap the benefits of Core Animation with very little effort. For example, several properties of the UIView class (including the view’s frame, center, color, and opacity—among others) can be configured to trigger animations when their values change. You have to do some work to let UIKit know that you want these animations performed, but the animations themselves are created and run automatically for you. For information about how to trigger the built-in view animations, see “Animating Views” in UIView Class Reference . When you go beyond the basic animations, you must interact more directly with Core Animation classes and methods. The following sections provide information about Core Animation and show you how to work with its classes and methods to create typical animations in iOS. For additional information about Core Animation and how to use it, see Core Animation Programming Guide . About Layers The key technology in Core Animation is the layer object. Layers are lightweight objects that are similar in nature to views, but that are actually model objects that encapsulate geometry, timing, and visual properties for the content you want to display. The content itself is provided in one of three ways: ● You can assign a CGImageRef to the contents property of the layer object. ● You can assign a delegate to the layer and let the delegate handle the drawing. ● You can subclass CALayer and override one of the display methods. iOS Drawing Concepts Applying Core Animation Effects 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 27When you manipulate a layer object’s properties, what you are actually manipulating is the model-level data that determines how the associated content should be displayed. The actual rendering of that content is handled separately from your code and is heavily optimized to ensure it is fast. All you must do is set the layer content, configure the animation properties, and then let Core Animation take over. For more information about layers and how they are used, see Core Animation Programming Guide . About Animations When it comes to animating layers, Core Animation uses separate animation objects to control the timing and behavior of the animation. The CAAnimation class and its subclasses provide different types of animation behaviors that you can use in your code. You can create simple animations that migrate a property from one value to another, or you can create complex keyframe animations that track the animation through the set of values and timing functions you provide. Core Animation also lets you group multiple animations together into a single unit, called a transaction. The CATransaction object manages the group of animations as a unit. You can also use the methods of this class to set the duration of the animation. For examples of how to create custom animations, see Animation Types and Timing Programming Guide . Accounting for Scale Factors in Core Animation Layers Apps that use Core Animation layers directly to provide content may need to adjust their drawing code to account for scale factors. Normally, when you draw in your view’s drawRect: method, or in the drawLayer:inContext: method of the layer’s delegate, the system automatically adjusts the graphics context to account for scale factors. However, knowing or changing that scale factor might still be necessary when your view does one of the following: ● Creates additional Core Animation layers with different scale factors and composites them into its own content ● Sets the contents property of a Core Animation layer directly Core Animation’s compositing engine looks at the contentsScale property of each layer to determine whether the contents of that layer need to be scaled during compositing. If your app creates layers without an associated view, each new layer object’s scale factor is initially set to 1.0. If you do not change that scale factor, and if you subsequently draw the layer on a high-resolution screen, the layer’s contents are scaled automatically to compensate for the difference in scale factors. If you do not want the contents to be scaled, you can change the layer’s scale factor to 2.0 by setting a new value for the contentsScale property, but if you do so without providing high-resolution content, your existing content may appear smaller than you were expecting. To fix that problem, you need to provide higher-resolution content for your layer. iOS Drawing Concepts Applying Core Animation Effects 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 28Important: The contentsGravity property of the layer plays a role in determining whether standard-resolution layer content is scaled on a high-resolution screen. This property is set to the value kCAGravityResize by default, which causes the layer content to be scaled to fit the layer’s bounds. Changing the gravity to a nonresizing option eliminates the automatic scaling that would otherwise occur. In such a situation, you may need to adjust your content or the scale factor accordingly. Adjusting the content of your layer to accommodate different scale factors is most appropriate when you set the contents property of a layer directly. Quartz images have no notion of scale factors and therefore work directly with pixels. Therefore, before creating the CGImageRef object you plan to use for the layer’s contents, check the scale factor and adjust the size of your image accordingly. Specifically, load an appropriately sized image from your app bundle or use the UIGraphicsBeginImageContextWithOptions function to create an image whose scale factor matches the scale factor of your layer. If you do not create a high-resolution bitmap, the existing bitmap may be scaled as discussed previously. For information on how to specify and load high-resolution images, see “Loading Images into Your App” (page 83). For information about how to create high-resolution images, see “Drawing to Bitmap Contexts and PDF Contexts” (page 19). iOS Drawing Concepts Applying Core Animation Effects 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 29In iOS 3.2 and later, you can use the UIBezierPath class to create vector-based paths. The UIBezierPath class is an Objective-C wrapper for the path-related features in the Core Graphics framework. You can use this classto define simple shapes,such as ovals and rectangles, as well as complex shapesthat incorporate multiple straight and curved line segments. You can use path objects to draw shapes in your app’s user interface. You can draw the path’s outline, fill the space it encloses, or both. You can also use paths to define a clipping region for the current graphics context, which you can then use to modify subsequent drawing operations in that context. Bézier Path Basics A UIBezierPath object is a wrapper for a CGPathRef data type. Paths are vector-based shapes that are built using line and curve segments. You can use line segments to create rectangles and polygons, and you can use curve segments to create arcs, circles, and complex curved shapes. Each segment consists of one or more points(in the current coordinate system) and a drawing command that defines how those points are interpreted. Each set of connected line and curve segments form what is referred to as a subpath. The end of one line or curve segment in a subpath defines the beginning of the next. A single UIBezierPath object may contain one or more subpaths that define the overall path, separated by moveToPoint: commands that effectively raise the drawing pen and move it to a new location. The processes for building and using a path object are separate. Building the path is the first process and involves the following steps: 1. Create the path object. 2. Set any relevant drawing attributes of your UIBezierPath object, such as the lineWidth or lineJoinStyle properties for stroked paths or the usesEvenOddFillRule property for filled paths. These drawing attributes apply to the entire path. 3. Set the starting point of the initial segment using the moveToPoint: method. 4. Add line and curve segments to define a subpath. 5. Optionally, close the subpath by calling closePath, which draws a straight line segment from the end of the last segment to the beginning of the first. 6. Optionally, repeat the steps 3, 4, and 5 to define additional subpaths. 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 30 Drawing Shapes Using Bézier PathsWhen building your path, you should arrange the points of your path relative to the origin point (0, 0). Doing so makes it easier to move the path around later. During drawing, the points of your path are applied as-is to the coordinate system of the current graphics context. If your path is oriented relative to the origin, all you have to do to reposition it is apply an affine transform with a translation factor to the current graphics context. The advantage of modifying the graphics context (as opposed to the path object itself) is that you can easily undo the transformation by saving and restoring the graphics state. To draw your path object, you use the stroke and fill methods. These methods render the line and curve segments of your path in the current graphics context. The rendering process involves rasterizing the line and curve segments using the attributes of the path object. The rasterization process does not modify the path object itself. As a result, you can render the same path object multiple timesin the current context or in another context. Adding Lines and Polygons to Your Path Lines and polygons are simple shapes that you build point-by-point using the moveToPoint: and addLineToPoint: methods. The moveToPoint: method sets the starting point of the shape you want to create. From that point, you create the lines of the shape using the addLineToPoint: method. You create the linesin succession, with each line being formed between the previous point and the new point you specify. Listing 2-1 shows the code needed to create a pentagon shape using individual line segments. (Figure 2-1 showsthe result of drawing thisshape with appropriate stroke and fill colorsettings, as described in “Rendering the Contents of a Bézier Path Object” (page 36).) This code sets the initial point of the shape and then adds four connected line segments. The fifth segment is added by the call to the closePath method, which connects the last point (0, 40) with the first point (100, 0). Listing 2-1 Creating a pentagon shape UIBezierPath *aPath = [UIBezierPath bezierPath]; // Set the starting point of the shape. [aPath moveToPoint:CGPointMake(100.0, 0.0)]; // Draw the lines. [aPath addLineToPoint:CGPointMake(200.0, 40.0)]; [aPath addLineToPoint:CGPointMake(160, 140)]; [aPath addLineToPoint:CGPointMake(40.0, 140)]; [aPath addLineToPoint:CGPointMake(0.0, 40.0)]; Drawing Shapes Using Bézier Paths Adding Lines and Polygons to Your Path 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 31[aPath closePath]; Figure 2-1 Shape drawn with methods of the UIBezierPath class Using the closePath method not only ends the subpath describing the shape, it also draws a line segment between the first and last points. This is a convenient way to finish a polygon without having to draw the final line. Adding Arcs to Your Path The UIBezierPath class providessupport for initializing a new path object with an arc segment. The parameters of the bezierPathWithArcCenter:radius:startAngle:endAngle:clockwise: method define the circle that containsthe desired arc and the start and end points of the arc itself. Figure 2-2 showsthe components that go into creating an arc, including the circle that defines the arc and the angle measurements used to Drawing Shapes Using Bézier Paths Adding Arcs to Your Path 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 32specify it. In this case, the arc is created in the clockwise direction. (Drawing the arc in the counterclockwise direction would paint the dashed portion of the circle instead.) The code for creating this arc isshown in Listing 2-2 (page 33). Figure 2-2 An arc in the default coordinate system 100 200 100 200 (0, 0) 3π 4 (135°) rad 75 pts 0 rad (0°) (150, 150) Listing 2-2 Creating a new arc path // pi is approximately equal to 3.14159265359. #define DEGREES_TO_RADIANS(degrees) ((pi * degrees)/ 180) - (UIBezierPath *)createArcPath { UIBezierPath *aPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(150, 150) radius:75 startAngle:0 endAngle:DEGREES_TO_RADIANS(135) clockwise:YES]; return aPath; } Drawing Shapes Using Bézier Paths Adding Arcs to Your Path 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 33If you want to incorporate an arc segment into the middle of a path, you must modify the path object’s CGPathRef data type directly. For more information about modifying the path using Core Graphics functions, see “Modifying the Path Using Core Graphics Functions” (page 35). Adding Curves to Your Path The UIBezierPath class provides support for adding cubic and quadratic Bézier curves to a path. Curve segments start at the current point and end at the point you specify. The shape of the curve is defined using tangent lines between the start and end points and one or more control points. Figure 2-3 shows approximations of both types of curve and the relationship between the control points and the shape of the curve. The exact curvature of each segment involves a complex mathematical relationship between all of the points and is well documented online and at Wikipedia. Figure 2-3 Curve segments in a path Start point Control point 2 Endpoint Control point 1 A Current point B Control point C Endpoint Bézier curve Quad curve To add curves to a path, you use the following methods: ● Cubic curve:addCurveToPoint:controlPoint1:controlPoint2: ● Quadratic curve:addQuadCurveToPoint:controlPoint: Because curves rely on the current point of the path, you must set the current point before calling either of the preceding methods. Upon completion of the curve, the current point is updated to the new end point you specified. Drawing Shapes Using Bézier Paths Adding Curves to Your Path 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 34Creating Oval and Rectangular Paths Ovals and rectangles are common types of pathsthat are built using a combination of curve and line segments. The UIBezierPath class includes the bezierPathWithRect: and bezierPathWithOvalInRect: convenience methods for creating paths with oval or rectangular shapes. Both of these methods create a new path object and initialize it with the specified shape. You can use the returned path object right away or add more shapes to it as needed. If you want to add a rectangle to an existing path object, you must do so using the moveToPoint:, addLineToPoint:, and closePath methods as you would for any other polygon. Using the closePath method for the final side of the rectangle is a convenient way to add the final line of the path and also mark the end of the rectangle subpath. If you want to add an oval to an existing path, the simplest way to do so is to use Core Graphics. Although you can use the addQuadCurveToPoint:controlPoint: to approximate an oval surface, the CGPathAddEllipseInRect function is much simpler to use and more accurate. For more information, see “Modifying the Path Using Core Graphics Functions” (page 35). Modifying the Path Using Core Graphics Functions The UIBezierPath class is really just a wrapper for a CGPathRef data type and the drawing attributes associated with that path. Although you normally add line and curve segments using the methods of the UIBezierPath class, the class also exposes a CGPath property that you can use to modify the underlying path data type directly. You can use this property when you would prefer to build your path using the functions of the Core Graphics framework. There are two ways to modify the path associated with a UIBezierPath object. You can modify the path entirely using Core Graphicsfunctions, or you can use a mixture of Core Graphicsfunctions and UIBezierPath methods. Modifying the path entirely using Core Graphics calls is easier in some ways. You create a mutable CGPathRef data type and call whatever functions you need to modify its path information. When you are done you assign your path object to the corresponding UIBezierPath object, as shown in Listing 2-3. Listing 2-3 Assigning a new CGPathRef to a UIBezierPath object // Create the path data. CGMutablePathRef cgPath = CGPathCreateMutable(); CGPathAddEllipseInRect(cgPath, NULL, CGRectMake(0, 0, 300, 300)); CGPathAddEllipseInRect(cgPath, NULL, CGRectMake(50, 50, 200, 200)); // Now create the UIBezierPath object. Drawing Shapes Using Bézier Paths Creating Oval and Rectangular Paths 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 35UIBezierPath *aPath = [UIBezierPath bezierPath]; aPath.CGPath = cgPath; aPath.usesEvenOddFillRule = YES; // After assigning it to the UIBezierPath object, you can release // your CGPathRef data type safely. CGPathRelease(cgPath); If you choose to use a mixture of Core Graphics functions and UIBezierPath methods, you must carefully move the path information back and forth between the two. Because a UIBezierPath object owns its underlying CGPathRef data type, you cannot simply retrieve that type and modify it directly. Instead, you must make a mutable copy, modify the copy, and then assign the copy back to the CGPath property as shown in Listing 2-4. Listing 2-4 Mixing Core Graphics and UIBezierPath calls UIBezierPath *aPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 300, 300)]; // Get the CGPathRef and create a mutable version. CGPathRef cgPath = aPath.CGPath; CGMutablePathRef mutablePath = CGPathCreateMutableCopy(cgPath); // Modify the path and assign it back to the UIBezierPath object. CGPathAddEllipseInRect(mutablePath, NULL, CGRectMake(50, 50, 200, 200)); aPath.CGPath = mutablePath; // Release both the mutable copy of the path. CGPathRelease(mutablePath); Rendering the Contents of a Bézier Path Object After creating a UIBezierPath object, you can render it in the current graphics context using its stroke and fill methods. Before you call these methods, though, there are usually a few other tasksto perform to ensure your path is drawn correctly: Drawing Shapes Using Bézier Paths Rendering the Contents of a Bézier Path Object 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 36● Set the desired stroke and fill colors using the methods of the UIColor class. ● Position the shape where you want it in the target view. If you created your path relative to the point (0, 0), you can apply an appropriate affine transform to the current drawing context. For example, to draw your shape starting at the point (10, 10), you would call the CGContextTranslateCTM function and specify 10 for both the horizontal and vertical translation values. Adjusting the graphics context (as opposed to the points in the path object) is preferred because you can undo the change more easily by saving and restoring the previous graphics state. ● Update the drawing attributes of the path object. The drawing attributes of your UIBezierPath instance override the values associated with the graphics context when rendering the path. Listing 2-5 shows a sample implementation of a drawRect: method that draws an oval in a custom view. The upper-left corner of the oval’s bounding rectangle is located at the point (50, 50) in the view’s coordinate system. Because fill operations paint right up to the path boundary, this method fills the path before stroking it. This prevents the fill color from obscuring half of the stroked line. Listing 2-5 Drawing a path in a view - (void)drawRect:(CGRect)rect { // Create an oval shape to draw. UIBezierPath *aPath = [UIBezierPath bezierPathWithOvalInRect: CGRectMake(0, 0, 200, 100)]; // Set the render colors. [[UIColor blackColor] setStroke]; [[UIColor redColor] setFill]; CGContextRef aRef = UIGraphicsGetCurrentContext(); // If you have content to draw after the shape, // save the current state before changing the transform. //CGContextSaveGState(aRef); // Adjust the view's origin temporarily. The oval is // now drawn relative to the new origin point. CGContextTranslateCTM(aRef, 50, 50); Drawing Shapes Using Bézier Paths Rendering the Contents of a Bézier Path Object 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 37// Adjust the drawing options as needed. aPath.lineWidth = 5; // Fill the path before stroking it so that the fill // color does not obscure the stroked line. [aPath fill]; [aPath stroke]; // Restore the graphics state before drawing any other content. //CGContextRestoreGState(aRef); } Doing Hit-Detection on a Path To determine whether a touch event occurred on the filled portion of a path, you can use the containsPoint: method of UIBezierPath. This method teststhe specified point against all closed subpathsin the path object and returns YES if it lies on or inside any of those subpaths. Important: The containsPoint: method and the Core Graphics hit-testing functions operate only on closed paths. These methods always return NO for hits on open subpaths. If you want to do hit detection on an open subpath, you must create a copy of your path object and close the open subpaths before testing points. If you want to do hit-testing on the stroked portion of the path (instead of the fill area), you must use Core Graphics. The CGContextPathContainsPoint function lets you test points on either the fill orstroke portion of the path currently assigned to the graphics context. Listing 2-6 shows a method that tests to see whether the specified point intersects the specified path. The inFill parameter lets the caller specify whether the point should be tested against the filled or stroked portion of the path. The path passed in by the caller must contain one or more closed subpaths for the hit detection to succeed. Listing 2-6 Testing points against a path object - (BOOL)containsPoint:(CGPoint)point onPath:(UIBezierPath *)path inFillArea:(BOOL)inFill { CGContextRef context = UIGraphicsGetCurrentContext(); Drawing Shapes Using Bézier Paths Doing Hit-Detection on a Path 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 38CGPathRef cgPath = path.CGPath; BOOL isHit = NO; // Determine the drawing mode to use. Default to // detecting hits on the stroked portion of the path. CGPathDrawingMode mode = kCGPathStroke; if (inFill) { // Look for hits in the fill area of the path instead. if (path.usesEvenOddFillRule) mode = kCGPathEOFill; else mode = kCGPathFill; } // Save the graphics state so that the path can be // removed later. CGContextSaveGState(context); CGContextAddPath(context, cgPath); // Do the hit detection. isHit = CGContextPathContainsPoint(context, point, mode); CGContextRestoreGState(context); return isHit; } Drawing Shapes Using Bézier Paths Doing Hit-Detection on a Path 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 39Most of the time, it is fairly straightforward to display images using standard views. However, there are two situations in which you may need to do additional work: ● If you want to display images as part of a custom view, you must draw the images yourself in your view’s drawRect: method. “Drawing Images” (page 40) explains how. ● If you want to render images offscreen (to draw later, or to save into a file), you must create a bitmap image context. To learn more, read “Creating New Images Using Bitmap Graphics Contexts” (page 41). Drawing Images For maximum performance, if your image drawing needs can be met using the UIImageView class, you should use this image object to initialize a UIImageView object. However, if you need to draw an image explicitly, you can store the image and use it later in your view’s drawRect: method. The following example shows how to load an image from your app’s bundle. NSString *imagePath = [[NSBundle mainBundle] pathForResource:@"myImage" ofType:@"png"]; UIImage *myImageObj = [[UIImage alloc] initWithContentsOfFile:imagePath]; // Store the image into a property of type UIImage * // for use later in the class's drawRect: method. self.anImage = myImageObj; To draw the resulting image explicitly in your view’s drawRect: method, you can use any of the drawing methods available in UIImage. These methods let you specify where in your view you want to draw the image and therefore do not require you to create and apply a separate transform prior to drawing. The following snippet draws the image loaded above at the point (10, 10) in the view. - (void)drawRect:(CGRect)rect { 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 40 Drawing and Creating Images... // Draw the image. [self.anImage drawAtPoint:CGPointMake(10, 10)]; } Important: If you use the CGContextDrawImage function to draw bitmap images directly, the image data is inverted along the y axis by default. This is because Quartz images assume a coordinate system with a lower-left corner origin and positive coordinate axes extending up and to the right from that point. Although you can apply a transform before drawing, the simpler (and recommended) way to draw Quartz images is to wrap them in a UIImage object, which compensates for this difference in coordinate spaces automatically. For more information on creating and drawing images using Core Graphics, see Quartz 2D Programming Guide . Creating New Images Using Bitmap Graphics Contexts Most of the time, when drawing, your goal is to show something onscreen. However, it is sometimes useful to draw something to an offscreen buffer. For example, you might want to create a thumbnail of an existing image, draw into a buffer so that you can save it to a file, and so on. To support those needs, you can create a bitmap image context, use UIKit framework or Core Graphics functions to draw to it, and then obtain an image object from the context. In UIKit, the procedure is as follows: 1. Call UIGraphicsBeginImageContextWithOptions to create a bitmap context and push it onto the graphics stack. For the first parameter (size), pass a CGSize value to specify the dimensions of the bitmap context (in points). For the second parameter (opaque), if your image contains transparency (an alpha channel), pass NO. Otherwise, pass YES to maximize performance. For the final parameter (scale), pass 0.0 for a bitmap that is scaled appropriately for the main screen of the device, or pass the scale factor of your choice. For example, the following code snippet creates a bitmap that is 200 x 200 pixels. (The number of pixels is determined by multiplying the size of the image by the scale factor.) UIGraphicsBeginImageContextWithOptions(CGSizeMake(100.0,100.0), NO, 2.0); Drawing and Creating Images Creating New Images Using Bitmap Graphics Contexts 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 41Note: You should generally avoid calling the similarly named UIGraphicsBeginImageContext function (except as a fallback for backwards compatibility), because it always creates images with a scale factor of 1.0. If the underlying device has a high-resolution screen, an image created with UIGraphicsBeginImageContext might not appear as smooth when rendered. 2. Use UIKit or Core Graphics routines to draw the content of the image into the newly created graphics context. 3. Call the UIGraphicsGetImageFromCurrentImageContext function to generate and return a UIImage object based on what you drew. If desired, you can continue drawing and call this method again to generate additional images. 4. Call UIGraphicsEndImageContext to pop the context from the graphics stack. The method in Listing 3-1 gets an image downloaded over the Internet and draws it into an image-based context, scaled down to the size of an app icon. It then obtains a UIImage object created from the bitmap data and assigns it to an instance variable. Note that the size of the bitmap (the first parameter of UIGraphicsBeginImageContextWithOptions) and the size of the drawn content (the size of imageRect) should match. If the content is larger than the bitmap, a portion of the content will be clipped and not appear in the resulting image. Listing 3-1 Drawing a scaled-down image to a bitmap context and obtaining the resulting image - (void)connectionDidFinishLoading:(NSURLConnection *)connection { UIImage *image = [[UIImage alloc] initWithData:self.activeDownload]; if (image != nil && image.size.width != kAppIconHeight && image.size.height != kAppIconHeight) { CGRect imageRect = CGRectMake(0.0, 0.0, kAppIconHeight, kAppIconHeight); UIGraphicsBeginImageContextWithOptions(itemSize, NO, [UIScreen mainScreen].scale); [image drawInRect:imageRect]; self.appRecord.appIcon = UIGraphicsGetImageFromCurrentImageContext(); // UIImage returned. UIGraphicsEndImageContext(); } else { self.appRecord.appIcon = image; } self.activeDownload = nil; [image release]; Drawing and Creating Images Creating New Images Using Bitmap Graphics Contexts 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 42self.imageConnection = nil; [delegate appImageDidLoad:self.indexPathInTableView]; } You can also call Core Graphics functions to draw the contents of the generated bitmap image; the code fragment in Listing 3-2, which draws a scaled-down image of a PDF page, gives an example of this. Note that the code flips the graphics context prior to calling CGContextDrawPDFPage to align the drawn image with default coordinate system of UIKit. Listing 3-2 Drawing to a bitmap context using Core Graphics functions // Other code precedes... CGRect pageRect = CGPDFPageGetBoxRect(page, kCGPDFMediaBox); pdfScale = self.frame.size.width/pageRect.size.width; pageRect.size = CGSizeMake(pageRect.size.width * pdfScale, pageRect.size.height * pdfScale); UIGraphicsBeginImageContextWithOptions(pageRect.size, YES, pdfScale); CGContextRef context = UIGraphicsGetCurrentContext(); // First fill the background with white. CGContextSetRGBFillColor(context, 1.0,1.0,1.0,1.0); CGContextFillRect(context,pageRect); CGContextSaveGState(context); // Flip the context so that the PDF page is rendered right side up CGContextTranslateCTM(context, 0.0, pageRect.size.height); CGContextScaleCTM(context, 1.0, -1.0); // Scale the context so that the PDF page is rendered at the // correct size for the zoom level. CGContextScaleCTM(context, pdfScale,pdfScale); CGContextDrawPDFPage(context, page); CGContextRestoreGState(context); UIImage *backgroundImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); Drawing and Creating Images Creating New Images Using Bitmap Graphics Contexts 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 43backgroundImageView = [[UIImageView alloc] initWithImage:backgroundImage]; // Other code follows... If you prefer using Core Graphics entirely for drawing in a bitmap graphics context, you can use the CGBitmapContextCreate function to create the context and draw your image contents into it. When you finish drawing, call the CGBitmapContextCreateImage function to obtain a CGImageRef object from the bitmap context. You can draw the Core Graphics image directly or use this it to initialize a UIImage object. When finished, call the CGContextRelease function on the graphics context. Drawing and Creating Images Creating New Images Using Bitmap Graphics Contexts 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 44The UIKit framework provides a set of functions for generating PDF content using native drawing code. These functions let you create a graphics context that targets a PDF file or PDF data object. You can then create one or more PDF pages and draw into those pages using the same UIKit and Core Graphics drawing routines you use when drawing to the screen. When you are done, what you are left with is a PDF version of what you drew. The overall drawing process is similar to the process for creating any other image (described in “Drawing and Creating Images” (page 40)). It consists of the following steps: 1. Create a PDF context and push it onto the graphics stack (as described in “Creating and Configuring the PDF Context” (page 45)). 2. Create a page (as described in “Drawing PDF Pages” (page 48)). 3. Use UIKit or Core Graphics routines to draw the content of the page. 4. Add links if needed (as described in “Creating Links Within Your PDF Content” (page 50)). 5. Repeat steps 2, 3, and 4 as needed. 6. End the PDF context (as described in “Creating and Configuring the PDF Context” (page 45)) to pop the context from the graphicsstack and, depending on how the context was created, either write the resulting data to the specified PDF file or store it into the specified NSMutableData object. The following sections describe the PDF creation processin more detail using a simple example. For information about the functions you use to create PDF content, see UIKit Function Reference . Creating and Configuring the PDF Context You create a PDF graphics context using either the UIGraphicsBeginPDFContextToData or UIGraphicsBeginPDFContextToFile function. These functions create the graphics context and associate it with a destination for the PDF data. For the UIGraphicsBeginPDFContextToData function, the destination is an NSMutableData object that you provide. And for the UIGraphicsBeginPDFContextToFile function, the destination is a file in your app’s home directory. PDF documents organize their content using a page-based structure. This structure imposes two restrictions on any drawing you do: ● There must be an open page before you issue any drawing commands. 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 45 Generating PDF Content● You must specify the size of each page. The functions you use to create a PDF graphics context allow you to specify a default page size but they do not automatically open a page. After creating your context, you must explicitly open a new page using either the UIGraphicsBeginPDFPage or UIGraphicsBeginPDFPageWithInfo function. And each time you want to create a new page, you must call one of these functions again to mark the start of the new page. The UIGraphicsBeginPDFPage function creates a page using the default size, while the UIGraphicsBeginPDFPageWithInfo function lets you customize the page size and other page attributes. When you are done drawing, you close the PDF graphics context by calling the UIGraphicsEndPDFContext. This function closes the last page and writes the PDF content to the file or data object you specified at creation time. This function also removes the PDF context from the graphics context stack. Listing 4-1 shows the processing loop used by an app to create a PDF file from the text in a text view. Aside from three function calls to configure and manage the PDF context, most of the code is related to drawing the desired content. The textView member variable points to the UITextView object containing the desired text. The app uses the Core Text framework (and more specifically a CTFramesetterRef data type) to handle the text layout and management on successive pages. The implementations for the custom renderPageWithTextRange:andFramesetter: and drawPageNumber: methods are shown in Listing 4-2 (page 48). Listing 4-1 Creating a new PDF file - (IBAction)savePDFFile:(id)sender { // Prepare the text using a Core Text Framesetter. CFAttributedStringRef currentText = CFAttributedStringCreate(NULL, (CFStringRef)textView.text, NULL); if (currentText) { CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(currentText); if (framesetter) { NSString *pdfFileName = [self getPDFFileName]; // Create the PDF context using the default page size of 612 x 792. UIGraphicsBeginPDFContextToFile(pdfFileName, CGRectZero, nil); CFRange currentRange = CFRangeMake(0, 0); NSInteger currentPage = 0; Generating PDF Content Creating and Configuring the PDF Context 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 46BOOL done = NO; do { // Mark the beginning of a new page. UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, 612, 792), nil); // Draw a page number at the bottom of each page. currentPage++; [self drawPageNumber:currentPage]; // Render the current page and update the current range to // point to the beginning of the next page. currentRange = [self renderPageWithTextRange:currentRange andFramesetter:framesetter]; // If we're at the end of the text, exit the loop. if (currentRange.location == CFAttributedStringGetLength((CFAttributedStringRef)currentText)) done = YES; } while (!done); // Close the PDF context and write the contents out. UIGraphicsEndPDFContext(); // Release the framewetter. CFRelease(framesetter); } else { NSLog(@"Could not create the framesetter needed to lay out the atrributed string."); } // Release the attributed string. CFRelease(currentText); } else { NSLog(@"Could not create the attributed string for the framesetter"); } Generating PDF Content Creating and Configuring the PDF Context 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 47} Drawing PDF Pages All PDF drawing must be done in the context of a page. Every PDF document has at least one page and many may have multiple pages. You specify the start of a new page by calling the UIGraphicsBeginPDFPage or UIGraphicsBeginPDFPageWithInfo function. These functions close the previous page (if one was open), create a new page, and prepare it for drawing. The UIGraphicsBeginPDFPage creates the new page using the default size while the UIGraphicsBeginPDFPageWithInfo function lets you customize the page size or customize other aspects of the PDF page. After you create a page, all of your subsequent drawing commands are captured by the PDF graphics context and translated into PDF commands. You can draw anything you want in the page, including text, vectorshapes, and images just as you would in your app’s custom views. The drawing commands you issue are captured by the PDF context and translated into PDF data. Placement of content on the the page is completely up to you but must take place within the bounding rectangle of the page. Listing 4-2 shows two custom methods used to draw content inside a PDF page. The renderPageWithTextRange:andFramesetter: method uses Core Text to create a text frame that fits the page and then lay out some text inside that frame. After laying out the text, it returns an updated range that reflectsthe end of the current page and the beginning of the next page. The drawPageNumber: method uses the NSString drawing capabilities to draw a page number string at the bottom of each PDF page. Note: This code snippet makes use of the Core Text framework. Be sure to add it to your project. Listing 4-2 Drawing page-based content // Use Core Text to draw the text in a frame on the page. - (CFRange)renderPage:(NSInteger)pageNum withTextRange:(CFRange)currentRange andFramesetter:(CTFramesetterRef)framesetter { // Get the graphics context. CGContextRef currentContext = UIGraphicsGetCurrentContext(); // Put the text matrix into a known state. This ensures // that no old scaling factors are left in place. CGContextSetTextMatrix(currentContext, CGAffineTransformIdentity); Generating PDF Content Drawing PDF Pages 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 48// Create a path object to enclose the text. Use 72 point // margins all around the text. CGRect frameRect = CGRectMake(72, 72, 468, 648); CGMutablePathRef framePath = CGPathCreateMutable(); CGPathAddRect(framePath, NULL, frameRect); // Get the frame that will do the rendering. // The currentRange variable specifies only the starting point. The framesetter // lays out as much text as will fit into the frame. CTFrameRef frameRef = CTFramesetterCreateFrame(framesetter, currentRange, framePath, NULL); CGPathRelease(framePath); // Core Text draws from the bottom-left corner up, so flip // the current transform prior to drawing. CGContextTranslateCTM(currentContext, 0, 792); CGContextScaleCTM(currentContext, 1.0, -1.0); // Draw the frame. CTFrameDraw(frameRef, currentContext); // Update the current range based on what was drawn. currentRange = CTFrameGetVisibleStringRange(frameRef); currentRange.location += currentRange.length; currentRange.length = 0; CFRelease(frameRef); return currentRange; } - (void)drawPageNumber:(NSInteger)pageNum { NSString *pageString = [NSString stringWithFormat:@"Page %d", pageNum]; UIFont *theFont = [UIFont systemFontOfSize:12]; Generating PDF Content Drawing PDF Pages 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 49CGSize maxSize = CGSizeMake(612, 72); CGSize pageStringSize = [pageString sizeWithFont:theFont constrainedToSize:maxSize lineBreakMode:UILineBreakModeClip]; CGRect stringRect = CGRectMake(((612.0 - pageStringSize.width) / 2.0), 720.0 + ((72.0 - pageStringSize.height) / 2.0), pageStringSize.width, pageStringSize.height); [pageString drawInRect:stringRect withFont:theFont]; } Creating Links Within Your PDF Content Besides drawing content, you can also include links that take the user to another page in the same PDF file or to an external URL. To create a single link, you must add a source rectangle and a link destination to your PDF pages. One of the attributes of the link destination is a string that serves as the unique identifier for that link. To create a link to a specific destination, you specify the unique identifier for that destination when creating the source rectangle. To add a new link destination to your PDF content, you use the UIGraphicsAddPDFContextDestinationAtPoint function. This function associates a named destination with a specific point on the current page. When you want to link to that destination point, you use UIGraphicsSetPDFContextDestinationForRect function to specify the source rectangle for the link. Generating PDF Content Creating Links Within Your PDF Content 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 50Figure 4-1 shows the relationship between these two function calls when applied to the pages of your PDF documents. Tapping on the rectangle surrounding the “see Chapter 1” text takesthe user to the corresponding destination point, which is located at the top of Chapter 1. Figure 4-1 Creating a link destination and jump point Chapter 1 UIGraphicsAddPDFContextDestinationAtPoint Name: “Chapter_1” Point: (72, 72) see Chapter 1 UIGraphicsSetPDFContextDestinationForRect Name: “Chapter_1” Rect: (72, 528, 400, 44) In addition to creating links within a document, you can also use the UIGraphicsSetPDFContextURLForRect function to create links to content located outside of the document. When using this function to create links, you specify the target URL and the source rectangle on the current page. Generating PDF Content Creating Links Within Your PDF Content 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 51In iOS 4.2 and later, apps can add support for printing content to local AirPrint-capable printers. Although not all apps need printing support, it is often a useful feature if your app is used for creating content (such as a word processor or a drawing program), making purchases(printing order confirmations), and other tasks where the user might reasonably want a permanent record. This chapter explains how to add printing support to your app. At a high level, your app creates a print job, providing either an array of ready-to-print images and PDF documents, a single image or PDF document, an instance of any of the built-in print formatter classes, or a custom page renderer. Terminology Note: The notion of a print job comes up many times in this chapter. A print job is a unit of work that includes not just the content to be printed but information used in the printing of it, such as the identity of the printer, the name of the print job, and the quality and orientation of printing. Printing in iOS is Designed to be Simple and Intuitive To print, users tap a button that is usually in a navigation bar or toolbar that is associated with the view or selected item the user wants to print. The app then presents a view of printing options. The user selects a printer and various options and then requests printing. The app is asked to generate printing output from its content or provide printable data or file URLs. The requested print job is spooled and control returns to the app. If the destination printer is currently not busy, printing beginsimmediately. If the printer is already printing or if there are jobs before it in the queue, the print job remains in the iOS print queue until it moves to the top of queue and is printed. The Printing User Interface The first thing a user sees related to printing is a print button. The print button is often a bar-button item on a navigation bar or a toolbar. The print button should logically apply to the content the app is presenting; if the user taps the button, the app should print that content. Although the print button can be any custom 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 52 Printingbutton, it is recommended that you use the system item-action button shown in Figure 5-1. This is a UIBarButtonItem object, specified with the UIBarButtonSystemItemAction constant, that you create either in Interface Builder or by calling initWithBarButtonSystemItem:target:action:. Figure 5-1 System item action button—used for printing When a user taps the print button, a controller object of the app receives the action message. The controller responds by preparing for printing and displaying the printer-options view. The options always include the destination printer (selected from a list of discoverable printers), the number of copies, and sometimes the range of pages to print. If the selected printer is capable of duplex printing, users can choose single-sided or double-sided output. If users decide not to print, they tap outside the options view (on iPad) or tap the Cancel button (on iPhone and iPod touch) to dismiss the printer-options view. The kind of user interface shown depends on the device. On iPad, the UIKit framework displays a popover view containing the options, as shown in Figure 5-2. An app can animate this view to appear from the print button or from an arbitrary area of the app’s user interface. Figure 5-2 Printer-options popover view (iPad) Printing Printing in iOS is Designed to be Simple and Intuitive 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 53On iPhone and iPod touch devices, UIKit displays a sheet of printing options that an app can animate to slide up from the bottom of the screen, as shown in Figure 5-3. Figure 5-3 Printer-options sheet (iPhone) Printing Printing in iOS is Designed to be Simple and Intuitive 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 54Once a print job has been submitted and is either printing or waiting in the print queue, users can check on itsstatus by double-tapping the Home button to accessthe Print Center in the multitasking UI. The Print Center (shown in Figure 5-4) is a background system app that shows the order of jobs in the print queue, including those that are currently printing. It is only available while a print job is in progress. Figure 5-4 Print Center Printing Printing in iOS is Designed to be Simple and Intuitive 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 55Users can tap a print job in the Print Center to get detailed information about it (Figure 5-5) and cancel jobs that are printing or waiting in the queue. Figure 5-5 Print Center: detail of print job How Printing Works in iOS An app uses the UIKit printing API to assemble the elements of a print job, including the content to print and information related to the print job. It then presents the printer-options view described in “The Printing User Interface” (page 52). The user makes his or her choices and then taps Print. In some cases, the UIKit framework then asks the app to draw the content to be printed; UIKit records what the app draws as PDF data. UIKit then hands off the printing data to the printing subsystem. The printing system does a few things. As UIKit passes the print data to the printing subsystem, it writes this data to storage (that is, it spools the data). It also captures information about the print job. The printing system manages the combined print data and metadata for each print job in a first-in-first-out print queue. Multiple apps on a device can submit multiple print jobs to the printing subsystem, and all of these are placed in the print queue. Each device has one queue for all print jobs regardless of originating app or destination printer. Printing Printing in iOS is Designed to be Simple and Intuitive 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 56When a print job risesto the top of the queue, the system printing daemon (printd) considersthe destination printer's requirements and, if necessary, converts the print data to a form that is usable by the printer. The printing system reports error conditions such as "Out of Paper" to the user as alerts. It also reports the progress of print jobs programmatically to the Print Center, which displays information such as “page 2 of 5” for a print job. This overall architecture is shown in Figure 5-6. Figure 5-6 Printing architecture Application UIKit Print job Print job Print job Print job Printing subsystem Print Queue printd Printer The UIKit Printing API The UIKit printing API includes eight classes and one formal protocol. Objects of these classes and the delegate implementing the protocol have runtime relationships as depicted in Figure 5-7. Figure 5-7 Relationships of UIKit printing objects UIPrintFormatter subclass UIPrintPageRenderer subclass UIPrintInteractionController printInfo delegate printPaper printingItems printingItem printPageRenderer printFormatter UIPrintPaper paperSize printableRect numberOfPages headerHeight footerHeight paperRect printableRect printFormatters UIPrintFormatter UIPrintFormatter subclass subclass Inherited: contentInsets maximumContentWidth maximumContentHeight startPage pageCount , , , UIPrintInfo printerID jobName orientation duplex outputType Printing The UIKit Printing API 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 57Printing Support Overview At a high level, there are two waysto add printing to your app. If you are using a UIActivityViewController, and if you do not need the ability to control whether the user can choose a page range or override the paper selection process, you can add a printing activity. Otherwise, to add printing to your app, you must work with the UIPrintInteractionController class. A shared instance of the UIPrintInteractionController class provides your app with the ability to specify what should happen when the user tells your app to print. It contains information about the print job (UIPrintInfo) and the size of the paper and the area for the printed content (UIPrintPaper). It can also have a reference to a delegate object that adoptsthe UIPrintInteractionControllerDelegate protocol for further configuring behavior. More importantly, the print interaction controller lets your app provide the content to be printed. The UIPrintInteractionController class provides three distinct ways to print content: ● Static images or PDFs. For simple content, you can use the print interaction controller’s printingItem or printingItems properties to provide an image (in various formats), a PDF file, or an array of images and PDF files. ● Print formatters. If you need to print text and HTML content with automatic reflow, you can assign an instance of any of the built-in print formatter classesto the print interaction controller’s printFormatter property. ● Page renderers. Page renderers let you provide your own drawing routines for custom content, and give you complete control over the page layout, including headers and footers. To use a page renderer, you must first write a page renderer subclass, then assign an instance of it to the print interaction controller’s printPageRenderer property. Important: These four properties are mutually exclusive; that is, if you assign a value to one of the properties, UIKit makes sure that all the other properties are nil. With such a range of options available to you, what is the best option for your app? Table 5-1 clarifies the factors involved in making this decision. Table 5-1 Deciding how to print app content If... Then... Your app has access to directly printable Use the printingItem or printingItems properties. content (images or PDF documents). Printing The UIKit Printing API 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 58If... Then... You want to print a single image or PDF Use the printingItem property. document and want the user to be able to select a page range. Assign a UISimpleTextPrintFormatter or UIMarkupTextPrintFormatter object to the printFormatter property. The print-formatter object must be initialized with the plain or HTML text. You want to print a plain text or HTML document (and do not want additional content such as headers and footers). Get a UIViewPrintFormatter object from the view and assign it to the printFormatter property. You want to print the content of a UIKit view (and do not want additional content such as headers and footers). Assign an instance of a custom subclass of UIPrintPageRenderer to printPageRenderer. This subclass should implement the methods required for drawing headers and footers. You want the printed pages to have repeating headers and footers, possibly with incremented page numbers. Assign an instance of UIPrintPageRenderer (or a custom subclassthereof) to printPageRenderer. You can add one or more print formatters to render specific pages of content. If you are using a custom subclass of UIPrintPageRenderer, you also have the option of providing custom drawing code to render some or all of the pages yourself. You have mixed content or sources that you want to print—for example, HTML and custom drawing. Assign an instance of a custom subclass of UIPrintPageRenderer to printPageRenderer and draw everything that gets printed. You want to have the greatest amount of control over what gets drawn for printing. Printing Workflow The general workflow for printing an image, document, or other printable content of an app is as follows: 1. Obtain the shared instance of UIPrintInteractionController. 2. (Optional, but strongly recommended) Create a UIPrintInfo object, set attributes such as output type, job name, and print orientation; then assign the object to the printInfo property of the UIPrintInteractionController instance. (Setting the output type and job name are strongly recommended.) If you don’t assign a print-info object, UIKit assumes default attributes for the print job (for example, the job name is the app name). Printing The UIKit Printing API 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 593. (Optional) Assign a custom controller object to the delegate property. This object must adopt the UIPrintInteractionControllerDelegate protocol. The delegate can do a range of tasks. It can respond appropriately when printing options are presented and dismissed, and when the print job starts and ends. It can return a parent view controller for the print interaction controller. Also, by default, UIKit chooses a default paper size and printable area based on the output type, which indicates the kind of content your app is printing. If your app needs more control over paper size, you can override this standard behavior. See “Specifying Paper Size, Orientation, and Duplexing Options” (page 75) for more details. 4. Assign one of the following to a property of the UIPrintInteractionController instance: ● A single NSData, NSURL, UIImage, or ALAsset object containing or referencing PDF data or image data to the printingItem property. ● An array of directly printable images or PDF documents to the printingItems property. Array elements must be NSData, NSURL, UIImage, or ALAsset objects containing, referencing, or representing PDF data or images in supported formats. ● A UIPrintFormatter object to the printFormatter property. Print formatters perform custom layout of printable content. ● A UIPrintPageRenderer object to the printPageRenderer property. Only one of these properties can be non-nil for any print job. See “Printing Support Overview” (page 58) for descriptions of these properties. 5. If you assigned a page renderer in the previousstep, that object istypically an instance of a custom subclass of UIPrintPageRenderer. This object draws pages of content for printing when requested by the UIKit framework. It can also draw content in headers and footers of printed pages. A custom page renderer must override one or more of the “draw” methods and, if it is drawing at least part of the content (excluding headers and footers), it must compute and return the number of pages for the print job. (Note that you can use an instance of UIPrintPageRenderer “as-is” to connect a series of print formatters.) 6. (Optional) If you are using a page renderer, you can create one or more UIPrintFormatter objects using concrete subclasses of this class; then add the print formatters for specific pages (or page ranges) to the UIPrintPageRenderer instance either by calling the addPrintFormatter:startingAtPageAtIndex: method of UIPrintPageRenderer or by creating an array of one or more print formatters (each with its own starting page) and assigning that array to the printFormatters property of UIPrintPageRenderer. 7. If the current user-interface idiom is iPad, present the printing interface to the user by calling presentFromBarButtonItem:animated:completionHandler: or presentFromRect:inView:animated:completionHandler:; if the idiom is iPhone or iPod touch, call presentAnimated:completionHandler:. Alternatively, you can embed the printing UI into your existing UI by implementing a printInteractionControllerParentViewController: delegate method. If your app uses an activity sheet (in iOS 6.0 and later), you can also add a printing activity item. Printing The UIKit Printing API 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 60From here, the process varies depending on whether you are printing using static content, a print formatter, or a page renderer. Printing Printer-Ready Content The iOS printing system accepts certain objects and prints their contents directly, with minimal involvement by the app. These objects are instances of the NSData, NSURL, UIImage, and ALAsset classes, and they must contain or reference image data or PDF data. Image data involves all of these object types; PDF data is either referenced by NSURL objects or encapsulated by NSData objects. There are additional requirements for these printer-ready objects: ● An image must be in a format supported by the Image I/O framework. See “Supported Image Formats” in UIImage Class Reference for a list of these formats. ● NSURL objects must use as a scheme file:, assets-library:, or anything that can return an NSData with a registered protocol (for example, QuickLook’s x-apple-ql-id: scheme). ● ALAsset objects must be of type ALAssetTypePhoto. You assign printer-ready objects either to the printingItem or printingItems property of the shared UIPrintInteractionController instance. You assign a single printer-ready object to printingItem and an array of printer-ready objects to the printingItems property. Note: By providing printer-ready content, you are putting the layout of that content in the hands of the printing system. Thus, settings such as printing orientation have no effect. If your app needs to control layout, you must do the drawing yourself. Also, if your app uses printingItems for its printable content (as opposed to printingItem), users cannot specify page ranges in the printer-options view, even if there are multiple pages and the showsPageRange property is set to YES. Before assigning objects to the these properties, you should validate the objects by using one of the class methods of UIPrintInteractionController. If, for example, you have the UTI of an image and you want to verify that the image is printer-ready, you can test it first with the printableUTIs class method, which returns the set of UTIs that are valid for the printing system: if ([[UIPrintInteractionController printableUTIs] containsObject:mysteryImageUTI]) printInteractionController.printingItem = mysteryImage; Printing Printing Printer-Ready Content 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 61Similarly, you can apply the canPrintURL: and canPrintData: class methods of UIPrintInteractionController to NSURL and NSData objects prior to assigning those objects to the printingItem or printingItems properties. These methods determine if the printing system can directly print those objects. Their use is strongly recommended, especially for PDF. Listing 5-1 shows code that prints a PDF document encapsulated in an NSData object. Before assigning it to printingItem, it teststhe object’s validity. It also tellsthe print interaction controller to include the page-range controls in the printing options presented to the user. Listing 5-1 Printing a single PDF document with capability for page-range selection - (IBAction)printContent:(id)sender { UIPrintInteractionController *pic = [UIPrintInteractionController sharedPrintController]; if (pic && [UIPrintInteractionController canPrintData: self.myPDFData] ) { pic.delegate = self; UIPrintInfo *printInfo = [UIPrintInfo printInfo]; printInfo.outputType = UIPrintInfoOutputGeneral; printInfo.jobName = [self.path lastPathComponent]; printInfo.duplex = UIPrintInfoDuplexLongEdge; pic.printInfo = printInfo; pic.showsPageRange = YES: pic.printingItem = self.myPDFData; void (^completionHandler)(UIPrintInteractionController *, BOOL, NSError *) = ^(UIPrintInteractionController *pic, BOOL completed, NSError *error) { self.content = nil; if (!completed && error) NSLog(@"FAILED! due to error in domain %@ with error code %u", error.domain, error.code); }; if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { [pic presentFromBarButtonItem:self.printButton animated:YES completionHandler:completionHandler]; } else { Printing Printing Printer-Ready Content 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 62[pic presentAnimated:YES completionHandler:completionHandler]; } } The procedure for submitting several printer-ready objects at once is identical—except (of course), you must assign an array of these objects to the printingItems property: pic.printingItems = [NSArray arrayWithObjects:imageViewOne.image, imageViewTwo.image, imageViewThree.image, nil]; Using Print Formatters and Page Renderers Print formatters and page renderers are objectsthat lay out printable content over multiple pages. They specify the beginning page of content and compute the final page of content based on the starting page, the content area, and the content they lay out. They can also specify the margins relative to the printable area of the page. The difference can be summarized as follows: ● Print formatters lay out a single piece of content (a block of text or HTML, a view, and so on). ● Page renderers let you add headers and footers, perform custom drawing, and so on. Page renderers can, if desired, use print formatters to do most of their work. If you create a custom subclass of UIPrintPageRenderer, you can draw each page of printable content partially or entirely. A page renderer can have one or more print formatters associated with specific pages or page ranges of the printable content. Setting the Layout Properties for the Print Job To define the areas on pages for printable content, the UIPrintFormatter class declares four key properties for its concrete subclasses. These properties, along with the footerHeight and headerHeight properties of UIPrintPageRenderer and the paperSize and printableRect properties of UIPrintPaper, define the layout of a multi-page print job. Figure 5-8 (page 65) depicts this layout. Property Description Distances in points inset from the top, left, and right boundaries of the printable rectangle. These valuesset the margins of the printed content, although they can be overridden by the maximumContentHeight and maximumContentWidth values. The top inset applies only to the first page of a given formatter. contentInsets Printing Using Print Formatters and Page Renderers 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 63Property Description Specifies the maximum height of the content area, which factors in any header or footer height. UIKit compares this value against the height of the content area minus the top content-inset and uses the lesser of the two values. maximumContentHeight Specifies the maximum width of the content area. UIKit compares this value against the width of the content area created by the left content-inset and right content-inset and uses the lesser of the two values. maximumContentWidth The page on which this formatter should start drawing content for printing. This value is zero-based—the first page of output has a value of 0—but a formatter used by a pager renderer may begin drawing on a later page. For example, to tell a formatter to start printing on the third page, a page renderer would specify 2 for startPage. startPage Printing Using Print Formatters and Page Renderers 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 64Note: If you are using the printFormatter property of UIPrintInteractionController, there is no UIPrintPageRenderer object, which means you cannot specify headers or footers on the printed pages. Figure 5-8 The layout of a multi-page print job Paper rect Printable rect Right content inset Maximum content width Start page Page 1 Page 3 Header height Top content inset Footer height Left content inset Page 2 Maximum content height UIPrintFormatter uses all the properties depicted in the diagram in Figure 5-8 to compute the number of pages needed for the print job; it stores this value in the read-only pageCount property. Using a Print Formatter UIKit allows you to assign a single print formatter for a print job. This can be a useful capability if you have plain-text or HTML documents, because UIKit has concrete print-formatter classes for these types of textual content. The framework also implements a concrete print-formatter subclass that enables you to print the content of certain UIKit views in a printer-friendly way. The UIPrintFormatter class is the abstract base class for the system-provided print formatters. Currently, iOS provides the following built-in print formatters: ● UIViewPrintFormatter—automatically lays out the content of a view over multiple pages. To obtain a print formatter for a view, call the view’s viewPrintFormatter method. Printing Using Print Formatters and Page Renderers 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 65Not all built-in UIKit classes support printing. Currently, only the view classes UIWebView, UITextView, and MKMapView know how to draw their contents for printing. View formatters should not be used for printing your own custom views. To print the contents of a custom view, use a UIPrintPageRenderer instead. ● UISimpleTextPrintFormatter—automatically draws and lays out plain-text documents. Thisformatter allows you to set global properties for the text, such a font, color, alignment, and line-break mode. ● UIMarkupTextPrintFormatter—automatically draws and lays out HTML documents. Note: The UIPrintFormatter class is not intended to be subclassed by third-party developers. If you need to do custom layout, you should write a page renderer instead. Although the following discussion pertains to the use of a single formatter (and no page renderer), much of the information about print formatters applies to print formatters used in conjunction with page renderers, which is described in “Using One or More Formatters with a Page Renderer” (page 72). Printing Text or HTML Documents Many apps include textual content that users might want to print. If the content is plain text or HTML text, and you have access to the backing string for the displayed textual content, you can use an instance of UISimpleTextPrintFormatter or UIMarkupTextPrintFormatter to lay out and draw the text for printing. Simply create the instance, initializing it with the backing string, and specify the layout properties. Then assign it to the printFormatter instance variable of the shared UIPrintInteractionController instance. Listing 5-2 illustrates how you might use a UIMarkupTextPrintFormatter object to print an HTML document. It adds an additional inch of margin inside the (printer-defined) printable area. You can determine the printable area by examining the printPaper property of the UIPrintInteractionController object. For a more complete example of how to create margins of a specific width, see the PrintWebView sample code project. Listing 5-2 Printing an HTML document (without header information) - (IBAction)printContent:(id)sender { UIPrintInteractionController *pic = [UIPrintInteractionController sharedPrintController]; pic.delegate = self; UIPrintInfo *printInfo = [UIPrintInfo printInfo]; printInfo.outputType = UIPrintInfoOutputGeneral; Printing Using Print Formatters and Page Renderers 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 66printInfo.jobName = self.documentName; pic.printInfo = printInfo; UIMarkupTextPrintFormatter *htmlFormatter = [[UIMarkupTextPrintFormatter alloc] initWithMarkupText:self.htmlString]; htmlFormatter.startPage = 0; htmlFormatter.contentInsets = UIEdgeInsetsMake(72.0, 72.0, 72.0, 72.0); // 1 inch margins pic.printFormatter = htmlFormatter; pic.showsPageRange = YES; void (^completionHandler)(UIPrintInteractionController *, BOOL, NSError *) = ^(UIPrintInteractionController *printController, BOOL completed, NSError *error) { if (!completed && error) { NSLog(@"Printing could not complete because of error: %@", error); } }; if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { [pic presentFromBarButtonItem:sender animated:YES completionHandler:completionHandler]; } else { [pic presentAnimated:YES completionHandler:completionHandler]; } } Remember that if you use a single print formatter for a print job (that is, a UIPrintFormatter object assigned to the printFormatter property of the UIPrintInteractionController instance), you cannot draw header and footer content on each printed page. To do this you must use a UIPrintPageRenderer object plus any needed print formatters. For more information, see “Using One or More Formatters with a Page Renderer” (page 72). The procedure for using a UISimpleTextPrintFormatter object to lay out and print a plain text document is almost identical. However, the class of this object includes properties that enable you to set the font, color, and alignment of the printed text. Printing Using Print Formatters and Page Renderers 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 67Using a View Print Formatter You can use an instance of the UIViewPrintFormatter class to lay out and print the contents of some system views. The UIKit framework creates these view print formatters for the view. Often the same code used to draw the view for display is used to draw the view for printing. Currently, the system views whose contents you can print using a view print formatter are instances of UIWebView, UITextView, and MKMapView (MapKit framework). To get the view print formatter for a UIView object, call viewPrintFormatter on the view. Set the starting page and any layout properties and then assign the object to the printFormatter property of the UIPrintInteractionController shared instance. Alternatively, you can add the view print formatter to a UIPrintPageRenderer object if you are using that object to draw portions of the printed output. Listing 5-3 shows code that uses a view print formatter from a UIWebView object to print the contents of that view. Listing 5-3 Printing the contents of a web view - (void)printWebPage:(id)sender { UIPrintInteractionController *controller = [UIPrintInteractionController sharedPrintController]; void (^completionHandler)(UIPrintInteractionController *, BOOL, NSError *) = ^(UIPrintInteractionController *printController, BOOL completed, NSError *error) { if(!completed && error){ NSLog(@"FAILED! due to error in domain %@ with error code %u", error.domain, error.code); } }; UIPrintInfo *printInfo = [UIPrintInfo printInfo]; printInfo.outputType = UIPrintInfoOutputGeneral; printInfo.jobName = [urlField text]; printInfo.duplex = UIPrintInfoDuplexLongEdge; controller.printInfo = printInfo; controller.showsPageRange = YES; UIViewPrintFormatter *viewFormatter = [self.myWebView viewPrintFormatter]; viewFormatter.startPage = 0; controller.printFormatter = viewFormatter; Printing Using Print Formatters and Page Renderers 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 68if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { [controller presentFromBarButtonItem:printButton animated:YES completionHandler:completionHandler]; }else [controller presentAnimated:YES completionHandler:completionHandler]; } For a complete example based on UIViewPrintFormatter, see the PrintWebView sample code project. Using a Page Renderer A page renderer is an instance of a custom subclass of UIPrintPageRenderer that draws the full or partial content of a print job. To use one, you must create the subclass, add it to your project, and instantiate it when you prepare a UIPrintInteractionController instance for a print job. Then assign the page renderer to the printPageRenderer property of the UIPrintInteractionController instance. A page renderer can have one or more print formatters associated with it; if it does, it mixes its drawing with the drawing of the print formatters. A page renderer can draw and lay out printable content on its own or it can use print formatters to handle some or all of the rendering of specific ranges of pages. Thus, for relatively straightforward formatting needs, you can use an instance of UIPrintPageRenderer “as-is” to connect multiple print formatters. However, most page renderers are typically instances of custom subclasses of UIPrintPageRenderer. Note: If you want to print header and footer information, such as a repeating document title and an incrementing page count, you must use a custom subclass of UIPrintPageRenderer. The UIPrintPageRenderer base class includes properties for the page count and for heights of headers and footers of pages. It also declares several methods that you can override to draw specific portions of a page: the header, the footer, the content itself, or to integrate page renderer and print formatter drawing. Setting Page Renderer Attributes If your page renderer is going to draw in the header or footer of each printed page, you should specify a height for the header and footer. To do this, assign float values (representing points) to the headerHeight and footerHeight properties inherited by your subclass. If these properties have height values of 0 (the default), the drawHeaderForPageAtIndex:inRect: and drawFooterForPageAtIndex:inRect: methods are not called. Printing Using Print Formatters and Page Renderers 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 69If your page renderer is going to draw in the content area of the page—that is, the area between any header or footer areas—then your subclass should override the numberOfPages method to compute and return the number of pages the page renderer will draw. If print formatters associated with the page renderer are going to draw all of the content between the header and footer, then the print formatters will compute the number of pages for you. This situation occurs your page renderer just draws in the header and footer areas and you let the print formatter draw all the other content. With a page renderer with no associated print formatter, the layout of each page of printable content is entirely up to you. When computing layout metrics, you can take into account the headerHeight, footerHeight, paperRect, and printableRect properties of UIPrintPageRenderer (the lasttwo properties are read-only). If the page renderer uses print formatters, the layout metrics also include the contentInsets, maximumContentHeight, and maximumContentWidth properties of UIPrintFormatter. See “Setting the Layout Properties for the Print Job” (page 63) for an illustration and explanation. Implementing the Drawing Methods When an app uses a page renderer to draw printable content, UIKit calls the following methods for each page of requested content. Note that there is no guarantee that UIKit calls these methods in page-sequence order. Moreover, if users request a subset of pages for printing (that is, they specify a page range), UIKit does not invoke the methods for pages not in the subset. Note: Remember that if you are drawing images or PDF documents as printable content using non-UIKit API (for example, Quartz API), then you must "flip” the UIKit’s coordinate system—putting the origin in the lower-left corner with positive values going upwards—to match the coordinate system used by Core Graphics. See “Coordinate Systems and Drawing in iOS” (page 13) for more information. The drawPageAtIndex:inRect: method calls each of the other draw methods, in the order listed below. Your app can override this method if you want to have complete control over what is drawn for printing. Override... To... Draw content in the header. This method is not called if headerHeight is 0. drawHeaderForPageAtIndex: inRect: Draw the content of the print job (that is, the area between the header and the footer). drawContentForPageAtIndex: inRect: Printing Using Print Formatters and Page Renderers 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 70Override... To... Intermix custom drawing with the drawing performed by print formatters. This method is called for each print formatter associated with a given page. See “Using One or More Formatters with a Page Renderer” (page 72) for more information. drawPrintFormatter: forPageAtIndex: Draw content in the footer. This method is not called if footerHeight is 0. drawFooterForPageAtIndex: inRect: All of these drawing methods are set up for drawing to the current graphics context (as returned by UIGraphicsGetCurrentContext). The rectangle passed into each method—defining header area, footer area, content area, and entire page—has values relative to the origin of the page, which is in the upper-left corner. Listing 5-4 shows example implementations of the drawHeaderForPageAtIndex:inRect: and drawFooterForPageAtIndex:inRect: methods. They use CGRectGetMaxX and CGRectGetMaxY to compute placement of text in the footerRect and headerRect rectangles in the coordinate system of the printable rectangle. Listing 5-4 Drawing the header and footer of a page - (void)drawHeaderForPageAtIndex:(NSInteger)pageIndex inRect:(CGRect)headerRect { UIFont *font = [UIFont fontWithName:@"Helvetica" size:12.0]; CGSize titleSize = [self.jobTitle sizeWithFont:font]; //center title in header CGFloat drawX = CGRectGetMaxX(headerRect)/2 - titleSize.width/2; CGFloat drawY = CGRectGetMaxY(headerRect) - titleSize.height; CGPoint drawPoint = CGPointMake(drawX, drawY); [self.jobTitle drawAtPoint:drawPoint withFont: font]; } - (void)drawFooterForPageAtIndex:(NSInteger)pageIndex inRect:(CGRect)footerRect { UIFont *font = [UIFont fontWithName:@"Helvetica" size:12.0]; NSString *pageNumber = [NSString stringWithFormat:@"%d.", pageIndex+1]; // page number at right edge of footer rect CGSize pageNumSize = [pageNumber sizeWithFont:font]; Printing Using Print Formatters and Page Renderers 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 71CGFloat drawX = CGRectGetMaxX(footerRect) - pageNumSize.width - 1.0; CGFloat drawY = CGRectGetMaxY(footerRect) - pageNumSize.height; CGPoint drawPoint = CGPointMake(drawX, drawY); [pageNumber drawAtPoint:drawPoint withFont: font]; } Using One or More Formatters with a Page Renderer A page renderer can draw printable content in conjunction with one or more print formatters. For example, an app can use a UISimpleTextPrintFormatter object to draw pages of textual content for printing, but use a page renderer to draw a document title in each page header. Or an app can use two print formatters, one to draw header (or summary) information at the beginning of the first page and another print formatter to draw the remaining content; then it might use a page renderer to draw a line separating the two parts. As you may recall, you can use a single print formatter for a print job by assigning it the printFormatter property of the UIPrintInteractionController shared instance. But if you use a page renderer and print formatters, you must associate each print formatter with the page renderer. You do this one of two ways: ● Include each print formatter in the array assigned to the printFormatters property. ● Add each print formatter by calling the addPrintFormatter:startingAtPageAtIndex: method. Before you associate a print formatter with a page renderer, be sure to set its layout properties, including the starting page (startPage) of the print job. Once you have set these properties, UIPrintFormatter computes the number of pages for the print formatter. Note that if you specify a starting page by calling addPrintFormatter:startingAtPageAtIndex:; that value overwrites any value assigned to startPage. For a discussion of print formatters and layout metrics,see “Setting the Layout Propertiesfor the PrintJob” (page 63). A page renderer can override drawPrintFormatter:forPageAtIndex: to integrate its drawing with the drawing performed by the print formatters assigned to a given page. It can draw in an area of the page where the print formatter doesn’t draw and then call the drawInRect:forPageAtIndex: method on the passed-in print formatter to have it draw its portion of the page. Or the page renderer can achieve an “overlay” effect by having the print formatter draw first and then drawing something over the content drawn by the print formatter. For complete examples based on UIPrintPageRenderer, see the PrintPhoto , Recipes and Printing , and PrintWebView sample code projects. Printing Using Print Formatters and Page Renderers 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 72Testing the Printing of App Content The iOS 4.2 SDK (and later) provides a Printer Simulator app that you can use to test your app’s printing capabilities. The app simulates printers of various general types (inkjet, black-and-white laser, color laser, and so on). It displays printed pages in the OS X Preview app. You can set a preference to show the printable area of each page. Printer Simulator also logs information from the printing system about each print job. You can run the Printer Simulator in one of thee ways: ● Choose Open Printer Simulator from the File menu in the iOS Simulator. ● Choose the Printer Simulator in Xcode using the Xcode > Open Developer Tool menu. ● You can find Printer Simulator in the following file-system location: /Platforms/iPhoneOS.platform/Developer/Applications/PrinterSimulator.app When testing your app’s printing code, you should also implement the completion handler passed into the present... methods and log any errors returned from the printing system. These errors are typically programming errors, which you should catch before your app is deployed. See “Responding to Print-Job Completion and Errors” (page 79) for details. Common Printing Tasks All the coding tasks described below are things that an app does (or can do) in response to a request for printing. Although most of the tasks can occur in any order, you should first check that the device is capable of printing and you should conclude with presenting the printing options. See “Printing Printer-Ready Content” (page 61), “Using Print Formatters and Page Renderers” (page 63), and “Using a Page Renderer” (page 69) for complete examples. An important set of tasks not covered here is adding a print button to an appropriate place in the app’s user interface, declaring an action method, making a target-action connection, and implementing the action method. (See “The Printing User Interface” (page 52) for a recommendation on which print button to use.) The following tasks (except for “Specifying Paper Size, Orientation, and Duplexing Options” (page 75)) are part of the implementation of the action method. Testing for Printing Availability Some iOS devices do not support printing. You should immediately determine this fact once your view loads. If printing is not available for the device, you should either not programmatically add any printing user-interface element (button, bar button item, and so on), or you should remove any printing element loaded from a nib Printing Testing the Printing of App Content 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 73file. To determine if printing is available, call the isPrintingAvailable class method of UIPrintInteractionController. Listing 5-5 illustrates how you might do this; it assumes an outlet to a print button (myPrintButton) loaded from a nib file. Listing 5-5 Enabling or disabling a print button based on availability of printing - (void)viewDidLoad { if (![UIPrintInteractionController isPrintingAvailable]) [myPrintButton removeFromSuperView]; // other tasks... } Note: Although you could disable a printing element such as an “action” bar button item, removal is recommended. The value returned by isPrintingAvailable never changes for a given device because it reflects whether that device supports printing, not whether printing is currently available. Specifying Print-Job Information An instance of the UIPrintInfo class encapsulates information about a print job, specifically: ● The output type (indicating the type of content) ● The print-job name ● The printing orientation ● The duplex mode ● The identifier of the selected printer You do not need to assign values to all UIPrintInfo properties; users choose some of these values and UIKit assumes default valuesfor others. (Indeed, you don’t even have to explicitly create an instance of UIPrintInfo.) However, in most cases you’ll want to specify some aspects of a print job, such as output type. Get an instance of UIPrintInfo by calling the printInfo class method. Assign values to the object’s properties you want to configure. Then assign the UIPrintInfo object to the printInfo property of the shared UIPrintInteractionController instance. Listing 5-6 gives an example of this procedure. Listing 5-6 Setting properties of a UIPrintInfo object and assigning it to the printInfo property UIPrintInteractionController *controller = [UIPrintInteractionController sharedPrintController]; Printing Common Printing Tasks 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 74UIPrintInfo *printInfo = [UIPrintInfo printInfo]; printInfo.outputType = UIPrintInfoOutputGeneral; printInfo.jobName = [self.path lastPathComponent]; printInfo.duplex = UIPrintInfoDuplexLongEdge; controller.printInfo = printInfo; One of the UIPrintInfo properties is the printing orientation: portrait or landscape. You might want the printing orientation to suit the dimensions of the object being printed. In other words, if the object is large, and its width is greater than its height, landscape would be a suitable printing orientation for it. Listing 5-7 illustrates this with an image. Listing 5-7 Setting the printing orientation to match image dimension UIPrintInteractionController *controller = [UIPrintInteractionController sharedPrintController]; // other code here... UIPrintInfo *printInfo = [UIPrintInfo printInfo]; UIImage *image = ((UIImageView *)self.view).image; printInfo.outputType = UIPrintInfoOutputPhoto; printInfo.jobName = @"Image from PrintPhoto"; printInfo.duplex = UIPrintInfoDuplexNone; // only if drawing... if (!controller.printingItem && image.size.width > image.size.height) printInfo.orientation = UIPrintInfoOrientationLandscape; Specifying Paper Size, Orientation, and Duplexing Options By default, UIKit presents a set of default paper sizes for printable content based on the destination printer and the output type of the print job, as specified by the outputType property of the UIPrintInfo object. For example, if the output type is UIPrintInfoOutputPhoto, the default paper size is 4 x 6 inches, A6, or some other standard size, depending on locale; if the output type is UIPrintInfoOutputGeneral or UIPrintInfoOutputGrayscale, the default paper size is US Letter (8 1/2 x 11 inches), A4, or some other standard size, depending on locale. For most apps, these default paper sizes are acceptable. However, some apps might need a special paper size. A page-based app might need to show the user how content will actually appear on paper of a given size, an app that produces brochures or greeting cards might have its own preferred size, and so on. Printing Common Printing Tasks 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 75In this case, the delegate of the print interaction controller can implement the UIPrintInteractionControllerDelegate protocol method printInteractionController:choosePaper: to return a UIPrintPaper objectrepresenting the optimal combination of available paper size and printable rectangle for a given content size. The delegate has two approaches it can take. It can examine the passed-in array of UIPrintPaper objects and identify the one that is most suitable. Or it can let the system pick the most suitable object by calling the UIPrintPaper class method bestPaperForPageSize:withPapersFromArray:. Listing 5-8 shows an implementation of the method for an app that supports multiple document types, each with its own page size. Listing 5-8 Implementing the printInteractionController:choosePaper: method - (UIPrintPaper *)printInteractionController:(UIPrintInteractionController *)pic choosePaper:(NSArray *)paperList { // custom method & properties... CGSize pageSize = [self pageSizeForDocumentType:self.document.type]; return [UIPrintPaper bestPaperForPageSize:pageSize withPapersFromArray:paperList]; } Typically, apps that use custom page renderers factor the paper size into their calculations of the number of pages for a print job (numberOfPages). If your app needs to present the user with a choice of page size (for a word processing app, for example), you must implement that UI yourself, and you must then use that paper size in your printInteractionController:choosePaper: implementation. For example: // Create a custom CGSize for 8.5" x 11" paper. CGSize custompapersize = CGSizeMake(8.5 * 72.0, 11.0 * 72.0); The UIPrintInfo class also lets you provide additional settings, such as the printing orientation, selected printer, and the duplexing mode (if the printersupports duplex printing). Users can change the selected printer and duplex settings from the values you provide Integrating Printing Into Your User Interface There are two ways to integrate printing into your user interface: Printing Common Printing Tasks 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 76● Using a print interaction controller. ● From the activity sheet (in iOS 6.0 and later). The way you integrate printing depends on which of these techniques you choose. Presenting Printing Options Using a Print Interaction Controller UIPrintInteractionController declares three methods for presenting the printing options to users, each with its own animation: ● presentFromBarButtonItem:animated:completionHandler: animates a popover view from a button in the navigation bar or toolbar (usually the print button). ● presentFromRect:inView:animated:completionHandler: animates a popover view from an arbitrary rectangle in the app’s view. ● presentAnimated:completionHandler: animates a sheet that slides up from the bottom of the screen. The first two of these methods are intended to be invoked on iPad devices; the third method is intended to be invoked on iPhone and iPod touch devices. You can conditionally code for each device type (or, user-interface idiom) by calling the UI_USER_INTERFACE_IDIOM and comparing the result to UIUserInterfaceIdiomPad or UIUserInterfaceIdiomPhone. Listing 5-9 gives an example of this. Listing 5-9 Presenting printing options based upon current device type if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { [controller presentFromBarButtonItem:self.printButton animated:YES completionHandler:completionHandler]; } else { [controller presentAnimated:YES completionHandler:completionHandler]; } If your app calls one of the iPad-specific methods on an iPhone (and requests animation), the default behavior is to display the printing options in a sheet that slides up from the bottom of the screen. If your app calls the iPhone-specific method on iPad, the default behavior is to animate the popover view from the current window frame. If you call one of the present… methods when the printing options are already displayed, UIPrintInteractionController hidesthe printing-options view orsheet. You must call the method again to display the options. Printing Common Printing Tasks 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 77If you assign a printer ID or a duplex mode as print-info values, these appear as defaultsin the printing options. (The printer must be capable of double-sided printing for the duplex control to appear.) If you want to let your users select ranges of pages for printing, you should set the showsPageRange property of the UIPrintInteractionController object to YES (NO is the default value). Be aware, however, that no page-range control appears in the printing options if you supply printable content via the printingItems property or if the total number of pages is 1, even if showsPageRange is YES. If you want the printing UI to appear within a particular view, you can do this by implementing the printInteractionControllerParentViewController: method in your UIPrintInteractionControllerDelegate class. This method should return the view controller that should be used as the parent for the print interaction controller. If the provided parent view controller is a UINavigationController instance, the printing UI is pushed into view in that controller. For any other UIViewController instance, the print navigation is shown as a modal dialog within the specified view. Printing From the Activity Sheet If your app uses an activity sheet (in iOS 6.0 and later), you can allow printing from the activity sheet. Printing from the activity sheet is simpler than using a print interaction controller. There are two caveats, however: ● The app cannot control whether a user can choose a page range. ● The app cannot use delegate methods to override behavior, such as manually overriding the paper size selection process. To use this technique, your app must create an activity items array containing: ● A UIPrintInfo object. ● Either a page renderer formatter object, a page renderer or a printable item. ● Any additional activity items appropriate for your app. You then call initWithActivityItems:applicationActivities:, passing that array asthe first parameter and nil as the second parameter (or an array of custom activities, if your app provides any). Finally, you present the activity view using the standard view controller present* methods. If the user chooses to printfromthat activity view, iOS creates a printjob for you. Formore information,read UIActivityViewController Class Reference and UIActivity Class Reference . Printing Common Printing Tasks 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 78Responding to Print-Job Completion and Errors The final parameter of the presentation methods declared by UIPrintInteractionController and described in “Presenting Printing Options Using a Print Interaction Controller ” (page 77) is a completion handler. The completion handler is a block of type UIPrintInteractionCompletionHandler that isinvoked when a print job completes successfully or when it is terminated because of an error. You can provide a block implementation that cleans up state that you have set up for the print job. The completion handler can also log error messages. The example in Listing 5-10 clears an internal property upon completion or error; if there is an error, it logs information about it. Listing 5-10 Implementing a completion-handler block void (^completionHandler)(UIPrintInteractionController *, BOOL, NSError *) = ^(UIPrintInteractionController *pic, BOOL completed, NSError *error) { self.content = nil; if (!completed && error) NSLog(@"FAILED! due to error in domain %@ with error code %u", error.domain, error.code); }; UIKit automatically releases all objects assigned to the UIPrintInteractionController instance at the end of a print job (except for the delegate), so you do not have to do this yourself in a completion handler. A printing error isrepresented by an NSError object having a domain of UIPrintErrorDomain and an error code declared in UIPrintError.h. In almost all cases, these codes indicate programming errors, so usually there is no need to inform the user about them. However, some errors can result from an attempt to print a file (located by a file-scheme NSURL object) that results in an error. Printing Common Printing Tasks 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 79Drawing is a relatively expensive operation on any platform, and optimizing your drawing code should always be an important step in your development process. Table A-1 lists several tips for ensuring that your drawing code is as optimal as possible. In addition to these tips, you should always use the available performance tools to test your code and remove hotspots and redundancies. Table A-1 Tips for improving drawing performance Tip Action During each update cycle, you should update only the portions of your view that actually changed. If you are using the drawRect: method of UIView to do your drawing, use the update rectangle passed to that method to limit the scope of your drawing. For OpenGL drawing, you must track updates yourself. Draw minimally If you are calling setNeedsDisplay:, always spend the time to calculate the actual area that you need to redraw. Don’t just pass a rectangle containing the entire view. Also, don’t call setNeedsDisplay: unless you actually need to redraw content. If the content hasn’t actually changed, don’t redraw it. Call setNeedsDisplay: judiciously Compositing a view whose contents are opaque requires much less effort than compositing one that is partially transparent. To make a view opaque, the contents of the view must not contain any transparency and the opaque property of the view must be set to YES. Mark opaque views as such Creating new views during scrolling should be avoided at all costs. Taking the time to create new views reduces the amount of time available for updating the screen, which leads to uneven scrolling behavior. Reuse table cells and views during scrolling By modifying the current transformation matrix, you can use a single path to draw content on different parts of the screen. For details, see “Using Coordinate Transforms to Improve Drawing Performance” (page 24). Reuse paths by modifying the current transformation matrix By default, UIKit clears a view’s current context buffer prior to calling its drawRect: method to update that same area. If you are responding to scrolling eventsin your view, clearing thisregion repeatedly during scrolling updates can be expensive. To disable the behavior, you can change the value in the clearsContextBeforeDrawing property to NO. Avoid clearing the previous content during scrolling 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 80 Improving Drawing PerformanceTip Action Changing the graphics state requires work by the underlying graphics subsystems. If you need to draw content that usessimilarstate information, try to draw that content together to reduce the number of state changes needed. Minimize graphics state changes while drawing The Core Animation instrument can help you spot drawing performance problems in your app. In particular: ● Flash Updated Regions makes it easy to see what parts of your view are actually being updated. ● Color Misaligned Images helps you see imagesthat are aligned poorly, which results in both fuzzy images and poor performance. For more information,see “Measuring Graphics Performance in Your iOS Device” in Instruments User Guide . Use Instruments to debug your performance Improving Drawing Performance 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 81Apps built against iOS SDK 4.0 and later need to be prepared to run on devices with differentscreen resolutions. Fortunately, iOS makes supporting multiple screen resolutions easy. Most of the work of handling the different types of screens is done for you by the system frameworks. However, your app still needs to do some work to update raster-based images, and depending on your app you may want to do additional work to take advantage of the extra pixels available to you. See “Points Versus Pixels” (page 16) for important background information related to this topic. Checklist for Supporting High-Resolution Screens To update your apps for devices with high-resolution screens, you need to do the following: ● Provide a high-resolution image for each image resource in your app bundle, as described in “Updating Your Image Resource Files” (page 83). ● Provide high-resolution app and document icons, as described in “Updating Your App’s Icons and Launch Images” (page 85). ● For vector-based shapes and content, continue using your custom Core Graphics and UIKit drawing code as before. If you want to add extra detail to your drawn content, see “Points Versus Pixels” (page 16) for information on how to do so. ● If you use OpenGL ES for drawing, decide whether you want to opt in to high-resolution drawing and set the scale factor of your layer accordingly, as described in “Drawing High-Resolution Content Using OpenGL ES or GLKit” (page 85). ● For custom images that you create, modify your image-creation code to take the current scale factor into account, as described in “Drawing to Bitmap Contexts and PDF Contexts” (page 19). ● If your app uses Core Animation, adjust your code as needed to compensate for scale factors, as described in “Accounting for Scale Factors in Core Animation Layers” (page 28). Drawing Improvements That You Get for Free The drawing technologies in iOS provide a lot of support to help you make your rendered content look good regardless of the resolution of the underlying screen: 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 82 Supporting High-Resolution Screens In Views● Standard UIKit views (text views, buttons, table views, and so on) automatically render correctly at any resolution. ● Vector-based content (UIBezierPath, CGPathRef, PDF) automatically takes advantage of any additional pixels to render sharper lines for shapes. ● Text is automatically rendered at higher resolutions. ● UIKit supports the automatic loading of high-resolution variants (@2x) of your images. If your app uses only native drawing technologies for its rendering, the only thing you need to do to support higher-resolution screens is provide high-resolution versions of your images. Updating Your Image Resource Files Apps running in iOS 4 should now include two separate files for each image resource. One file provides a standard-resolution version of a given image, and the second provides a high-resolution version of the same image. The naming conventions for each pair of image files is as follows: ● Standard: . ● High resolution: @2x. The and portions of each name specify the usual name and extension for the file. The portion is optional and contains either the string ~ipad or ~iphone. You include one of these modifiers when you want to specify different versions of an image for iPad and iPhone. The inclusion of the @2x modifier for the high-resolution image is new and letsthe system know that the image is the high-resolution variant of the standard image. Important: The order of the modifiers is critical. If you incorrectly put the @2x after the device modifier, iOS will not find the image. When creating high-resolution versions of your images, place the new versions in the same location in your app bundle as the original. Loading Images into Your App The UIImage class handles all of the work needed to load high-resolution imagesinto your app. When creating new image objects, you use the same name to request both the standard and the high-resolution versions of your image. For example, if you have two image files, named Button.png and Button@2x.png, you would use the following code to request your button image: Supporting High-Resolution Screens In Views Updating Your Image Resource Files 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 83UIImage *anImage = [UIImage imageNamed:@"Button"]; Note: In iOS 4 and later, you may omit the filename extension when specifying image names. On devices with high-resolution screens, the imageNamed:, imageWithContentsOfFile:, and initWithContentsOfFile: methods automatically looksfor a version of the requested image with the @2x modifier in its name. If it finds one, it loads that image instead. If you do not provide a high-resolution version of a given image, the image object still loads a standard-resolution image (if one exists) and scales it during drawing. When it loads an image, a UIImage object automatically sets the size and scale properties to appropriate values based on the suffix of the image file. For standard resolution images, it sets the scale property to 1.0 and sets the size of the image to the image’s pixel dimensions. For images with the @2x suffix in the filename, it sets the scale property to 2.0 and halves the width and height values to compensate for the scale factor. These halved values correlate correctly to the point-based dimensions you need to use in the logical coordinate space to render the image. Note: If you use Core Graphics to create an image, remember that Quartz images do not have an explicit scale factor, so their scale factor is assumed to be 1.0. If you want to create a UIImage object from a CGImageRef data type, use the initWithCGImage:scale:orientation: to do so. That method allows you to associate a specific scale factor with your Quartz image data. A UIImage object automatically takes its scale factor into account during drawing. Thus, any code you have for rendering images should work the same as long as you provide the correct image resources in your app bundle. Using an Image View to Display Multiple Images If your app uses the UIImageView class to present multiple images for a highlight or animation, all of the images you assign to that view must use the same scale factor. You can use an image view to display a single image or to animate several images, and you can also provide a highlight image. Therefore, if you provide high-resolution versions for one of these images, then all must have high-resolution versions as well. Supporting High-Resolution Screens In Views Updating Your Image Resource Files 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 84Updating Your App’s Icons and Launch Images In addition to updating your app’s custom image resources, you should also provide new high-resolution icons for your app’s icon and launch images. The process for updating these image resources is the same as for all other image resources. Create a new version of the image, add the @2x modifier string to the corresponding image filename, and treat the image as you do the original. For example, for app icons, add the high-resolution image filename to the CFBundleIconFiles key of your app’s Info.plist file. For information about specifying the icons and launch images for your app, see “App-Related Resources” in iOS App Programming Guide . Drawing High-Resolution Content Using OpenGL ES or GLKit If your app uses OpenGL ES or GLKit for rendering, your existing drawing code should continue to work without any changes. When drawn on a high-resolution screen, though, your content is scaled accordingly and will appear more blocky. The reason for the blocky appearance is that the default behavior of the CAEAGLLayer class, which you use to back your OpenGL ES renderbuffers (directly or indirectly), is the same as other Core Animation layer objects. In other words, its scale factor is set to 1.0 initially, which causes the Core Animation compositor to scale the contents of the layer on high-resolution screens. To avoid this blocky appearance, you need to increase the size of your OpenGL ES renderbuffers to match the size of the screen. (With more pixels, you can then increase the amount of detail you provide for your content.) Because adding more pixels to your renderbuffers has performance implications, though, you must explicitly opt in to support high-resolution screens. To enable high-resolution drawing, you must change the scale factor of the view you use to present your OpenGL ES or GLKit content. Changing the contentScaleFactor property of your view from 1.0 to 2.0 triggers a matching change to the scale factor of the underlying CAEAGLLayer object. The renderbufferStorage:fromDrawable: method, which you use to bind the layer object to your renderbuffers, calculatesthe size of the render buffer by multiplying the layer’s bounds by itsscale factor. Thus, doubling the scale factor doubles the width and height of the resulting render buffer, giving you more pixels for your content. After that, it is up to you to provide the content for those additional pixels. Listing B-1 shows the proper way to bind your layer object to your renderbuffers and retrieve the resulting size information. If you used the OpenGL ES app template to create your code, then this step is already done for you, and the only thing you need to do is set the scale factor of your view appropriately. If you did not use the OpenGL ES app template, you should use code similar to this to retrieve the render buffer size. You should never assume that the render buffer size is fixed for a given type of device. Listing B-1 Initializing a render buffer’s storage and retrieving its actual dimensions GLuint colorRenderbuffer; Supporting High-Resolution Screens In Views Drawing High-Resolution Content Using OpenGL ES or GLKit 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 85glGenRenderbuffersOES(1, &colorRenderbuffer); glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer); [myContext renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:myEAGLLayer]; // Get the renderbuffer size. GLint width; GLint height; glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &width); glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &height); Important: A view that is backed by a CAEAGLLayer object should not implement a custom drawRect: method. Implementing a drawRect: method causes the system to change the default scale factor of the view so that it matches the scale factor of the screen. If your drawing code is not expecting this behavior, your app content will not be rendered correctly. If you do opt in to high-resolution drawing, you also need to adjust the model and texture assets of your app accordingly. For example, when running on iPad or on a high-resolution device, you might want to choose larger models and more detailed textures to take advantage of the increased number of pixels. Conversely, on a standard-resolution iPhone, you can continue to use smaller models and textures. An important factor when determining whether to support high-resolution content is performance. The quadrupling of pixels that occurs when you change the scale factor of your layer from 1.0 to 2.0 puts additional pressure on the fragment processor. If your app performs many per-fragment calculations, the increase in pixels may reduce your app’s frame rate. If you find your app runs significantly slower at the higher scale factor, consider one of the following options: ● Optimize your fragment shader’s performance using the performance-tuning guidelines found in OpenGL ES Programming Guide for iOS . ● Choose a simpler algorithm to implement in your fragment shader. By doing so, you are reducing the quality of each individual pixel to render the overall image at a higher resolution. ● Use a fractional scale factor between 1.0 and 2.0. A scale factor of 1.5 provides better quality than a scale factor of 1.0 but needs to fill fewer pixels than an image scaled to 2.0. ● OpenGL ES in iOS 4 and later offers multisampling as an option. Even though your app can use a smaller scale factor (even 1.0), implement multisampling anyway. An added advantage is that this technique also provides higher quality on devices that do not support high-resolution displays. Supporting High-Resolution Screens In Views Drawing High-Resolution Content Using OpenGL ES or GLKit 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 86The best solution depends on the needs of your OpenGL ES app; you should test more than one of these options and choose the approach that provides the best balance between performance and image quality. Supporting High-Resolution Screens In Views Drawing High-Resolution Content Using OpenGL ES or GLKit 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 87For both functional and aesthetic reasons, images are a pervasive element of app user interfaces. They can be a key differentiating factor for apps. Many images used by apps, including launch images and app icons, are stored asfilesin the app’s main bundle. You can have launch images and icons that are specific to device type (iPad versus iPhone and iPod touch) and that are optimized for high-resolution displays. You can find full descriptions of these bundled image files in “Advanced App Tricks” and “App-Related Resources” in iOS App Programming Guide . “Updating Your Image Resource Files” (page 83) discusses adjustments that make your image files compatible with high-resolution screens. In addition, iOS provides support for loading and displaying images using both the UIKit and Core Graphics frameworks. How you determine which classes and functionsto use to draw images depends on how you intend to use them. Whenever possible, though, it is recommended that you use the classes of UIKit for representing images in your code. Table C-1 lists some of the usage scenarios and the recommended options for handling them. Table C-1 Usage scenarios for images Scenario Recommended usage Use the UIImageView class to display the image. This option assumes that your view’s only content is an image. You can still layer other views on top of the image view to draw additional controls or content. Display an image as the content of a view Display an image as an Load and draw the image using the UIImage class. adornment for part of a view You can do this using the UIKit functions or Core Graphicsfunctions described in “Creating New Images Using Bitmap Graphics Contexts” (page 41). Save some bitmap data into an image object Create a UIImage object from the original image data. Call the UIImageJPEGRepresentationorUIImagePNGRepresentation function to get an NSData object, and use that object’s methods to save the data to a file. Save an image as a JPEG or PNG file 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 88 Loading ImagesSystem Support for Images The UIKit framework as well as the lower-level system frameworks of iOS give you a wide range of possibilities for creating, accessing, drawing, writing, and manipulating images. UIKit Image Classes and Functions The UIKit framework has three classes and one protocol that are related to images in some way: UIImage Objects of this class represent images in the UIKit framework. You can create them from several different sources, including files and Quartz image objects. Methods of the class enable you to draw images to the current graphics context using different blend modes and opacity values. The UIImage class automatically handles any required transformations for you, such as applying the proper scale factor (taking into consideration high-resolution displays) and, when given Quartz images, modifying the coordinate system of the image so that it matches the default coordinate system of UIKit (where the y origin is at the upper left). UIImageView Objects of this class are views that display either a single image or animate a series of images. If an image is to be the sole content of a view, use the UIImageView class instead of drawing the image. UIImagePickerController and UIImagePickerControllerDelegate This class and protocol give your app a way to obtain images (photos) and movies supplied by the user. The class presents and manages user interfaces for choosing and taking photos and movies. When users pick a photo, it deliversthe selected UIImage object to the delegate, which must implement the protocol methods. In addition to these classes, UIKit declares functions that you can call to perform a variety of tasks with images: ● Drawing into an image-backed graphics context. The UIGraphicsBeginImageContext function creates an offscreen bitmap graphics context. You can draw in this graphics context and then extract a UIImage object from it. (See “Drawing Images” (page 40) for additional information.) ● Getting or caching image data. Each UIImage object has a backing Core Graphics image object (CGImageRef) that you can access directly. You can then pass the Core Graphics object to the Image I/O framework to save the data. You can also convert the image data in a UIImage object to either a PNG or JPEG format by calling the UIImagePNGRepresentation or UIImageJPEGRepresentation functions. You can then access the bytes in the data object and you can write the image data to a file. ● Writing an image to the Photo Album on a device. Call the UIImageWriteToSavedPhotosAlbum function, passing in a UIImage object, to put that image in the Photo Album on a device. “Drawing Images” (page 40) identifies scenarios when you would use these UIKit classes and functions. Loading Images System Support for Images 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 89Other Image-Related Frameworks You can use several system frameworks other than UIKit to create, access, modify, and write images. If you find that you cannot accomplish a certain image-related task using a UIKit method or function, a function of one of these lower-level frameworks might be able do what you want. Some of these functions might require a Core Graphicsimage object (CGImageRef). You can accessthe CGImageRef object backing a UIImage object through the CGImage property. Note: If a UIKit method or function exists to accomplish a given image-related task, you should use it instead of any corresponding lower-level function. The Core Graphics framework of Quartz is the most important of the lower-level system frameworks. Several of its functions correspond to UIKit functions and methods; for example, some Core Graphics functions allow you to create and draw to bitmap graphics contexts, while others let you create images from various sources. However, Core Graphics offers more optionsfor handling images. With Core Graphics you can create and apply image masks, create images from portions of existing images, apply color spaces, and access a number of additional image attributes, including bytes per row, bits per pixel, and rendering intent. The Image I/O framework is closely related to Core Graphics. It allows an app to read and write most image file formats, including the standard web formats, high dynamic range images, and raw camera data. It features fast image encoding and decoding, image metadata, and image caching. Assets Library is a framework that allows an app to access assets managed by the Photos app. You can get an asset either by representation (for example, PNG or JPEG) or URL. From the representation or URL you can obtain a Core Graphics image object or the raw image data. The framework also lets you write images to the Saved Photos Album. Supported Image Formats Table C-2 lists the image formats supported directly by iOS. Of these formats, the PNG format is the one most recommended for use in your apps. Generally, the image formats that UIKit supports are the same formats supported by the Image I/O framework. Table C-2 Supported image formats Format Filename extensions Portable Network Graphic (PNG) .png Tagged Image File Format (TIFF) .tiff or .tif Joint Photographic Experts Group (JPEG) .jpeg or .jpg Loading Images System Support for Images 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 90Format Filename extensions Graphic Interchange Format (GIF) .gif Windows Bitmap Format (DIB) .bmp or .BMPf Windows Icon Format .ico Windows Cursor .cur XWindow bitmap .xbm Maintaining Image Quality Providing high-quality images for your user interface should be a priority in your design. Images provide a reasonably efficient way to display complicated graphics and should be used wherever they are appropriate. When creating images for your app, keep the following guidelines in mind: ● Use the PNG format for images. The PNG format provides lossless image content, meaning that saving image data to a PNG format and then reading it back results in the exact same pixel values. PNG also has an optimized storage format designed for faster reading of the image data. It isthe preferred image format for iOS. ● Create images so that they do not need resizing. If you plan to use an image at a particular size, be sure to create the corresponding image resource at that size. Do not create a larger image and scale it down to fit, because scaling requires additional CPU cycles and requires interpolation. If you need to present an image at variable sizes, include multiple versions of the image at different sizes and scale down from an image that is relatively close to the target size. ● Remove alpha channels from opaque PNG files. If every pixel of a PNG image is opaque, removing the alpha channel avoids the need to blend the layers containing that image. This simplifies compositing of the image considerably and improves drawing performance. Loading Images Maintaining Image Quality 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 91This table describes the changes to Drawing and Printing Guide for iOS . Date Notes Revised wording throughout, fixed a number of technical errors, and updated the printing chapter for iOS 6. 2012-09-19 2011-09-26 Made several minor changes. 2011-03-09 Made some minor changes. 2010-12-07 Added "Drawing to a Bitmap Graphics Context" to the Images chapter. First version of the document describing the concepts, APIs, and techniques for drawing and printing in iOS. 2010-11-15 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 92 Document Revision HistoryApple Inc. © 2012 Apple Inc. All rights reserved. No part of this publication may be reproduced, stored in a retrievalsystem, or transmitted, in any form or by any means, mechanical, electronic, photocopying, recording, or otherwise, without prior written permission of Apple Inc., with the following exceptions: Any person is hereby authorized to store documentation on a single computer for personal use only and to print copies of documentation for personal use provided that the documentation contains Apple’s copyright notice. No licenses, express or implied, are granted with respect to any of the technology described in this document. Apple retains all intellectual property rights associated with the technology described in this document. This document is intended to assist application developers to develop applications only for Apple-labeled computers. Apple Inc. 1 Infinite Loop Cupertino, CA 95014 408-996-1010 Apple, the Apple logo, Instruments, iPad, iPhone, iPod, iPod touch, Objective-C, OS X, Pages, Quartz, Spaces, and Xcode are trademarks of Apple Inc., registered in the U.S. and other countries. AirPrint is a trademark of Apple Inc. Helvetica is a registered trademark of Heidelberger Druckmaschinen AG, available from Linotype Library GmbH. OpenGL is a registered trademark of Silicon Graphics, Inc. iOS is a trademark or registered trademark of Cisco in the U.S. and other countries and is used under license. Even though Apple has reviewed this document, APPLE MAKES NO WARRANTY OR REPRESENTATION, EITHER EXPRESS OR IMPLIED, WITH RESPECT TO THIS DOCUMENT, ITS QUALITY, ACCURACY, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.ASARESULT, THISDOCUMENT IS PROVIDED “AS IS,” AND YOU, THE READER, ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND ACCURACY. IN NO EVENT WILL APPLE BE LIABLE FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL,OR CONSEQUENTIAL DAMAGES RESULTING FROM ANY DEFECT OR INACCURACY IN THIS DOCUMENT, even if advised of the possibility of such damages. THE WARRANTY AND REMEDIES SET FORTH ABOVE ARE EXCLUSIVE AND IN LIEU OF ALL OTHERS, ORAL OR WRITTEN, EXPRESS OR IMPLIED. No Apple dealer, agent, or employee is authorized to make any modification, extension, or addition to this warranty. Some states do not allow the exclusion or limitation of implied warranties or liability for incidental or consequential damages, so the above limitation or exclusion may not apply to you. This warranty gives you specific legal rights, and you may also have other rights which vary from state to state. QuickTime 7.3 User’s Guide Includes instructions for using QuickTime Pro For Mac OS X version 10.3.9 or later, and WindowsK Apple Inc. © 2007 Apple Inc. All rights reserved. Under the copyright laws, this manual may not be copied, in whole or in part, without the written consent of Apple. Your rights to the software are governed by the accompanying software license agreement. The Apple logo is a trademark of Apple Inc., registered in the U.S. and other countries. Use of the “keyboard” Apple logo (Option-Shift-K) for commercial purposes without the prior written consent of Apple may constitute trademark infringement and unfair competition in violation of federal and state laws. Every effort has been made to ensure that the information in this manual is accurate. Apple is not responsible for printing or clerical errors. Apple 1 Infinite Loop Cupertino, CA 95014-2084 408-996-1010 www.apple.com Apple, the Apple logo, AppleScript, Final Cut Pro, FireWire, iMovie, iPod, iTunes, Mac, Mac OS, Macintosh, QuickDraw, and QuickTime are trademarks of Apple Inc., registered in the U.S. and other countries. Finder, iPhone, and Tiger are trademarks of Apple Inc. Apple Store is a service mark of Apple Inc., registered in the U.S. and other countries. .Mac is a service mark of Apple Inc. Intel, Intel Core, and Xeon are trademarks of Intel Corp. in the U.S. and other countries. PowerPC™ is a trademark of International Business Machines Corporation, used under license therefrom. Other company and product names mentioned herein are trademarks of their respective companies. Mention of third-party products is for informational purposes only and constitutes neither an endorsement nor a recommendation. Apple assumes no responsibility with regard to the performance or use of these products. Manufactured under license from Dolby Laboratories. “Dolby,” “Pro Logic,” and the double-D symbol are trademarks of Dolby Laboratories. Confidential UnPublished Works, © 1992–1997 Dolby Laboratories, Inc. All rights reserved. Simultaneously published in the United States and Canada. 019-1032/2007-09-01 3 3 Contents Preface 6 Welcome to QuickTime 6 What Is QuickTime? 6 What Is QuickTime Pro? 7 What’s New in QuickTime 7? 7 New in QuickTime Player 8 New in QuickTime Pro 9 System Requirements 9 Types of Files QuickTime Supports 10 Checking for New Versions of QuickTime 10 Using Onscreen Help 10 Where to Go for Additional Information Chapter 1 11 Using QuickTime Player 11 Opening and Playing Files 11 Opening and Playing Movies in QuickTime Player 12 Opening and Playing Files in a Web Browser 15 Viewing QuickTime Virtual Reality (QTVR) Movies 16 Viewing Still Images 16 Playing MIDI Files 17 Opening Recently Used Files 17 Finding Movies Quickly Using QuickTime Favorites 17 Playing Copy-Protected Movies 18 Viewing Information About a File 18 Controlling Playback 18 Adjusting Audio and Video Settings 18 Changing Playback Preferences 19 Viewing Movies at Full Screen 20 Changing Movie Size for Playback 20 Looping a Movie 20 Simultaneously Playing Multiple Movies 21 Using Frame Number and Time Codes 21 Navigating a Movie by Frame Number or Time Code 22 Finding Text in a Text Track4 Contents 22 Preventing Users from Changing QuickTime Settings 22 Viewing Movies that have Flash Content Chapter 2 23 Getting Started with QuickTime Pro 23 Getting QuickTime Pro 23 Using Advanced Playback Options 23 Playing a Movie on a Second Display 24 Presenting a Movie as a Slideshow 24 Changing the Color Around a Movie 25 Loading Movies into RAM for Better Playback 25 Creating Movies and Other Media 25 Recording Video and Audio 26 About Saving Movies 27 Saving Movies from the Internet 27 Creating a Slideshow or Animation from Still Images 28 Creating a Still Image from a Movie 28 Converting Files into QuickTime Movies 29 Sharing Movies by Email or the Web 29 Sharing Movies for Podcast Producer Chapter 3 30 Editing and Authoring with QuickTime Pro 30 Simple Editing 30 Selecting and Playing Part of a Movie 31 Cutting, Copying, or Deleting a Section of a Movie 31 Combining Two QuickTime Movies into One 32 Working with Tracks 32 Turning Tracks On or Off 32 Extracting, Adding, and Moving Tracks 33 Working with Audio Tracks 34 Presenting Multiple Movies in the Same Window 35 Pasting Graphics and Text into a Movie 35 Working with Text Tracks 37 Specifying Languages for Individual Tracks 38 Changing Movie Properties 38 Adding Annotations to a Movie 38 Resizing, Flipping, or Rotating a Movie 39 Changing a Movie’s Shape with a Video Mask 39 Changing a Track’s Transparency 39 Creating a Chapter List for a Movie 41 Setting a Movie’s Poster Frame 41 Saving a Movie with Specific Playback Settings 41 Changing the Movie Controller TypeContents 5 Chapter 4 42 Exporting Files with QuickTime Pro 42 About Video and Audio Compression 43 Exporting Files Using Presets 43 Customizing Export Settings 43 Customizing Video Export Settings 45 Adding Special Effects and Filters to a QuickTime Movie 45 Changing Image (Frame) Size 46 Customizing Sound Export Settings 46 Preparing Movies for Internet Delivery 47 Preparing a Movie for Fast Start 47 Preparing a Movie for Real-Time Streaming 48 Creating Reference Movies to Optimize Web Playback 48 Creating Movies Optimized for iPhone and Web Delivery 49 Exporting MPEG-4 Files 49 MPEG-4 Video Export Options 50 MPEG-4 Audio Export Options 51 MPEG-4 Streaming Export Options 51 Exporting 3G Files 52 3G File Format Export Options 52 3G Video Export Options 53 3G Audio Export Options 54 3G Text Options 54 3G Streaming Options 54 3G Advanced Options Appendix 55 Shortcuts and Tips 55 QuickTime Player Keyboard Shortcuts 56 QuickTime Pro Keyboard Shortcuts 57 Automating QuickTime Player with AppleScript 58 Automating QuickTime Player on Windows Glossary 59 Index 62Preface 6 Welcome to QuickTime Want to play movies from your hard disk or the Internet? QuickTime Player makes it easy. What Is QuickTime? QuickTime Player is a free multimedia player. You can use it to view many kinds of files, including video, audio, still images, graphics, and virtual reality (VR) movies. QuickTime supports the most popular formats on the Internet for news, sports, education, movie trailers, and other entertainment. QuickTime is also a multimedia architecture that other applications can leverage. Some of the most popular software—such as iTunes, iMovie, and Final Cut Pro from Apple, as well as many third-party programs—uses the QuickTime architecture for important multimedia functions. These applications require QuickTime to be installed in order to function properly. What Is QuickTime Pro? You can easily add a host of useful features to your QuickTime software by purchasing QuickTime Pro. With QuickTime Pro, you can:  Save files from the Internet  Edit audio and video  Record audio (Mac OS X and Windows) and video (Mac OS X only)  Add special effects  Create slideshows  Convert and save video, audio, and images to more than a hundred standard formats For information about how to start using QuickTime Pro, see “Getting QuickTime Pro” on page 23.Preface Welcome to QuickTime 7 What’s New in QuickTime 7? Both the free QuickTime Player and QuickTime Pro provide a host of new features. New in QuickTime Player  H.264 video support. This state-of-the-art, standards-based codec delivers exceptional-quality video at the lowest data rate possible, across data rates ranging from 3G to HD and beyond.  Live resize. Playback continues smoothly as you change the size of the QuickTime Player window. (Some hardware requirements may apply.)  Zero-configuration streaming. You no longer need to set your Internet connection speed in QuickTime Preferences. QuickTime automatically determines the best connection speed for your computer. If a connection is lost during streaming, QuickTime automatically reconnects to the server.  Surround sound. QuickTime Player can now play up to 24 channels of audio. With QuickTime 7, your Mac, and surround speakers, you can enjoy the full effect of your surround sound movie or game.  New and improved playback controls. Use the new A/V Controls window to adjust settings for the best viewing experience. Easily change settings including jog shuttle, playback speed, bass, treble, and balance.  All-new content guide. The all-new QuickTime Content Guide provides the latest in entertainment on the Internet.  Full-screen playback. Get the most out of your display by using every pixel possible. Thee new modes allow you fit the content to any size screen.  Floating controls. Full-screen mode now provides floating DVD-like controls for easy access to functions like pause, play, fast-forward, rewind, and full-screen options. Move your mouse and the full-screen controller appears on the screen for several seconds.  Additional keyboard shortcuts. QuickTime Player now supports the same transport control keyboard shortcuts as Final Cut Pro. While viewing a movie, press J, K, or L to rewind, pause, or resume playback at variable speeds.  Closed Captioning. An option in QuickTime Player Preferences allows you to display standard CEA-608 closed captions, when they’re available in your movies.  Timecode Display. QuickTime Player now allows you to switch between displaying movie time, timecode, and frame count. You can also jump to a specific timecode or frame number using the keyboard.  Spotlight-friendly media. With Mac OS X v10.4 or later, you can use Spotlight to easily find your QuickTime content. Spotlight can search for movie attributes such as artist, copyright, codec, and so on.  Screen reader compatibility. Using VoiceOver, included with Mac OS X v10.4 or later, visually impaired users can enjoy QuickTime Player features.8 Preface Welcome to QuickTime  Easy access to QuickTime Pro. When you use the free QuickTime Player, features available only in QuickTime Pro display “Pro” by their name. If you choose one of these items, you’ll see a definition of the feature and learn how to purchase QuickTime Pro. (To purchase QuickTime Pro, you must be connected to the Internet using the computer on which you want to install the software.) New in QuickTime Pro QuickTime 7 Pro users enjoy not only all the great features in QuickTime Player, but also the following new QuickTime Pro capabilities:  Create H.264 video. Use this codec for all your video encoding needs. Create content ranging in size from HD (high definition) to 3G (for mobile devices), and everything in between.  Create surround audio. Create a rich multimedia experience for your customers by adding multi-channel audio to your movie. If some of your customers don’t have surround speakers, don’t worry; QuickTime automatically mixes the audio to work with the speaker setup of each user.  Improved movie authoring. Editing tasks are much easier with new hot keys for in and out points. In addition, the Movie Properties interface has been completely redesigned to facilitate simple and efficient movie authoring.  New AAC constant-quality mode. Create AAC audio files optimized for constant quality rather than a constant bit rate for a consistently high-quality listening experience.  3G streaming. Create 3G files for RTSP streaming that are fully interoperable with other 3G streaming handsets and delivery architectures.  Conform to Aperture. View a movie’s aperture mode, and choose to have the movie conform to new aperture settings, including pixel shape.  Deinterlace source video. When exporting with the “Movie to QuickTime Movie” option, you can now deinterlace the video by setting an option in Export Size settings.  Export to Apple TV, iPod, and iPhone. New presets allow you to easily export your movies in formats optimized for use with Apple TV, iPod, and iPhone.  Export for Web. Automatically creates versions of a movie that are optimized for both web and iPhone delivery, a reference movie that automatically selects the appropriate version for playback, and an HTML snippet file that you can use to embed the movie on a web page.  Concurrent exports. Export multiple files simultaneously—and continue with your next playback or editing task. New for Mac OS X In addition to the capabilities above, QuickTime Pro for Mac OS X provides these capabilities:  Video recording. With a digital video camera connected to your Mac, you can quickly create video postcards to share with family and friends.Preface Welcome to QuickTime 9  Movie sharing. Easily create a movie file for sending via email or posting to a website.  Automator integration. With Mac OS X v10.4 Tiger or later, employ the easy-to-use interface of Automator for streamlining your QuickTime workflow. QuickTime 7 Pro users have exclusive access to a set of QuickTime-based Automator actions for easily automating such tasks as starting and stopping captures, hinting movies, enabling tracks, and more. With Automator and QuickTime 7 Pro, you can also create your own personal set of QuickTime-based Automator actions.  Podcast sharing. With Mac OS X v10.5 Leopard, you can easily send a movie file to Podcast Producer, on a computer with Mac OS X Server v10.5 Leopard, for automatic creation and delivery of podcasts. System Requirements For Mac OS computers:  A 400 MHz or faster G3 PowerPC–based or Intel-based Macintosh computer  At least 128 MB of RAM  Mac OS X version 10.3.9 or later For Windows computers:  A Pentium processor–based PC or compatible computer  At least 128 MB of RAM  Windows XP Service Pack 2 or Windows Vista Types of Files QuickTime Supports You can open (import) dozens of types of media with QuickTime. Some of the formats you can open in QuickTime include the following:  Video formats: MOV, MPEG-1, MPEG-2, 1 MPEG-4, 3GPP, 3GPP2, JPEG, DV, Motion JPEG, AVI, MQV, H.264  Audio formats: AIFF/AIFC, Audio CD, CAF, MOV, MP3, MPEG-4, AU, WAV, iTunes audio  Still-image formats: BMP, GIF, JPEG/JFIF, JPEG 2000, PDF, MacPaint, PICT, PNG, Photoshop (including layers), SGI, Targa, FlashPix (including layers), TIFF (including layers)  Animation formats: Animated GIF, FLC, Flash, PICS  Other formats: KAR (Karaoke), MIDI, QuickDraw GX, QuickTime Image File, QuickTime VR, Text 1. MPEG-2 playback is available via the QuickTime MPEG-2 Playback Component, sold separately at the Apple Store online. Because some file formats can contain many different kinds of audio and video, QuickTime may not be able to play all audio and video formats within a particular file format.10 Preface Welcome to QuickTime For a complete list of supported formats, see the Products area of the QuickTime website. To determine if QuickTime Player can open a file, choose File > Open File and select the file you want to open. You will be able to select only files that can be imported. Checking for New Versions of QuickTime From time to time, Apple releases new versions of QuickTime. If you’re connected to the Internet while using QuickTime Player, you’ll be notified when there’s a newer version of QuickTime available. It’s a good idea to have the latest version of the software installed on your computer. To check for a new version of QuickTime (if you are using Mac OS X), choose QuickTime Player > Update Existing Software. In Windows, choose Edit > Preferences > QuickTime Preferences, and then choose Update Check. Using Onscreen Help While QuickTime is open, you can see instructions for performing tasks by choosing Help > QuickTime Player Help. Where to Go for Additional Information Consult the resources listed below for more information about QuickTime:  Latest QuickTime content listings. QuickTime Player includes an up-to-the-minute guide to the best in QuickTime content. You can view the latest news, entertainment, educational features, and more. You can also listen to audio programs. To view the content guide, open QuickTime Player and choose Window > Show Content Guide. You can also visit www.apple.com/quicktime.  QuickTime News. For the latest news about QuickTime content and products, sign up for the QuickTime newsletter at applenews.lists.apple.com/subscribe.  Tutorials and tips. For step-by-step tutorials and a collection of instructional books and CDs, visit www.apple.com/quicktime/resources.  Discussion lists. Sign up with one of the many QuickTime-specific discussion lists to post messages, exchange ideas and information, and keep current with the latest QuickTime developments at www.apple.com/quicktime/resources.  Developer support. If you’re interested in developing products using QuickTime, go to developer.apple.com/quicktime.  Technical support. To view all the support resources available, visit www.apple.com/support.1 11 1 Using QuickTime Player This chapter explains the basics of using QuickTime Player. Opening and Playing Files You can open and play QuickTime movies in QuickTime Player or in your web browser. Opening and Playing Movies in QuickTime Player You can use QuickTime Player to play media stored on your computer’s hard disk, a CD, a DVD, or the Internet. To open a movie on your hard disk, a CD, or a DVD, do one of the following:  In the Finder (or Windows Explorer), double-click the file or drag it to the QuickTime Player application icon.  Choose File > Open and select the file.  Drag the file to the QuickTime Player icon in the Dock (Mac OS X only). To open a movie on the Internet, open QuickTime Player, choose File > Open URL, and enter the URL (the Internet address) for the movie file. When audio is detected, you’ll see activity in the equalizer. Playhead Volume Play/Pause Go to Fast-forward; go to end beginning; rewind Drag to resize the window.12 Chapter 1 Using QuickTime Player QuickTime Player has onscreen controls similar to those found on CD players and DVD players. Use the controls to play, pause, rewind, fast-forward, jump to the beginning or end, and adjust the volume of a QuickTime movie. You can also use the controls to move forward or backward in a movie. To go to a specific point in the movie, drag the playhead (the small black triangle) in the timeline. To step through frame-by-frame, first click the small black triangle and then press the Right or Left Arrow keys on your keyboard. Some movies have chapter lists you can use to jump to a specific point in a movie. If a movie has a chapter list, a pop-up menu appears between the timeline and the equalizer. You can drag the handle in the lower-right corner of the window to resize the viewing space. Opening and Playing Files in a Web Browser With the QuickTime plug-in (part of the free QuickTime software), you can play most multimedia you encounter on the Internet within your web browser. On some websites, movies play automatically. On other sites, you need to click an image of the movie or a play button. When a movie plays on a webpage, you typically see controls you can use to play, pause, fast-forward, rewind, and adjust the volume of the movie. To play a movie in a web browser, go to the website and follow the site’s instructions to watch the movie. Choose a chapter from the pop-up menu to jump to that chapter. Volume Play/Pause Rewind; fast-forward QuickTime Pro menu The playheadChapter 1 Using QuickTime Player 13 With QuickTime Pro, you also have the option of saving the movie to your hard disk (if the author of the movie allows it). To save a movie from the web, click the downwardpointing arrow on the right and choose “Save as QuickTime Movie” or “Save as Source” from the QuickTime Pro menu. If the movie is a Real-Time Streaming Protocol (RTSP) movie, it is saved as a small “reference movie” that points to the actual movie on the Internet. The QuickTime website has a number of QuickTime movies (including the latest movie trailers) that you can view in your web browser. Go to www.apple.com/quicktime. Adjusting Playback Preferences for Internet Movies When you watch movies on the Internet, they start playing automatically. You can, however, download entire movies to your hard disk before they start playing so that you can watch the movies at your convenience. To download movies before they start playing (in Mac OS X): 1 Choose QuickTime Player > QuickTime Preferences and click Browser. 2 Deselect “Play movies automatically.” To download movies before they start playing (in Windows): 1 Choose Edit > Preferences > QuickTime Preferences. 2 Choose Browser. 3 Deselect “Play movies automatically.” So that you don’t have to download movies and images each time you view them on a website, QuickTime can save these files in a storage area called a cache. If you view a movie or image more than once, having the item cached improves performance. To have QuickTime cache movies and images you view on the Internet, select “Save movies in disk cache.” You might not want to select this option if you don't have sufficient free space on your hard disk to allocate a cache, or if, for security reasons, you don't want movie data stored in a cache file. You can specify how big to make the cache by changing the Movie Cache Size setting. How big you make the cache depends on how much free space your hard disk has. A larger cache can hold more files (or larger files), but it takes up more space on your hard disk. After the QuickTime cache fills all the space reserved for it, older items are automatically deleted from the cache when new items are added. To clear the cache, click Empty Download Cache (in Windows, choose Download Cache in QuickTime Settings and then click Empty Cache Now). You might want to clear the cache for security or privacy reasons, or to recover free space on your hard disk.14 Chapter 1 Using QuickTime Player QuickTime automatically detects your Internet connection speed so that you get the highest-quality QuickTime content that your Internet connection can support. If movies you’re watching on the Internet don’t play properly, however, it may help to change the connection speed setting. To change the connection speed setting in Mac OS X, open QuickTime Preferences and click Streaming. In Windows, open QuickTime Preferences and choose Connection Speed. QuickTime tries to play versions of the movie authored to match the connection speed you choose. If you choose a speed slower than your actual connection speed, the resulting movie may be smaller in size and lower in quality than your connection can actually support. If you choose a speed faster than your actual connection, QuickTime playback may stutter or appear jerky because it is sending more data than your connection can support. If you’re unsure of your connection speed, check with your Internet service provider (ISP). If you change your connection speed setting and later want to make QuickTime automatically detect your speed again, choose Automatic from the Streaming Speed pop-up menu (in Mac OS X). To set the Internet connection speed in Windows, choose Edit > Preferences > QuickTime Preferences, and then follow the directions above. Instant-On QuickTime includes Instant-On, a technology that dramatically reduces buffer (wait) time when you view streamed video. Instant-On provides an instantaneous viewing experience; you can navigate quickly through video as if it were on your hard disk. To experience Instant-On, you must have a broadband connection. The responsiveness of Instant-On is affected by available bandwidth and the size, or data rate, of the content. It can also be affected by the codec used to compress the streaming video. Instant-On is on by default. If you experience problems with streamed video, you can change the wait time (drag the Play slider) or turn off Instant-On (open QuickTime Preferences and click Streaming). Viewing Streamed Files Behind a Firewall QuickTime streaming chooses the best protocol (a method of communicating via the Internet) for your needs. Typically, QuickTime streaming uses Real-Time Streaming Protocol (RTSP) to ensure the best performance. If your network connection is protected by a firewall, you may want to use the HTTP protocol instead.Chapter 1 Using QuickTime Player 15 To use HTTP streaming (in Mac OS X): 1 In QuickTime Player, choose QuickTime Player > QuickTime Preferences (or open System Preferences and click QuickTime). 2 Click Advanced. 3 Choose Custom from the Transport Setup pop-up menu. 4 Choose HTTP from the Transport Protocol pop-up menu. To use HTTP streaming (in Windows): 1 In QuickTime Player, choose Edit > Preferences > QuickTime Preferences. 2 Choose Advanced. 3 Choose Custom from the Transport Setup pop-up menu. 4 Choose HTTP from the Transport Protocol pop-up menu. If QuickTime can configure itself for your firewall, you can now watch streaming QuickTime movies. If you still experience problems, contact your network administrator or see the information on the Apple QuickTime website (www.apple.com/quicktime). Setting QuickTime to Handle More or Fewer File Types (MIME Settings) When files are downloaded over the Internet, each file is assigned a MIME type to indicate what kind of file it is. Your browser keeps track of which plug-in should be used to display each kind of file. QuickTime can display a wide variety of file types. To make QuickTime handle more or fewer file types, you can edit the MIME type settings. If you edit the list, you can return to the default list by following the instructions below and clicking Use Defaults. To edit MIME settings in Mac OS X, open QuickTime Preferences and click Advanced. In Windows, choose Edit > Preferences > QuickTime Preferences, choose Browser, and click MIME Settings. Viewing QuickTime Virtual Reality (QTVR) Movies QTVR movies display three-dimensional places (panoramas) and objects with which the user can interact. With a QTVR panorama, it’s as if you’re standing in the scene and you can look around you up to 360 degrees in any direction. In a QTVR movie of an object, you can rotate the object in any direction. To pan through a QTVR movie, drag the cursor through the scene. To zoom in or out, click the + or – button. (If the buttons are not showing, zoom in by pressing Shift; zoom out by pressing Control.)16 Chapter 1 Using QuickTime Player Some QTVR movies have hot spots that take you from one scene (or node) to another. As you move the mouse over a hot spot, the cursor changes to an arrow. To see all the places where you can jump from one node in a scene to another, click the Show Hot Spot button (an arrow with a question mark in it). A translucent blue outline of any hot spots within the currently visible VR scene appears. (If there are no hot spots, clicking this button has no effect.) Click a hot spot to jump to a new scene. To step backward scene by scene, click the Back button. (The Back button appears only on QTVR movie windows, not in all QuickTime movie windows.) Viewing Still Images You can view still images in QuickTime Player. Choose File > Open File and select the file, or drag the file to the QuickTime Player icon in the Dock (Mac OS X only). Mac OS X: You can use Preview to convert a still image to other formats (Preview is in the Applications folder on your hard disk). You can also convert many kinds of files using QuickTime Pro. For more information, see “Converting Files into QuickTime Movies” on page 28. Windows: If you have QuickTime Pro, you can use PictureViewer to import and export various types of still image file formats and to rotate images. PictureViewer is in the QuickTime folder on your hard disk. Playing MIDI Files QuickTime Player can import MIDI (Karaoke MIDI, Standard MIDI, and General MIDI) formats. To open a MIDI file, choose File > Open File and select the file. QuickTime uses its built-in synthesizer to play MIDI files. You can also set QuickTime to use an external synthesizer instead of the built-in one. To specify a different synthesizer (in Mac OS X): 1 Open System Preferences, click QuickTime, and then click Advanced. 2 Choose the synthesizer you want from the Default Synthesizer pop-up menu. To specify a different synthesizer (in Windows): 1 Choose Edit > Preferences > QuickTime Preferences. 2 Click Audio. 3 Select the synthesizer you want from the Default Music Synthesizer pop-up menu.Chapter 1 Using QuickTime Player 17 Opening Recently Used Files You can easily open recently used files. To open recently used files: m Choose File > Open Recent > [option] To change the number of items that appear in the Open Recent submenu (in Mac OS X), choose QuickTime Player > Preferences, click General, and choose an option from the Number of Recent Items pop-up menu. In Windows, choose Edit > Preferences > Player Preferences. Finding Movies Quickly Using QuickTime Favorites You can easily find and open movies by putting pointers to them in your QuickTime Favorites window. To view your list of favorites, choose Window > Favorites > Show Favorites. To add a movie to the Favorites list: 1 Open the movie in QuickTime Player. 2 Choose Window > Favorites > Add Movie As Favorite. You can also drag a file to the Favorites list window. To rearrange movies in the list, drag them. To delete an item from the list, drag the item to the Trash or select the item and press the Delete key. (In Windows, drag the item to the Recycle Bin or select the item and press the Backspace key.) Deleting an item from the Favorites list does not delete the file from your hard disk (or wherever the file is saved). Playing Copy-Protected Movies QuickTime movies can be encrypted so that only authorized viewers can watch them. Such movies are known as “secured media files.” To use such a file, you must enter a “media key,” which is usually available from the media file provider. To enter a media key (in Mac OS X): 1 Open System Preferences, click QuickTime, and click Advanced. 2 Click Media Keys. 3 Click the Add button and then enter the key provided by the author or vendor. To enter a media key (in Windows): 1 Choose Edit > Preferences > QuickTime Preferences. 2 Click Advanced. 3 Click Media Keys. 4 Click Add and then enter the key provided by the author or vendor.18 Chapter 1 Using QuickTime Player Viewing Information About a File QuickTime Player can display information about a QuickTime file, such as its compression format, size, and frame rate while playing. To view information about a file: 1 Open the file. 2 Choose Window > Show Movie Info. With QuickTime Pro, you can see additional information about a movie by choosing Window > Show Movie Properties. For more information about movie properties, see “Changing Movie Properties” on page 38. Controlling Playback You can change playback options such as balance, playback speed, the size at which a movie plays, and whether the QuickTime Player window shows. You can also optimize movies for playback on certain computers. Adjusting Audio and Video Settings For any QuickTime movie with an audio track, you can adjust the right/left balance, as well as the volume, bass, and treble levels. For any movie, you can also set playback options such as speed and playback rate (the jog shuttle). To set audio and video controls: 1 Choose Window > Show A/V Controls. 2 Drag a slider to adjust the setting. Other playback options (for playing several movies at once or for playing a movie while using another application, for example) are available in QuickTime Player Preferences. To open QuickTime Player Preferences (in Mac OS X), choose QuickTime Player > Preferences. In Windows, choose Edit > Preferences > Player Preferences. For more information, see “Changing Playback Preferences.” Changing Playback Preferences You can change playback preferences by choosing QuickTime Player > Preferences. The available options include:  Open movies in new players: Select to open movies in a new player window; deselect to replace the movie in the current player window with the new movie.  Automatically play movies when opened: Select to make all movies start playing when they’re opened; deselect to have the movie start when you click the Play button.  Use high-quality video settings when available: When this option is selected, video looks sharper and smoother, but more processor capacity is used.Chapter 1 Using QuickTime Player 19  Play sound in frontmost player only: Select to play the audio for only one QuickTime Player window (the active window); deselect to play the sound of all playing movies simultaneously.  Play sound when application is in background: Select to play audio even if QuickTime is not the frontmost application; deselect to mute the audio when QuickTime is not the active application.  Show equalizer: Select or deselect to show or hide the equalizer (which shows the presence of audio) in the QuickTime Player window.  Show Content Guide automatically: Select to see the latest content listings when QuickTime Player first opens (unless you open a specific movie file).  Pause movie before switching users: Select to automatically pause a movie when you use fast user switching to let another person use your computer.  Hide selection indicators for empty selection: Select to have the selection indicators in the timeline removed when no frames are selected.  Show closed captioning when available: Select to see the closed caption information, if captions have been provided by the movie’s creators. With QuickTime Pro, more options are available. For information about them, see “Getting QuickTime Pro” on page 23. Viewing Movies at Full Screen You can set the screen so that only the movie is visible, not the QuickTime Player window, desktop, or other windows. This presentation setting is called “full-screen mode.” (You can also set a movie to play at half size, double size, or other sizes.) To play a movie at full screen, do one of the following:  Choose View > Full Screen.  Choose View > Present Movie, choose Full Screen, and click Play. To quit full-screen mode, press Esc. To adjust the way the picture is sized to fit your screen, such as stretched to fit or in letterbox format, move the pointer to the top of the screen to display the QuickTime Player menu options, and then choose a setting from the View menu. The following additional options are available in full-screen mode:  Fit to Screen: The content is scaled to fill your screen as fully as possible without cropping the movie or changing the aspect ratio.  Zoom: The content is scaled and cropped to completely fill your screen in at least one dimension. This can eliminate black areas on the top (letterboxing) or side (pillarboxing) but may hide or distort the content.  Panoramic: The content is scaled to fit your screen and the outer horizontal edges compressed to avoid cropping the image. You can also cycle through all of the available full-screen options by clicking the button in the movie controls that appear when you move the pointer. 20 Chapter 1 Using QuickTime Player You can also set options for all movies playing at full screen. For example, you can hide the movie controls or change the amount of time they’re displayed before being hidden. To set these options in Mac OS X, choose QuickTime Player > Preferences and click Full Screen. To set these options in Windows, choose Edit > Preferences > Player Preferences, and then click Full Screen. Note: As long as “Display full-screen controls” is selected in QuickTime Player Preferences, you can make hidden controls appear by moving the pointer. Changing Movie Size for Playback QuickTime Player includes several options for changing movie playback size. To change a movie’s playback size, choose View > [a size], or drag the resize control in the lower-right corner of the window. To stretch the movie in any direction, hold down the Shift key when you drag (holding down the Shift key while dragging doesn’t preserve the aspect ratio). To return the movie to its default size and aspect ratio, press Command-1 (in Windows, press Alt-1). You can also view movies at full screen, with additional sizing options available during full-screen playback. For more information, see “Viewing Movies at Full Screen” on page 19. Looping a Movie You can play a movie repeatedly. When the movie finishes, it automatically starts playing again. To loop a movie: m Choose View > Loop. With QuickTime Pro, you can also play the movie forward and then backward repeatedly by choosing View > Loop Back and Forth. Simultaneously Playing Multiple Movies You can have more than one QuickTime Player window open at a time. To open more than one QuickTime Player window, do one of the following:  Double-click another movie file.  Choose View > Play All Movies. By default, when you have more than one QuickTime Player window open, the audio plays only on the active (frontmost) QuickTime Player window. For information about changing this setting, see “Changing Playback Preferences” on page 18.Chapter 1 Using QuickTime Player 21 Using Frame Number and Time Codes When you’re viewing a movie in QuickTime Player, you can display the current movie time or frame number, or the SMPTE time code if the movie has a time code track. (Some applications, such as Final Cut Pro, automatically add a time code during capture.) Displaying Frame Numbers, Movie Time, or Time Code The area next to the timeline in QuickTime Player displays the time information for the current movie. 1 Click the time display area. 2 Choose an option from the pop-up menu that appears:  Standard: Displays movie time in HH:MM:SS format.  Time Code: Displays the movie’s time code in HH:MM:SS:Frame format. Either the time code or drop-frame time code will be displayed, depending on the frames per second of the movie. A colon in the frame segment of the time notation indicates that a non-drop time code is being displayed. A semicolon indicates a drop-frame time code. If the movie has a time code track, it will be used. Otherwise, the time code will be calculated from 00:00:00:00 at the start of the movie.  Frame Number: Displays the frame number, incrementing from 0 at the start of the movie. An “f“ in the time display area indicates that the frame count is being displayed. Navigating a Movie by Frame Number or Time Code You can jump to a point in a movie by entering a specific frame number or time code.  Double-click the time display, and then press the arrow keys or type a new time or frame number.  To select the entire time display, double-click the area, or click the area and then press Command-A (in Mac OS X) or Control-A (in Windows). To enter a time, separate each unit with a period. For example, 5.02.10 will go to five minutes, two seconds, and 10 frames. To go to five minutes, zero seconds, and 10 frames you can enter 5..10.22 Chapter 1 Using QuickTime Player Finding Text in a Text Track Some movies contain text such as titles, credits, subtitles, or section headings. You can search for text in a movie so that, for example, you can find specific frames in the movie. To search for text in a QuickTime movie: 1 Choose Edit > Find > Find. If this command is unavailable, the movie does not have a text track. 2 In the Find dialog, type the text you are looking for and click Next. Preventing Users from Changing QuickTime Settings If you’re using a computer in a public setting (at a kiosk, for example), you can prevent users from changing QuickTime settings and saving movies from the Internet. To set up QuickTime for use on a public computer (in Mac OS X): 1 Open System Preferences, click QuickTime, and click Advanced. 2 Select “Enable kiosk mode.” To set up QuickTime for use on a public computer (in Windows): 1 Choose Edit > Preferences > QuickTime Preferences. 2 Choose Browser Plug-in. 3 Select “Enable kiosk mode.” Viewing Movies that have Flash Content Some QuickTime movies contain a Flash track . To enable these movies to play properly, you must turn on support for Flash within QuickTime. To enable Flash playback in QuickTime movies (in Mac OS X): 1 Open System Preferences, click QuickTime, and click Advanced. 2 Select “Enable Flash.” To enable Flash playback in QuickTime movies (in Windows): 1 Choose Edit > Preferences > QuickTime Preferences. 2 Choose Advanced. 3 Select “Enable Flash.”2 23 2 Getting Started with QuickTime Pro Learn how to use the advanced playback options in QuickTime Pro, create movie postcards, and share them via email or the web. Getting QuickTime Pro To get QuickTime Pro, choose a QuickTime Pro menu item and click Buy Now, or choose QuickTime Player > Buy QuickTime Pro. You must be connected to the Internet using the computer on which you want QuickTime Pro installed. You may need to restart QuickTime Player to make the new options available. Using Advanced Playback Options With QuickTime Pro, you have additional options for playing movies, such as playing a movie on a second display, and more. Playing a Movie on a Second Display With QuickTime Pro and a two-display setup with dual display support, you can play a movie on one display while working in another application on the other display. This arrangement is useful for presentations. Mac OS X: Make sure Mirror Displays is not selected. (Open System Preferences, click Displays, and click Arrangement. If you don’t see an Arrangement button, your computer does not support this feature.) Windows: Whether you can play a movie on a second display depends on your computer and monitor. Open the Display control panel, click Settings, and make sure that the second display is enabled. If it is not enabled, click it and make sure “Extend my Windows desktop onto this monitor” is selected.24 Chapter 2 Getting Started with QuickTime Pro To play a movie on a second display: 1 Open a movie in QuickTime Player. 2 Choose View > Present Movie. The two displays are shown side by side; one contains the menu bar. The letter “Q” appears on the display on which the movie will play. To play the movie on the other display, click it. 3 Choose an option from the pop-up menu. To play the movie without displaying the QuickTime Player controls, choose Full Screen. 4 Select Movie or Slideshow mode. In slideshow mode, you can advance frames by clicking the mouse or pressing the Right Arrow or Left Arrow key. 5 Click Play. You can open other applications while the movie is playing. To make another application active, press Command-Tab (in Windows, Alt-Tab). You can now use the mouse and keyboard in other applications while the movie continues to play. To stop the movie before it ends, press Command-Tab (in Windows, Alt-Tab) to make QuickTime Player active, and then click the mouse. All QuickTime movie playback keyboard shortcuts are available in full-screen mode. Presenting a Movie as a Slideshow In a slideshow, the viewer clicks to advance to the next frame. With QuickTime Pro, you can set a movie to play as a slideshow. To play a movie as a slideshow: 1 Choose View > Present Movie. 2 Click Slideshow, then click Play. 3 To advance the slideshow, click the mouse or press the Left or Right Arrow keys. Changing the Color Around a Movie By default, the onscreen area around the edge of a movie playing in full-screen mode is black, but you can change it to another color. To change a movie’s border color: 1 Choose View > Present Movie. 2 Click the color well to the right of the pop-up menu, then choose a color from the Colors window. If you have more than one display, you can have this color appear on all displays (not just the one playing the movie), by selecting “Display background color on all screens.”Chapter 2 Getting Started with QuickTime Pro 25 Loading Movies into RAM for Better Playback QuickTime has two memory (RAM) options you can use to improve playback performance. Preload puts the entire movie into memory before it is played; Cache keeps movie data in memory after it has played. This option is useful for small files you want to loop. With QuickTime Pro, you can adjust memory options for a QuickTime movie track. To adjust memory options for a track: 1 Choose Window > Show Movie Properties. 2 Select the track you want to adjust and click Other Settings. 3 To put the track into memory, select “Preload this track.” 4 To keep track data in memory, select Cache. Use these options only with tracks that contain very small amounts of data; too much data in memory may cause poor performance, system errors, or unpredictable results. Creating Movies and Other Media With QuickTime Pro, you can create movies in various ways. Recording Video and Audio With a video camera and a Macintosh computer you can use QuickTime Pro to record a movie. QuickTime Pro can capture video from most FireWire-equipped sources, including the Apple iSight, DV cameras, and some webcams. With a Macintosh or Windows computer, you can also record audio using a built-in or external microphone. To record audio or video with QuickTime Pro: 1 Connect the camera or microphone to the computer (unless you are using a built-in microphone). 2 In QuickTime Pro, choose File > New Movie Recording (or File > New Audio Recording). A preview window appears, which you can use to adjust settings such as camera position, lighting, and audio level before you start recording. 3 To start recording, click the Record button at the bottom of the window. 4 To stop recording, click the button again. The movie you just recorded appears in a QuickTime movie window. By default, the movie is saved on the desktop, but you can choose a different default location in the Recording pane of QuickTime Player Preferences. To see where the movie has been saved, Command-click the icon at the top of the window.26 Chapter 2 Getting Started with QuickTime Pro Setting Recording Options When you first use QuickTime Pro to record video or audio, settings are automatically chosen for you. If you want, you can change settings such as which recording device and format to use, and where recorded movies are stored. To change recording options: 1 Choose QuickTime Player > Preferences. 2 Click Recording (or Audio Recording in Windows). 3 Choose the desired options for your video source, microphone, and quality, and then choose a default location to store recorded files. About Saving Movies With QuickTime Pro, you can create and edit movies, and then save them. When you choose File > Save As, you can save the movie as one of the following:  A self-contained movie includes all the data (video, audio, and so on) you used to create the movie within a single file.  A reference movie contains pointers to other movies (or parts of movies) stored elsewhere, such as in different folders on your hard disk or even on a web server. Pointers to other movies are created when, for example, you copy and paste part of a movie from one movie into another. If you are concerned about free space on your hard disk and can be sure your source movies won’t change location, you can save your movie as a reference movie; the media you copy and paste is stored as a space-saving pointer to that media, rather than being stored entirely inside your new movie file. When you play a reference movie, QuickTime follows the pointers to access and play the other movies (or parts of movies). To determine whether a movie contains pointers to other data, choose Window > Show Movie Properties, select the movie at the top of the window, and click Resources. If the file containing the movie does not appear in the list, then the movie has pointers and is not self-contained. In Mac OS X, you can Command-click the icon to see the name and location of the file that contains the movie. The term “reference movie” is also used for the files you can create to intelligently deliver different-sized streams to different users depending on their connection speeds. For more information, see “Creating Reference Movies to Optimize Web Playback” on page 48.Chapter 2 Getting Started with QuickTime Pro 27 Saving Movies from the Internet With QuickTime Pro, you can save (download) a movie viewed in your web browser to your hard disk. (The movie must be authored to allow for saving.) If it’s a streaming movie, QuickTime Pro saves a small “reference movie” that points to the stream. To save an Internet movie on your hard disk: 1 When the movie finishes loading (when the entire progress bar is filled with gray), click the down arrow in the playback controls. 2 Choose “Save as QuickTime Movie.” If this command is not available, the movie is authored so that it cannot be saved. Creating a Slideshow or Animation from Still Images With QuickTime Pro, you can combine a series of still images to create a movie that plays like a slideshow. This process is an easy way to share the pictures from your digital camera or mobile phone. Note: Slideshows look best when all the images are the same size. To create a slideshow from still images: 1 Put all the graphic files you want to include in a folder. 2 Name each file with the same name followed by an increasing number; for example, “picture1,” “picture2.” Most digital cameras number files automatically. The numbers must be increasing but don’t have to be precisely sequential (for example, you could name the files “picture1,” “picture5,” “picture10,” and so on). 3 In QuickTime Player, choose File > Open Image Sequence, and then select the first file. 4 Choose a frame rate (the number of frames displayed per second) from the Frame Rate pop-up menu. Slideshows usually work best when slides are shown at 2 to 3 seconds per frame. QuickTime Pro creates the movie, which shows each picture in sequence. 5 Choose File > Save to name and save the movie.28 Chapter 2 Getting Started with QuickTime Pro You can add music to your slideshow by adding an audio track to your movie before saving it. Open an audio file, select the portion you want to add to the slideshow, and choose Edit > Copy. Select the slideshow (or a portion of it) and choose Edit > Select All, then choose Edit > “Add to Selection and Scale.” The audio is sped up or slowed down to fit the length of the paste destination (the pitch remains the same). For best results, make the slideshow length match that of the audio as closely as possible. You can also lengthen a soundtrack by adding multiple audio files to the movie, each beginning at a different point. Alternatively, you can keep the original audio speed and alter the image speed by opening a new player window, copying and pasting the audio into the new window, and then copying the slideshow and pasting it into the new window by choosing Edit > “Add to Selection and Scale.” If you’re using Mac OS X: You can also use the recording feature in QuickTime Pro to narrate your slideshow. See “Recording Video and Audio” on page 25. Creating a Still Image from a Movie With QuickTime Pro, you can export a single frame from a movie as an image file. To save a still image from a movie: 1 Move the playhead to the frame you want to export. 2 Choose File > Export. 3 Choose “Movie to Picture” from the Export pop-up menu. 4 Click Options and choose a format from the “Compression type” pop-up menu. To export every frame from the movie as a series of images, choose “Movie to Image Sequence.” Exporting every frame can generate a very large number of files; you may want to export to a folder rather than to the desktop. Converting Files into QuickTime Movies If you have QuickTime Pro, you can use QuickTime Player to convert many types of video, audio, graphics, and animation files (including Flash files) into QuickTime movies. To convert a file into a QuickTime movie, open it in QuickTime Player and then choose File > Save.Chapter 2 Getting Started with QuickTime Pro 29 Sharing Movies by Email or the Web With QuickTime Pro and Mac OS X it’s easy to create movies that are just right for sharing with others by email or on your .Mac HomePage. Simply select how you want to share your movie, and QuickTime Pro automatically creates a file suitable for that delivery method. (To use the Share feature to put your movie on the web, you need a .Mac account.) To share a movie: 1 Choose File > Share. 2 Click Email or HomePage. 3 Choose a name and size for the movie. 4 If you are going to publish your movie on the web, you can type a name for the movie (the name you type will appear on the webpage). 5 Click Share. While the movie is being exported, you can click the “x” to cancel the export if necessary. If you click Email, a new message window opens in Mail, with your movie attached. If you click HomePage, your browser opens to the specified webpage, with the movie embedded. Send the URL to friends so that they can view the movie. Sharing Movies for Podcast Producer With QuickTime Pro and Mac OS X, you can create a movie for use with Podcast Producer, an application included with Mac OS X Server v10.5 Leopard. Note: This option is available only if you have the Podcast Capture application installed on your computer. To share a movie to Podcast Producer: 1 Choose File > Share. 2 Click Podcast Producer. 3 Enter your user name, password, and server name, then click Login. 4 Choose a Podcast Producer workflow from the pop-up menu. See the Podcast Producer Administration Guide, or your network administrator, for information about these settings. 5 Click Share.3 30 3 Editing and Authoring with QuickTime Pro Learn how to use QuickTime Pro to edit movies, manipulate movie tracks, and much more. Simple Editing With QuickTime Pro, you can perform movie-editing tasks. Selecting and Playing Part of a Movie To perform editing functions such as Copy and Delete, in most cases you need to first select the desired portion of a movie. (If you don’t select anything, the edit commands work on the current frame.) To select a portion of a movie, move the In and Out selection markers. The darkened area between the two markers indicates the selected portion. To fine-tune the selection, select a marker and move it with the arrow keys. You can also move the playhead and press I (for In) or O (for Out) to set the start or end point of the selection, even while the movie is playing. To play the selection, choose View > Play Selection Only (so that the checkmark appears), then click Play. To play the whole movie, choose View > Play Selection again (to remove the checkmark). With QuickTime Pro, you can save the movie (choose File > Save) so that the next time it is opened, only the part you selected plays. Tip: To move the In or Out marker to a different position, drag the playhead to the desired position (or use the arrow keys), then press I or O. In and Out markers, showing the selected portion of the movie The playheadChapter 3 Editing and Authoring with QuickTime Pro 31 Note: By default, the selection markers hide when nothing is selected, making it easy to determine whether or not a frame is selected. To turn off this option so that the selection markers appear even when nothing is selected, change the “Hide selection indicators for empty selection” option in QuickTime Player preferences. Cutting, Copying, or Deleting a Section of a Movie Selecting and moving, copying, or deleting (trimming) part of a movie is easy in QuickTime Pro. To cut, copy, or delete part of a movie: 1 Move the playhead until the desired frame appears, or select the part of the movie you want to modify (use the In and Out selection markers and the arrow keys). 2 Choose Edit > Copy, Cut, or Delete. If you choose Copy or Cut, you can paste the selection elsewhere. 3 Position the playhead where you want to paste the selection and choose Edit > Paste. QuickTime Pro inserts the selection you pasted at the position of the playhead. You can also delete all parts of a movie that are not selected by choosing Edit > “Trim to Selection.” Note: After you delete parts of a movie, the file size stays the same until you choose File > Save As and select “Save as a self-contained movie.” Combining Two QuickTime Movies into One With QuickTime Pro, you can easily add one movie to another to make one longer movie. To combine two movies: 1 In QuickTime Player, choose Edit > Select All to select the entire contents of the first movie. 2 Choose Edit > Copy, then open the second movie. 3 Move the playhead to the point at which you want to insert the movie (usually the very beginning or end of the original movie), and choose Edit > Paste. 4 Choose File > Save As to name and save the new movie.32 Chapter 3 Editing and Authoring with QuickTime Pro Working with Tracks A QuickTime movie is made up of one or more “tracks.” Each track stores a particular kind of data. For example, a QuickTime movie could have a video track, music tracks, and sound effects tracks. With QuickTime Pro, you can edit tracks individually. You can move tracks from one movie to another, turn a track on or off, delete tracks, or modify the information contained in a track. Turning Tracks On or Off With QuickTime Pro, you can choose one or more tracks to enable or disable. For example, you might want to turn off tracks to simplify editing, or to hide a track in a final movie. When you export a movie, only enabled tracks are exported. To turn movie tracks on or off: 1 In QuickTime Player, choose Window > Show Movie Properties. The movie’s tracks appear in the list at the top of the Properties window. 2 Use the Enable checkboxes to turn tracks on (selected) or off (deselected). To delete a track, drag it to the Trash, or select it and click Delete,.You can also choose Edit > Cut, or press the Delete key. Note: For audio tracks, other options are available by clicking Audio Settings. To play only the audio in the selected track, select Solo. To play the movie without audio, select Mute. Extracting, Adding, and Moving Tracks With QuickTime Pro, you can create a new movie from one or more tracks of an existing movie, while leaving the original movie file intact. For example, you could create a movie that uses only the audio from an existing movie. To do so, you extract the desired tracks. You can also add the extracted track to an existing movie. Audio narration Video 1 Video 2 Text title Text credits Audio sound effectsChapter 3 Editing and Authoring with QuickTime Pro 33 To extract a track (and add it to another movie): 1 Choose Window > Show Movie Properties. 2 Select the desired track or tracks and click Extract. You can select more than one track by holding down the Shift key when you click. QuickTime creates a new movie containing the extracted tracks. 3 To add the extracted track to another movie, select the movie (or the portion of it you want your pasted media to fit into) and choose Edit > “Add to Movie.” When you add a track to a movie, the track’s duration is unaltered. For example, if you add a 10-second sound track to a 1-minute movie, the sound track plays for 10 seconds, starting at the position in the movie where you added the track. To “scale” a track so that it stretches or compresses to a particular length, drag the In and Out markers of the target movie to select the duration you want the new track to cover and then choose Edit > “Add to Selection and Scale” in step 3. Scaling audio may change the speed of the audio (although the pitch remains the same when you play the movie in QuickTime Player). You could add video to sound instead, and speed up or slow down the video to match the audio. You might have better results if you compare the timelines of the two tracks and cut from one or the other until they have the same duration. Working with Audio Tracks QuickTime audio includes music tracks, which contain MIDI or other data, and sound tracks, which contain digitized audio. Adding an Audio Track to a QuickTime Movie You can easily add audio and other tracks to a QuickTime movie. To add an audio track to a movie: 1 In QuickTime Player, choose File > Open File and select the audio file you want to import. 2 In the QuickTime Player window that opens, choose Edit > Select All to select the entire audio file, then choose Edit > Copy. 3 Open the movie to which you want to add the audio. 4 To add the audio to the whole movie, choose Edit > Add. To add the audio to a part of the movie, select a part and choose Edit > “Add to Selection and Scale”. “Add to Selection and Scale” slows down or speeds up the audio track to fit the length of the selected part of the movie; the pitch remains the same (when you play the movie in QuickTime Player). You could add video to sound instead, and speed up or slow down the video to match the audio. You might have better results if you compare the timelines of the two tracks and cut from one or the other until they have the same duration.34 Chapter 3 Editing and Authoring with QuickTime Pro Note: If your audio and video are created by the same device, such as a DV camera, and are created at the same time, the audio and video will be synchronized. Changing Sound Track Volume Levels and Other Audio Settings With QuickTime Pro, you can change the volume and balance of audio and music tracks. For example, if a movie has more than one audio track, you can adjust the volume of the tracks relative to one another. You can also change the bass and treble levels. To change settings for an audio track: 1 In QuickTime Player, choose Window > Show Movie Properties. 2 In the Properties window, select the audio track and click Audio Settings. 3 Drag the sliders to adjust the settings. 4 Use the pop-up menu to the right of each audio channel to specify where the channel’s sound should be directed. To direct a channel's sound to the subwoofer, choose LFE Screen. To specify a particular output for the audio device, choose one of the Discrete options. To silence a channel, choose Unused. 5 To turn off the audio (without having to delete the track), select Mute. To play only the selected audio track, select Solo. 6 To save the balance and channel settings with your movie, choose File > Save or Save As. Presenting Multiple Movies in the Same Window With QuickTime Pro, you can place multiple video tracks in the same window to play movies side by side or to create a picture-in-picture effect. To present multiple movies in the same window: 1 In QuickTime Player, choose Edit > Select All to select the entire contents of the first movie. 2 Choose Edit > Copy, then open the second movie. 3 Move the playhead to the point at which you want the first movie to begin playing (usually the beginning or end of the original movie), and choose Edit > “Add to Movie.” 4 Choose Window > Show Movie Properties, select the new video track, and click Visual Settings. 5 Use the Current Size and Layer controls to set the new video to a desired size and layer (layers with lower numbers are farther forward, or more “on top”). For example, for a picture-within-a-picture effect, with the added movie inside the original movie, make the new movie smaller and assign it a lower layer number.Chapter 3 Editing and Authoring with QuickTime Pro 35 Pasting Graphics and Text into a Movie With QuickTime Pro, you can paste graphics and text into a QuickTime movie. If a pasted graphic is larger than the movie’s dimensions, QuickTime Pro resizes the movie to fit the dimensions of the graphic. For best results, size graphics (using a graphics program) to match the movie size before you insert them. You can export a single frame from the movie to use as a guide for text placement. (See “Creating a Still Image from a Movie” on page 28.) To find a movie’s dimensions, choose Window > Show Movie Properties, select the video track, and click Visual Settings. To add graphics or text: 1 Copy the text or graphic to the Clipboard. 2 In QuickTime Player, move the playhead to the point at which you want the copied item to appear. 3 Choose Edit > Paste. This procedure inserts the graphic into the movie at the Paste location, in its own frame. To paste the graphic onto the frame at the Paste location, choose Edit >”Add to Movie.” To make a graphic show up in more than one frame, select the portion of the movie you want to add it to and choose Edit > “Add to Selection and Scale.” You can use this technique to add a company logo throughout a movie. (Also see “Changing a Track’s Transparency” on page 39.) Working with Text Tracks You can add text to a QuickTime movie to create titles, credits, and subtitles. With QuickTime Pro, text tracks are searchable, so you can use keywords to find precise frames in the movie. The following topics provide details about adding text tracks. Adding a Text Track to a QuickTime Movie With QuickTime Pro, you can import a text file into a QuickTime movie. To add a text track: 1 Create a text file containing the text you want in the movie, and save the file as text only (.txt). Separate each paragraph with a return character. Each paragraph appears in a separate frame of the movie. By default, each text frame is displayed for 2 seconds. 2 In QuickTime Player, choose File > Open File and select the text file. 3 Click Open.36 Chapter 3 Editing and Authoring with QuickTime Pro Overlaying a Movie with Text With QuickTime Pro, you can use QuickTime Player to overlay (superimpose) text on a specific part of an existing movie. To overlay text: 1 In QuickTime Player, choose File > Open File and then select the text file. 2 Choose Edit > Select All and then choose Edit > Copy. (In Windows, click Options, select the Keyed Text checkbox, and copy the track). 3 Select the part of the movie on which you want to overlay the text. 4 Choose Edit > “Add to Selection and Scale.” 5 Save as a self-contained movie. The text appears throughout the part of the movie you selected. For information about adjusting how long each line of text displays, see “Setting the Frame Duration of a Text Track” on page 36. Specifying Font Styles for Text Tracks With QuickTime Pro you can change the font attributes of a text track already in a movie. To do so, you export the track, make changes, then reimport the track. To change font styles for the text track: 1 In QuickTime Player, choose File > Export. 2 Choose “Text to Text” from the Export pop-up menu. 3 Click Options and select “Show Text, Descriptors, and Time.” 4 Use a text editor to alter the values after the {QTtext} tag. 5 Import the text track back into your movie. In Windows, click Convert. To import the text with the default settings, click Save. To select different settings (such as font attributes), click Options. You can also insert tags throughout the text to change values while the movie plays. Setting the Frame Duration of a Text Track With QuickTime Pro, you can set the duration of each frame in an existing text track to a value other than 2 seconds. To do so, you export the track, make changes, then reimport the track. To change the current text frame information: 1 In QuickTime Player, choose File > Export and choose “Text to Text” from the Export pop-up menu. 2 Click Options and select “Show Text, Descriptors, and Time.” 3 Edit the information in the text file and then import the track back into the movie. Chapter 3 Editing and Authoring with QuickTime Pro 37 The duration for each line of text in the text file appears on a separate line before the line of text. The time you type is the length of time after the movie has started at which this line of text will appear. Timestamps are specified as hours:minutes:seconds:fractions of a second (the default Text to Text export setting is 1/600th of a second). For example, if you enter the time 00:02:11:00, the text on the following line appears at 2 minutes and 11 seconds into the movie. For information about the other text track descriptors, see the developer section of the QuickTime website at www.apple.com/quicktime. Specifying Languages for Individual Tracks With QuickTime Pro, you can create a movie with support for multiple languages by specifying a language for an individual track. For example, you can create a movie that contains a separate audio track for each language. QuickTime automatically plays the correct track, based on the language setting of the user’s computer. To specify languages: 1 Create or assemble the alternate tracks. Record voiceovers in each desired language or create text tracks to use as subtitles. Save each alternate track as a self-contained movie, and put all the alternates together in a single folder. 2 Put a copy of your original movie, self-contained and minus any tracks that are now stored as alternates, in the folder with the alternates. 3 Open the movie and choose Window > Show Movie Properties. 4 In the Properties window, select a sound or text track and click Other Settings. 5 Choose the language of this track from the Language pop-up menu. 6 Choose a track to use when a different language is selected from the Alternate pop-up menu. 7 Save as a self-contained movie (choose Edit > Save As and make sure “Make movie selfcontained” is selected). 8 Repeat these steps for additional language tracks; each time, choose the previously selected language from the Alternate pop-up menu.38 Chapter 3 Editing and Authoring with QuickTime Pro Changing Movie Properties The following sections describe how to resize or rotate a movie, set a movie’s poster frame, and more. Adding Annotations to a Movie With QuickTime Pro, you can add annotations to document information about the movie, such as its author, director, and copyright information. You can annotate the entire movie and any of its individual tracks. To annotate a movie: 1 In QuickTime Player, choose Window > Show Movie Properties. 2 Select an item from the list and click Annotations. 3 Choose an annotation to add from the Add Annotation pop-up menu. 4 Enter the annotation in the Value column of the list. Users who don’t have QuickTime Pro see only three of the annotations the movie contains. (Which three appear depends on which annotations the movie contains.) Resizing, Flipping, or Rotating a Movie With QuickTime Pro, you can change the size and orientation of a video track of a movie. To resize or rotate a QuickTime movie: 1 In QuickTime Player, choose Window > Show Movie Properties. 2 In the Properties window, select a video track and click Visual Settings. 3 To resize the movie, type new numbers in the Current Size fields. To keep the same height-to-width proportions, select Preserve Aspect Ratio. 4 To rotate the movie, click one of the rotate buttons. To restore the movie to its original appearance, click Reset. Flip horizontal or vertical Rotate right or leftChapter 3 Editing and Authoring with QuickTime Pro 39 Changing a Movie’s Shape with a Video Mask With QuickTime Pro, you can change the shape of a movie from rectangular to other shapes using a video mask. In combination with a media skin; you can “skin” a movie so that it plays in a non-rectangular region (for example, a movie could play from within a ship porthole), and then use a mask to restrict the movie’s shape to the desired playback region. Use a graphics program to create the mask and save it as a QuickTime-compatible file (for example, BMP, GIF, JPEG, or PICT). The mask should be a black shape on a white background. The movie appears through the black shape. To add a video mask: 1 In QuickTime Player, choose Window > Show Movie Properties. 2 Select the video track you want to assign the mask to, then click Visual Settings. 3 Drag the mask file to the Mask well in the Properties window, or click Choose to select the file. Changing a Track’s Transparency With QuickTime Pro, you can create a track that is partly transparent. This technique is useful, for example, for overlaying a movie with a logo. To change a track’s transparency: 1 Add the track to the movie. (See “Extracting, Adding, and Moving Tracks” on page 32.) 2 Choose Window > Show Movie Properties. 3 Select the track and click Visual Settings. 4 Choose Blend from the Transparency pop-up menu and drag the Transparency Level slider. Creating a Chapter List for a Movie With QuickTime Pro, you can create a pop-up chapter list to navigate to specific points in a movie. First you create a list of topics (or entry points), and then you import the list into the movie as a text track. When you play the movie in QuickTime Player, the current chapter displays in the movie controller. (See “Opening and Playing Movies in QuickTime Player” on page 11.) To create a chapter list: 1 In a text editor or word processor, type your list of chapters and save the document as plain text. Make each item very short (preferably one word but no more than two or three words) and separate each item with a return character. 2 In QuickTime Player, choose File > Open File, select the text file, and click Open. 40 Chapter 3 Editing and Authoring with QuickTime Pro 3 Choose File > Export. In the Export pop-up menu, choose “Text to Text.” In the Use pop-up menu, choose “Text with Descriptors.” 4 Click Options. In the Text Export Settings dialog, select “Show Text, Descriptors, and Time”; select “Show time relative to start of Movie”; and set fractions of seconds to 1/30 (the default is 1/1000). 5 Click OK, then click Save to create a text file with descriptors. 6 Open the exported list in your text editor or word processor, and open the target movie in QuickTime Player. 7 Choose Window > Show Movie Info. 8 In QuickTime Player, drag the playhead on the timeline to find the first point in the movie where you want to begin a new chapter. Use the Right and Left Arrow keys to step forward or backward a frame at a time as needed. Note the current time in the Properties window. 9 In the text file, find the first chapter title and change the timestamp just before that chapter title to the time you noted in the Properties window. The timestamp might now read, for example, [00:01:30.15], meaning that selecting the first chapter title will jump the viewer 1 minute, 30 seconds, and 15 frames into the movie. 10 Repeat steps 9 through 11 until you’ve identified all the places in the movie that correspond to the chapter divisions and you’ve entered the proper timestamps in the text file. 11 Change the last timestamp (the one after the last chapter title in the text file) to match the duration of the movie. 12 Save the text file and import it into QuickTime Player. QuickTime creates a new movie with just a text track. 13 Choose Edit > Select All, choose Edit > Copy, and close the movie. 14 Click in the main movie, choose Edit > Select All, and then choose Edit > “Add to Movie.” QuickTime adds the text track to the movie. 15 Choose Window > Show Movie Properties. 16 In the Properties window, select the video or audio track you want to associate with the chapter track, and click Other Settings. 17 Choose the main video or audio track from the Chapters pop-up menu. If you have a movie with alternate subtitle or sound tracks, you can create multiple chapter lists in different languages and set the appropriate subtitle or sound track as the owner of each chapter list. The chapter list will change to match the selected language. Chapter 3 Editing and Authoring with QuickTime Pro 41 18 Select the text track, then select “Preload this track” (to make the chapter track load first). 19 Deselect the new text track so that it doesn’t display on top of the video. The new track will still function as a chapter track. 20 Save the movie as a self-contained movie. You can now choose a chapter title from the pop-up menu to the right of the timeline. Setting a Movie’s Poster Frame A poster frame is a still image of a movie that represents the movie in places like the QuickTime Player Favorites window and the Finder. The default poster frame is the first frame in the movie. With QuickTime Pro, you can change the poster frame. To change a movie’s poster frame: 1 In QuickTime Player, drag the playhead (or use the arrow keys to move the playhead) to the desired frame. 2 Choose View > Set Poster Frame. To view a movie’s poster frame, choose View > “Go to Poster Frame.” Saving a Movie with Specific Playback Settings With QuickTime Pro, you can specify how a movie should open and play, what happens when the movie finishes, and the method QuickTime uses to resize the video. To specify playback options: 1 Choose Window > Show Movie Properties. 2 Select the movie name, and then click Presentation. 3 Select the desired options. 4 Save the movie. Changing the Movie Controller Type With QuickTime Pro, you can specify the kind of playback controls available on the QuickTime Player window. For a QTVR movie, for example, you can save the movie with one of the QTVR movie controllers. To specify a movie controller type: 1 Choose Window > Show Movie Properties. 2 Select Movie and click Presentation. 3 Choose an option from the Movie Controller Type pop-up menu. 4 Save the movie.4 42 4 Exporting Files with QuickTime Pro If you want more control over how QuickTime creates a file, use the Export feature of QuickTime Pro. With QuickTime Pro, you can export a movie to a number of different file formats, such as QuickTime movie (MOV), MPEG-4, 3GPP, 3GPP2, AVI, and DV. In addition, you can export an audio track to several different audio formats, export the individual frames of a movie as separate image files, or export a text track to a text file. To see the list of file formats available for a movie open in QuickTime Player, choose File > Export and browse the list of file format choices in the Export pop-up menu. About Video and Audio Compression Because uncompressed video and audio require a lot of disk space to store and a lot of bandwidth (the rate at which data can be transferred) to deliver, you’ll want to compress (encode) your movie before sending it to another computer or on the web. Movies are usually compressed (encoded) as part of the export process.Chapter 4 Exporting Files with QuickTime Pro 43 Exporting Files Using Presets QuickTime Pro offers a myriad of settings and options for compressing video and audio during export. To help simplify the process of compressing and exporting, QuickTime Pro also offers export presets. Different presets are available for each file format. To export a movie using presets: 1 In QuickTime Player, open the movie you wish to export. 2 Choose File > Export. 3 Choose a file format from the Export pop-up menu. 4 Choose the preset that best meets your needs from the Use pop-up menu. For example, to export a movie for use with a video-capable iPod, choose “Movie to iPod.” To export a movie that is optimized for Apple TV, choose “Movie to Apple TV.” You can also create movies for iPhone by choosing one of the “Movie to iPhone” options. 5 Choose a filename and location, and click Save. Note: To use the same settings you used during the last export, choose Most Recent Settings from the Use pop-up menu. Customizing Export Settings For the greatest possible control when compressing and exporting media files, use the export options available in QuickTime Pro. For video compression and export, QuickTime Pro offers customizable settings in three categories: video settings, filters (also known as special effects), and image size. QuickTime Pro also offers many options for customizing compression settings for sound. The following topics provide information about which options to choose when exporting and compressing movies. Customizing Video Export Settings To customize video settings for export: 1 Choose File > Export. 2 Choose a file format from the Export pop-up menu. For the options discussed below, choose “Movie to QuickTime Movie.” 3 Click Options.44 Chapter 4 Exporting Files with QuickTime Pro 4 In the Video area of the Movie Settings dialog, click Settings, and then choose your settings.  Compression type: Choose the video compressor (codec) you want to use to compress your video. For the highest quality at the lowest data rate (or the smallest file), H.264 is recommended.  Data rate (bit rate): In general, the higher the data rate, the better the quality, but the bigger the file. In most cases, you’ll want to set a data rate based on the way your movie will be viewed. For example, for streaming to Internet dialup connections, limit the data rate to around 45 kilobits per second to leave room for network traffic. If the file will be downloaded for playback, the data rate can be higher (a 56K modem user, however, has longer to wait before playback begins). The data rate of a movie is also affected by other compression options you set, such as the frame rate. To let the compressor choose an appropriate data rate, select Automatic.  Optimized for: Choose your intended delivery method from the “Optimized for” pop-up menu. This setting informs the codec how much the data rate can vary above and below the data rate you choose. This option is available only for compressors that can apply limits, such as H.264.  Key frame options: Many compressors use “frame differencing” to compress moving images. Frame differencing is the process of determining what information has changed from a starting frame (called a key frame) to subsequent frames. The key frame contains all of the information for an image. Subsequent frames contain only the information that has changed. Depending on the compressor you use, you can specify how often you want key frames to occur. If you don’t have enough key frames, the quality of your movie might be lower because most frames are generated from others. However, more key frames result in a larger movie with a higher data rate. With some compressors, an additional key frame is inserted automatically if too much of the image has changed from one frame to the next. A good rule of thumb for general use is to have one key frame every 5 seconds (multiply the frames per second by 5). If you are creating a file for RTSP streaming and have concerns about the reliability of the delivery network (as with the public Internet), you may want to increase key frame frequency to one key frame every 1 or 2 seconds. To let the compressor choose the key frame interval, select Automatic.  Frame rate: Frame rate is the number of individual images shown every second. Standard (NTSC) video has a frame rate of 29.97 frames per second (fps), and the standard for film is 24 fps. The European standard (PAL) is 25 fps. QuickTime movies are sometimes created with a slower frame rate to reduce bandwidth and CPU requirements.Chapter 4 Exporting Files with QuickTime Pro 45 Movies with higher frame rates show motion better but have larger file sizes. If you choose a frame rate that’s lower than the movie’s current frame rate, frames will be deleted. If you choose a number that’s higher than the movie’s current frame rate, existing frames will be duplicated (not recommended, since it increases file size without improving quality). When choosing a frame rate, use a simple fraction of your current frame rate, such as 1/2, 1/3, and so on. For example, if your current frame rate is 30 (29.97), use 15 or 10.  Other options: Some compressors or codecs offer options specific to the codec. After you select a compressor (codec), any special options appear. Adding Special Effects and Filters to a QuickTime Movie With QuickTime Pro, you can add special effects such as blur, emboss, and film noise to a movie before you export it. You add special effects by using filters. To set a filter for a movie: 1 In QuickTime Player, choose File > Export. 2 Choose “Movie to QuickTime Movie” from the Export pop-up menu. 3 Click Options, click Filter, and select the filter and settings you want to use. The selected filter is applied to the entire movie. Changing Image (Frame) Size With QuickTime Pro, you can change the size of a movie’s video frame. For example, if your movie will be viewed on a small screen (such as a mobile device), you can change the movie’s dimensions to match the target device. You can experiment with making the frame size smaller for a given data rate to get better encoding results. To change the size of a movie’s video frame: 1 Choose File > Export. 2 Choose a file format from the Export pop-up menu. 3 Click Options. 4 In the Video area of the Movie Settings dialog, click Size and then choose an option:  Use current size: This option (the default) keeps the exported movie’s image size the same as your original source movie.  Use custom size: When you choose this option, you can specify (in pixels) a height and width for the exported movie’s image size. For best results, choose dimensions smaller than your source movie, and keep the height-to-width ratio the same as the source (so that objects don’t appear distorted).46 Chapter 4 Exporting Files with QuickTime Pro Customizing Sound Export Settings To customize sound settings for export: 1 Choose File > Export. 2 Choose “Movie to QuickTime Movie” from the Export pop-up menu. 3 Click Options. 4 In the Sound area of the Movie Settings dialog, click Settings and then choose your options:  Format: Choose the compressor (codec) you want to use for compressing sound. For general use and Internet delivery of music, MPEG-4 Audio (AAC) is recommended.  Channels: Choose between mono (1 channel) or stereo (2 channels).  Rate: Digitized sound is made up of sound samples. The more samples per second, the higher the sound quality. To maintain quality, music requires a higher sampling rate than spoken voice because music uses a wider range of frequencies. Audio CDs use a sampling rate of 44.1 kHz.  Render Settings: Choose the quality of the signal processing that will be used; higher quality settings take longer to process.  Other options: To see any additional options specific to your chosen codec, click the Options button. if it’s available. Preparing Movies for Internet Delivery With QuickTime Pro, you can create movies so that they can be delivered over the Internet. You can deliver a movie over the Internet in two ways:  With HTTP download, the movie is downloaded to the client’s hard disk. Fast Start is a QuickTime feature that enables users to watch or listen to media as it is being downloaded (long before the whole movie has been downloaded) from a standard web server to their hard disks. Fast Start works well for short-form movies where file size is limited. It ensures high-quality playback regardless of users’ Internet connection speeds, although those with slower connections will wait longer before media starts to play.  Real-time streaming provided by QuickTime Streaming Server (QTSS) delivers media in real time over the Internet, from modem rates to broadband. No file is ever downloaded to a viewer’s hard disk. Media is played, but not stored, by the client software as it is delivered. You would choose real-time streaming rather than Fast Start for webcasts of live events in real time, delivery of long-form video, 24/7 Internet radio and TV channels, and other cases in which you don’t files stored on a user’s hard disk. QTSS uses the RTSP protocol.Chapter 4 Exporting Files with QuickTime Pro 47 Preparing a Movie for Fast Start With QuickTime Pro, you can set up a movie to start playing from a web server before the movie has completely downloaded to the user’s hard disk. This is called a “Fast Start” movie. Set the Fast Start setting just before you distribute your movie; making other changes and resaving may undo the Fast Start setting. If the movie is in the format you want, you can set it up for Fast Start by choosing File > Save As and then selecting “Save as a self-contained movie.” If the movie is not in the format you want, you need to encode it first by following the steps below. To convert a movie and set it up for Fast Start: 1 In QuickTime Player, choose File > Export. 2 Choose “Movie to QuickTime Movie” from the Export pop-up menu. 3 Click Options and select video and sound compression options appropriate for web delivery. For more information, see “Customizing Video Export Settings” on page 43, “Customizing Sound Export Settings” on page 46, and the tutorials at www.apple.com/quicktime/resources. 4 Make sure the “Prepare for Internet Streaming” checkbox is selected and Fast Start appears in the pop-up menu. Preparing a Movie for Real-Time Streaming With QuickTime Pro, you can set up a movie to be streamed over the Internet. To do so, you should compress the movie so that its data rate is appropriate for the bandwidth at which your users will connect. Hinted streaming format is for use with QuickTime Streaming Server or Darwin Streaming Server. When you choose hinted streaming, “hint tracks” (information needed to stream the movie) are added to the movie. If the movie is already in the desired format, you can prepare a movie for streaming by choosing File > Export and then choosing “Movie to Hinted Movie.” If you want to change the movie’s format, follow the steps below. To set up a movie for Internet streaming: 1 In QuickTime Player, choose File > Export. 2 Choose “Movie to QuickTime Movie” from the Export pop-up menu. 3 Choose a streaming option from the Use pop-up menu. 4 Click Options and select the “Prepare for Internet Streaming” checkbox. 5 Choose Hinted Streaming from the pop-up menu.48 Chapter 4 Exporting Files with QuickTime Pro If you want to stream a QuickTime movie using QuickTime Streaming Server, you should use a web-optimized video or audio compressor to compress the movie file. All QuickTime compressors are compatible with QuickTime Streaming Server, but the compressors listed here are optimized to give the best results for delivery over the Internet. For a complete list of compressors that QuickTime supports, see the Products area of the QuickTime website (www.apple.com/quicktime/products).  Video compressors: H.264, MPEG-4, Sorenson Video (any version), H.263, H.261  Audio compressors: AAC, QUALCOMM PureVoice, AMR, QDesign For more information about preparing a movie for streaming, go to www.apple.com/quicktime/resources. Creating Reference Movies to Optimize Web Playback You can use reference movies to provide the appropriate movie for different users’ connection speeds. For example, you can have a smaller movie streamed to users connected over a standard modem, and a larger version of the movie streamed to users connected over a broadband connection. Apple provides a free tool, MakeRefMovie X, that greatly simplifies the process of creating reference movies. You can download this software at: developer.apple.com/quicktime/quicktimeintro/tools For more information about reference movies see “Creating Movies Optimized for iPhone and Web Delivery” on page 48 Creating Movies Optimized for iPhone and Web Delivery With QuickTime Pro you can easily create versions of your movie that are optimized for iPhone and desktop viewing. This saves you several steps in creating movies for online distribution and ensures that your audience automatically receives the best viewing experience for the device they’re using. To export for iPhone and web delivery: 1 Choose File > Export for Web. 2 In the dialog that appears, specify a filename and select a location for the exported movies and HTML snippet file. 3 Select the versions you want to create.  iPhone: Creates a movie that is optimized for delivery to iPhone over a Wi-Fi connection.  iPhone (cellular): Creates a move that is optimized for delivery to iPhone over a cellular (EDGE) connection.  Desktop: Creates a movie optimized for delivery to computers over broadband connections.Chapter 4 Exporting Files with QuickTime Pro 49 4 Choose a poster frame option for the movie. The poster frame determines the still image viewers will see when they load the web page with the embedded reference movie. If you want to set a new poster frame before exporting the versions, click Cancel. Then navigate to the frame you want to use and choose View > Set Poster Frame. 5 Click Export to create the files necessary for the options you selected. The exporting process creates several files, including files for each version of the movie you select, a reference movie that will automatically deliver the correct version to the viewer, and an HTML file that contains a snippet of code you can use to embed the movie in a web page. All of these files must be copied to your web server, in the same location relative to each other and with the same file names, in order for the reference movie and HTML snippet to function correctly. Exporting MPEG-4 Files MPEG-4 is the latest worldwide industry standard for delivering professional-quality audio and video over a wide range of bandwidths, from mobile multimedia to high definition. When you want to create a file that will work with another MPEG-4 device, use QuickTime Pro to create MPEG-4 content by exporting a movie. To export a file to the MPEG-4 format: 1 Open the movie you want to export in QuickTime Player, then choose File > Export. 2 Choose “Movie to MPEG-4” from the Export pop-up menu. Note: To create an MPEG-4 movie that is optimized for use with Apple TV, iPhone, or iPod, select “Movie to Apple TV” , “Movie to iPhone”, or “Movie to iPod” from the Export pop-up menu. All of the MPEG-4 options will be set to the appropriate values for you. To adjust settings such as file format, compression, and distribution restrictions, click Options. The options you choose depend on the network over which you’ll deliver the file and the viewers’ connection. The following sections describe the options in detail. MPEG-4 Video Export Options When you export a movie to MPEG-4 format (by choosing File > Export and then choosing “Movie to MPEG-4”), you access the following options by clicking Options and then clicking Video.  File Format: To ensure operability with devices made by ISMA members, choose “MP4 (ISMA).” For more information, go to www.isma.tv.50 Chapter 4 Exporting Files with QuickTime Pro  Video Format: Choose the video compressor (codec) you want to use to compress your video. For the highest quality at the lowest data rate (or the smallest file), H.264 is recommended. If you need the file to play on a device that supports MPEG-4 video, choose MPEG-4 Basic or MPEG-4 Improved, depending on the target device. If your source movie’s video track is already compressed, you can choose “Pass through” so that the video doesn’t get compressed again.  Data Rate: The more kilobits per second (kbps), the better the movie quality. For best playback, however, don’t choose a data rate higher than the available bandwidth.  Optimized for: If you choose H.264 from the Video Format pop-up menu, choose your intended delivery method from the “Optimized for” pop-up menu. This setting tells the codec how much the data rate can vary above and below the data rate you choose.  Image Size: Current maintains the source material size. To choose a size not listed in the pop-up menu, choose Custom.  Preserve Aspect Ratio Using: If you are changing the image size, use this option to specify an option in case the movie needs to be scaled to the new dimensions. Letterbox will scale the source proportionally to fit into the clean aperture, adding black bars to the top and bottom or sides as necessary. Crop centers, scales, and trims to the clean aperture. Fit Within Dimensions adjusts to the destination size by fitting to the longest side, scaling if necessary.  Frame Rate: In most cases, your video will look better if you choose a number that is exactly divisible by the FPS (frames per second) of your source. For example, if your source is captured at 30 FPS, choose a frame rate of 10 or 15. Don’t choose a rate larger than that of your source material.  Key Frame: The more often you specify a key frame (the lower the number), the better the video quality, but the bigger the file. If you choose MP4 from the File Format pop-up menu and H.264 from the Video Format pop-up menu, and then click Video Options, you get the following additional options:  Restrict Profile(s) to: If you need the file to play on a device that conforms to one or more of the standard’s profiles, check those profiles here.  Encoding Mode: Choose whether you want the best quality or faster encoding. MPEG-4 Audio Export Options When you export a movie to MPEG-4 format (by choosing File > Export and then choosing “Movie to MPEG-4”), you access the following options by clicking Options and then clicking Audio.  Audio Format: Choose your audio compressor (codec) here. If your source movie has only one audio track and it is already compressed, you can choose “Pass through” so that the audio doesn’t get compressed again.Chapter 4 Exporting Files with QuickTime Pro 51  Data Rate: As with video, the more kilobits per second, the better the audio quality.  Channels: Choose between mono (1 channel) or stereo (2 channels).  Output Sample Rate: Available only with AAC audio. It’s best to match the sample rate to that of the target device.  Encoding Quality: Available only with AAC audio. The Good setting is optimized for the highest-speed encoding, for higher-quality, choose Best for 16-bit audio, or Better if your audio source is 24-bit. MPEG-4 Streaming Export Options When you export a movie to MPEG-4 format (by choosing File > Export and then choosing “Movie to MPEG-4”), you access the following options by clicking Options and then clicking Streaming. If you’re going to deliver the exported file using RTSP streaming, select “Enable streaming.” Streamed data must be sent in smaller-size packets. Some networks have limitations on packet size and packet duration. If your network provider gives you information about size limitations, you can change the packet size and the maximum packet duration to comply with your delivery network. Otherwise, use the default values. Exporting 3G Files QuickTime Player can import and play back files for use on 3G networks—high-speed mobile networks that enable multimedia to be sent between mobile devices. QuickTime supports standards for nearly any kind of 3G mobile network. To import a 3G file, choose File > Open File and then select the file. You can also open a 3G file in QuickTime by dragging it to the QuickTime icon in the Dock or doubleclicking the file (Mac OS X only). With QuickTime Pro, you can export video, audio, and text to one of the many 3G formats that QuickTime supports. To export a file to the 3G format: 1 Open the movie you want to export in QuickTime Player, then choose File > Export. 2 Choose “Movie to 3G” from the Export pop-up menu. To adjust settings such as file format, compression, and distribution restrictions, click Options. The options you choose depend on the mobile network over which you’ll deliver the file and the capabilities of the viewer’s phone. The following sections describe the options in detail.52 Chapter 4 Exporting Files with QuickTime Pro 3G File Format Export Options After you choose File > Export and click Options, the first two items in the File Format pop-up menu are the standard formats.  3GPP is for GSM networks. With this format, you can use:  MPEG-4, H.263, or H.264 video  AAC or AMR audio  3G timed text  3GPP2 is for CDMA 2000 networks. With this format, you can use:  MPEG-4, H.263, or H.264 video  AAC, AMR, or QCELP audio  3G timed text  Movie fragments (enables playback to start sooner for longer movies, since only the fragment, not the whole movie, must fit on the handset) The remaining formats are provided for specific networks. With these formats, you can restrict distribution so that a file can’t be shared from the recipient’s phone (set this option in the Advanced pane). These formats may limit the acceptable file size or data rate; check with the service provider for more information.  3GPP (Mobile MP4) is for NTT DoCoMo’s i-motion 3G service. With this format, you can use the 3GPP options described above.  3GPP2 (EZmovie) is for KDDI’s 3G network service. This format provides the same options as 3GPP2 (described above), except for AMR audio support.  AMC (EZmovie) is for KDDI subscribers with AMC-capable phones. With this format, you can use:  MPEG-4 video  QCELP audio  KDDI’s text format 3G Video Export Options  Video Format: If your source movie has only one video track and it is already compressed, you can choose “Pass through” (so that the video doesn’t get compressed again).  Data Rate: The more kilobits per second (kbps), the better the movie quality. For best playback, however, don’t choose a data rate higher than the available bandwidth.  Optimized for: If you choose H.264 from the Video Format pop-up menu, choose your intended delivery method from the “Optimized for” pop-up menu. This setting tells the codec how much the data rate can vary above and below the data rate you choose.Chapter 4 Exporting Files with QuickTime Pro 53  Image Size: If you’re sending the file to a mobile phone, choose one of the standards. Current maintains the source material size; the resulting file may not play on a mobile phone. To choose a size not listed in the pop-up menu, choose Custom.  Preserve Aspect Ratio Using: If you are changing the image size, use this option to specify an option in case the movie needs to be scaled to the new dimensions. Letterbox will scale the source proportionally to fit into the clean aperture, adding black bars to the top and bottom or sides as necessary. Crop centers, scales, and trims to the clean aperture. Fit Within Dimensions adjusts to the destination size by fitting to the longest side, scaling if necessary.  Frame Rate: In most cases, your video will look better if you choose a number that is exactly divisible by the FPS (frames per second) of your source. For example, if your source is captured at 30 FPS, choose a frame rate of 10 or 15. Don’t choose a rate larger than that of your source material.  Key Frame: The more often you specify a key frame (the lower the number), the better the video quality, but the bigger the file. These additional options are available when you click Video Options:  Re-sync markers: Adds re-sync markers inside the video frames to help with packet loss recovery when streaming.  Encoding Mode: With H.264 video, you can speed up the compression process (for preview purposes, for example) by choosing “Faster encode (Single-pass).” With the default option, “Best quality (Multi-pass),” the codec determines how many passes are needed to compress the data for the best quality. 3G Audio Export Options When you export a movie to 3G format (by choosing File > Export and then choosing “Movie to 3G”), you access the following options by clicking Options and then clicking Audio.  Audio Format: If your source movie has only one audio track and it is already compressed, you can choose “Pass through” (so that the audio doesn’t get compressed again).  Data Rate: As with video, the more kilobits per second, the better the audio quality.  Channels: Choose between mono (1 channel) or stereo (2 channels).  Frames per sample: Available only with AMR audio, this option enables exported audio data to be packed more efficiently.  Silence detection: Available only with AMR audio, this option detects audio portions with low signal levels and adjusts the data rate of the output accordingly.  Output Sample Rate: Available only with AAC audio. It’s best to match the sample rate to that of the target device.  Encoding Quality: Available only with AAC audio. By choosing Best, you can get higher-quality audio but it takes longer to encode.54 Chapter 4 Exporting Files with QuickTime Pro 3G Text Options When you export a movie to 3G format (by choosing File > Export and then choosing “Movie to 3G”), you access the following options by clicking Options and then clicking Text. These options are available if your movie has a text track (credits, titles, subtitles, and so on). Some mobile devices can’t play text in a movie. To allow the movie to play only if the text can be displayed on the receiving device, select “Require text capability on handset.” Deselect this checkbox to allow the audio and video to play even if the text can’t be displayed on the device. 3G Streaming Options When you export a movie to 3G format (by choosing File > Export and then choosing “Movie to 3G”), you access the following options by clicking Options and then clicking Streaming. To create a file for RTSP streaming to QuickTime Player, select “Enable streaming.” This option creates a hint track (instructions necessary for streaming a file). “Optimize for server” helps the server to process the file faster, but increases the file size. 3G Advanced Options When you export a movie to 3G format (by choosing File > Export and then choosing “Movie to 3G”), you access the following options by clicking Options and then clicking Advanced. If your file is in Mobile MP4 or EZmovie format, you can restrict distribution so that once the file is on a handset it can’t be sent or copied anywhere else. You can specify how many times the file can play back on the handset once downloaded, or make the file expire after a certain number of days or on a certain date. “Fragment movie” enables the file to download via HTTP in small pieces so that playback can start faster and so that larger files can be played on the handset (only the fragment, not the entire movie, must fit on the handset at one time). 55 Appendix Shortcuts and Tips Learn keyboard shortcuts and other tips for using QuickTime efficiently. QuickTime Player Keyboard Shortcuts QuickTime Player and QuickTime Pro provide keyboard shortcuts for most playback options. When available, each of these shortcuts appears to the right of its associated menu item. A few keyboard shortcuts have no menu equivalents. For this control Press Play/pause Space bar Play or pause all movies Command-Return Play movie backward Shift–double-click, Command–Left Arrow Stop playback and go back one frame Left Arrow Stop playback and go forward one frame Right Arrow Go to beginning of selection or movie Option–Left Arrow Go to end of selection or movie Option–Right Arrow Turn volume up Up Arrow Turn volume down Down Arrow Turn volume up to maximum level Option–Up Arrow Turn volume down to minimum level Option–Down Arrow56 Appendix Shortcuts and Tips QuickTime Pro Keyboard Shortcuts For this control Press (Mac OS X) Press (Windows) Play/pause Space bar Space bar Play or pause all movies Command-Return Control-Enter Play movie backward Shift–double-click Command–Left Arrow Shift–double-click Stop playback and go back one frame Left Arrow Left Arrow Stop playback and go forward one frame Right Arrow Right Arrow Go to beginning of selection or movie Option–Left Arrow Control–Left Arrow Go to end of selection or movie Option–Right Arrow Control–Right Arrow Turn volume up Up Arrow Up Arrow Turn volume down Down Arrow Down Arrow Turn volume up to maximum level Option–Up Arrow Control–Up Arrow Turn volume down to minimum level Option–Down Arrow Control–Down Arrow To do this... Press Enter full-screen mode Command-F Exit full-screen mode Command-period or Esc Play movie at half size Command-0 Play movie at normal size Command-1 Play movie at double size Command-2 Play movie at full size Command-3 Move In marker to playhead location I Move Out marker to playhead location O Extend selection to the left Option–Shift–Left Arrow Extend selection to the right Option–Shift–Right Arrow Extend selection to point clicked in LCD Shift-clickAppendix Shortcuts and Tips 57 Automating QuickTime Player with AppleScript In Mac OS X, you can use AppleScript to automate QuickTime Player functions. For example, you can open a movie and tell it to play for a specific duration; automate the conversion of movies from one format to another; adjust track playback properties such as start time, volume, and layer; or adjust movie properties such as copyright and author. To determine all of the AppleScript commands you can use to control QuickTime Player, install AppleScript and look at the QuickTime Player AppleScript dictionary. 1 Open Script Editor. 2 Choose File > Open Dictionary. 3 Select QuickTime Player. Sample QuickTime Player scripts can be found on the AppleScript website (www.apple.com/applescript/quicktime). To do this Press (Mac OS X) Press (Windows) Enter full-screen mode Command-F Control-F Exit full-screen mode Command-period or Esc Control-period or Esc Play movie at half size Command-0 Control-0 Play movie at normal size Command-1 Control-1 Play movie at double size Command-2 Control-2 Play movie at full size Command-3 Control-3 Move In marker to playhead location I I Move Out marker to playhead location O O Extend selection to the left Option–Shift–Left Arrow Extend selection to the right Option–Shift– Right Arrow Extend selection to point clicked in LCD Shift-click58 Appendix Shortcuts and Tips Automating QuickTime Player on Windows In Windows, you can use JavaScript, Visual Basic, or other Active Scripting languages to automate QuickTime Player functions. As with AppleScript on Mac OS X, you can control movie playback, convert movies from one format to another, adjust movie and track properties, and more. There are three QuickTime Player objects available for use:  QuickTimePlayerApp The application object. This object has a Players property which returns a collection of the QuickTime Player windows. The Quit method exits the program.  QuickTimePlayers Use this object to enumerate player windows; the Remove and Add methods permit the removal and creation of new QuickTime Player windows.  QuickTimePlayer This object has properties and methods to open movies, control the window’s position and appearance, and to interact with its menus. The QTControl property returns the ActiveX control hosting the window’s movie. To examine the QuickTime Player or QuickTime Control interfaces in detail, look at the Apple QuickTime Player Library 1.0 or Apple QuickTime Control 2.0 interfaces in a COM object browser. 59 Glossary Glossary AIFF (Audio Interchange File Format) An audio file format used widely on the web. aspect ratio The relationship between the height and width of an image. audio channel Audio tracks can contain one or more channels of audio data. Each channel represents the sound directed to a particular speaker. For instance, stereo tracks contain two audio channels. audio channel label Each audio channel may be labeled to specify where its sound should be directed. In a stereo track, the channels are typically labeled Left and Right. In a 5.1 surround sound track, there are labels for Left, Right, Center, Left Surround, Right Surround, and LFE Screen (the subwoofer). bandwidth The capacity of a network connection, measured in bits or bytes per second (bps or Bps), for carrying data. BMP A bitmapped graphics format used for still images in the Windows environment. bitmapped Represented by pixels. chapter list A list of “locations” in a movie. A user can choose an item from the chapter list to go to that point in the movie. codec From “compressor/decompressor.” A codec is technology for compressing and decompressing data. Codecs can be implemented in software, hardware, or a combination of the two. Codecs can by “lossy” or “lossless,” depending on whether data is lost during compression. compression The process of reducing the data size of a file. Darwin Streaming Server A technology for delivering media over the Internet in real time. Based on the same code as Apple’s QuickTime Streaming Server (QTSS), Darwin Streaming Server is an open-source streaming server.60 Glossary Fast Start A method of delivering a movie so that it can start playing before it is fully downloaded. frame A single image in a movie. frame rate The number of frames displayed per second. GIF (Graphics Interchange Format) A file format for images. hint track In a streamed movie, a hint track specifies for the server how the movie’s content is to be transmitted. hot spot A place in a virtual reality movie where the user can interact with the movie using the mouse. Instant-On A technology that dramatically improves access to streaming content for broadband users. JPEG (Joint Photographic Experts Group) A standard for compressing still images. layer In QuickTime movies, how an image is displayed depends on its layer; images with lower layer numbers are displayed on top. MIDI (Musical Instrument Digital Interface) A software and hardware standard set by the music industry that enables electronic instruments to communicate with one another and with computers. MP3 (MPEG-1 layer 3) A format for compressing music. MPEG-4 An ISO standard based on the QuickTime file format that defines multimedia file and compression formats. node In QuickTime VR, a point from which an object or panorama can be viewed. NTSC (National Television System Committee) The organization that defines North American broadcast standards. The term NTSC video also refers to the video standard defined by the committee, which is 29.97 fps, 525 lines per frame, and interlaced. PAL (Phase Alternation by Line) A video format used by many European countries and other countries outside North America. The PAL standard is 25 fps, 625 lines per frame, and interlaced. PICT A Mac OS picture file format that does not apply compression to an image and therefore maintains the same quality level from copy to copy. pixel The onscreen dots that form text and graphics. A contraction of the words picture and element. plug-in Software that helps a web browser interpret certain types of media files.Glossary 61 PNG (Portable Network Graphics) A file format for images. poster In QuickTime, a still image, usually a single frame from a movie, used to represent the movie to users. protocol A set of standards for sending and receiving information on a network. QTSS (QuickTime Streaming Server) A technology used to deliver media over the Internet in real time. QuickTime Player An application that opens and plays QuickTime movies, as well as many other kinds of files. QuickTime Pro A version of QuickTime Player with advanced features, primarily the addition of editing capabilities. QuickTime VR A QuickTime media type with which users can interact with threedimensional places and objects. reference movie A file that contains the location of one or more media files. A reference file linked from a webpage, for example, can direct a QuickTime Player to the version encoded for a particular connection speed. RGB Red, green, blue; a way of representing colors onscreen. RTSP (Real-Time Streaming Protocol) A protocol for controlling a stream of real-time multimedia content. Sources of data can include both live feeds and stored digital video. sprite An image that is defined once and is then animated by commands that change its position or appearance. streaming Delivery of video or audio data over a network in real time, in packets instead of in a single file download. TIFF (Tagged Image File Format) A format for graphics, commonly used to transfer bitmapped images between applications. track A single data type in a QuickTime movie. A movie may contain one or more tracks. tween track A track that modifies the display of other tracks. virtual reality (VR) The effect achieved by QuickTime VR, where users can manipulate objects or environments. wav A Windows format for sound files.Index 62 Index 3G files exporting 51–53 A A/V Controls 18 animations 27 annotations 38 AppleScript 57 audio adding an audio track 33 audio controls 18, 34 B balance changing for an audio track 34 balance controls 18 bass level 18, 34 bit rate. See data rate browser playing movies in a 12 C Cache checkbox 25 chapter lists 12, 39 color changing a movie’s border 24 compressing audio and video 42–53 connection speed 14 content guide 19 converting files to QuickTime 28 copy-protected movies 17 cropping movies 31 D data rate 14, 44, 47, 50, 52 dimensions of a movie changing 20, 45 determining 35 disk cache 13 displays using more than one 23 E editing QuickTime movies 30–39 email sharing movies via 29 Empty Download Cache checkbox 13 “Enable kiosk mode” checkbox 22 Encoding Mode 53 equalizer 11, 19 exporting movies 42–53 F Fast Start 47 Favorites 17 file formats 9 filters (special effects) 45 firewalls 14 frame rate 18, 27, 44, 50, 53 full-screen mode 19 H help getting additional 10 onscreen 10 hinting 47 HomePage 29 HTTP 14 I importing files 9 Instant-On streaming 14 Internet connection speed 14 preparing movies for delivery over the 46–48 saving movies from the 27 sharing movies via the 29 J jog shuttle 18 K keyboard shortcuts 55 key frame options 44 L languages 37 Layer control 34Index 63 locked media files 17 looping 20 M media keys 17 memory options 25 MIDI 16 MIME Settings 15 Mirror Displays 23 monitors. See displays movie controller 41 Movie Download Cache Size slider 13 MPEG-4 files exporting 49–51 Multi-pass mode 53 Mute checkbox 32, 34 N new features in QuickTime 7 7 O Open Image Sequence command 27 opening files 9, 11 opening files automatically 18 opening more than one movie at a time 20 Open Recent command 17 P pass through 53 pasting items into a movie 35 playback options 13, 18, 41 playhead 11 playing movies 11 playing sound 19 “Play movies automatically” checkbox 13 poster frames 41 Preferences 18 “Preload this track” checkbox 25, 41 Preview application 16 protocols 14 Q QuickTime Player Preferences 18 QuickTime plug-in 12 QuickTime Pro defined 6 getting 23 QuickTime Streaming 47 QuickTime VR movies 15 QuickTime website 13 R recording audio and video 25 reference movies 13, 26, 27, 48 repeating a movie 20 resizing a movie 38 rotating a movie 38 RTSP 14 S “Save movies in disk cache” checkbox 13 saving a movie 27 secured media files 17 selecting part of a movie 30 self-contained movies 26 sharing movies 29 Show Movie Info command 18 Single-pass mode 53 size changing movie 20, 45 slideshow creating from still images 27 slideshows 24, 27 Solo checkbox 32, 34 special effects 45 still images converting to slideshow 27 exporting frames from a QuickTime movie 28 viewing and modifying 16 streaming 47 subtitles 22 system requirements 9 T technical support 10 text adding a text track 35 finding 22 overlaying a movie with text 36 specifying font styles 36 titles 22 tracks 32–37 adding an audio track 33 adding a text track 35 disabling 32 transparency 39 treble level 18, 34 Trim to Selection 31 V versions getting new versions of QuickTime 10 video frame changing the size of 45 video masks 39 virtual reality movies 15 volume 11, 34 adjusting during playback 12 changing sound track volume 34 W web. See Internet Event Handling Guide for iOSContents About Events in iOS 6 At a Glance 6 An Application Receives Multitouch Events When Users Touch its Views 6 An Application Receives Motion Events When Users Move the Device 7 Remote-Control Events Are Sent When Users Manipulate Multimedia Controls 7 How to Use this Book 7 See Also 8 Event Types and Delivery 9 UIKit Event Objects and Types 9 Event Delivery 11 Responder Objects and the Responder Chain 11 Motion Event Types 14 Multitouch Events 16 Events and Touches 17 Approaches for Handling Touch Events 18 Regulating Touch Event Delivery 19 Handling Multitouch Events 20 The Event-Handling Methods 20 Basics of Touch-Event Handling 21 Handling Tap Gestures 24 Handling Swipe and Drag Gestures 27 Handling a Complex Multitouch Sequence 29 Hit-Testing 33 Forwarding Touch Events 35 Handling Events in Subclasses of UIKit Views and Controls 37 Best Practices for Handling Multitouch Events 37 Gesture Recognizers 39 Gesture Recognizers Simplify Event Handling 39 Recognized Gestures 39 Gestures Recognizers Are Attached to a View 40 Gestures Trigger Action Messages 41 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 2Discrete Gestures and Continuous Gestures 41 Implementing Gesture Recognition 42 Preparing a Gesture Recognizer 43 Responding to Gestures 44 Interacting with Other Gesture Recognizers 46 Requiring a Gesture Recognizer to Fail 46 Preventing Gesture Recognizers from Analyzing Touches 47 Permitting Simultaneous Gesture Recognition 48 Regulating the Delivery of Touches to Views 48 Default Touch-Event Delivery 48 Affecting the Delivery of Touches to Views 49 Creating Custom Gesture Recognizers 50 State Transitions 50 Implementing a Custom Gesture Recognizer 52 Motion Events 56 Shaking-Motion Events 56 Getting the Current Device Orientation 58 Setting Required Hardware Capabilities for Accelerometer and Gyroscope Events 59 Accessing Accelerometer Events Using UIAccelerometer 59 Choosing an Appropriate Update Interval 61 Isolating the Gravity Component from Acceleration Data 61 Isolating Instantaneous Motion from Acceleration Data 62 Core Motion 63 Handling Accelerometer Events Using Core Motion 65 Handling Rotation-Rate Data 68 Handling Processed Device-Motion Data 72 Remote Control of Multimedia 76 Preparing Your Application for Remote-Control Events 76 Handling Remote-Control Events 77 Document Revision History 79 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 3 ContentsFigures, Tables, and Listings Event Types and Delivery 9 Figure 1-1 The responder chain in iOS 13 Listing 1-1 Event-type and event-subtype constants 9 Multitouch Events 16 Figure 2-1 A multitouch sequence and touch phases 17 Figure 2-2 Relationship of a UIEvent object and its UITouch objects 18 Figure 2-3 All touches for a given touch event 22 Figure 2-4 All touches belonging to a specific window 22 Figure 2-5 All touches belonging to a specific view 23 Listing 2-1 Detecting a double-tap gesture 24 Listing 2-2 Handling a single-tap gesture and a double-tap gesture 25 Listing 2-3 Tracking a swipe gesture in a view 27 Listing 2-4 Dragging a view using a single touch 28 Listing 2-5 Storing the beginning locations of multiple touches 30 Listing 2-6 Retrieving the initial locations of touch objects 30 Listing 2-7 Handling a complex multitouch sequence 31 Listing 2-8 Determining when the last touch in a multitouch sequence has ended 33 Listing 2-9 Calling hitTest: on a view’s CALayer object 34 Listing 2-10 Overriding hitTest:withEvent: 34 Listing 2-11 Forwarding touch events to “helper” responder objects 35 Gesture Recognizers 39 Figure 3-1 Path of touch objects when gesture recognizer is attached to a view 41 Figure 3-2 Discrete versus continuous gestures 42 Figure 3-3 Possible state transitions for gesture recognizers 51 Table 3-1 Gestures recognized by the gesture-recognizer classes of the UIKit framework 40 Listing 3-1 Creating and initializing discrete and continuous gesture recognizers 43 Listing 3-2 Handling pinch, pan, and double-tap gestures 44 Listing 3-3 Implementation of a “checkmark” gesture recognizer. 53 Listing 3-4 Resetting a gesture recognizer 55 Motion Events 56 Figure 4-1 Core Motion classes 64 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 4Figure 4-2 Right-hand rule 71 Table 4-1 Common update intervals for acceleration events 61 Listing 4-1 Becoming first responder 56 Listing 4-2 Handling a motion event 57 Listing 4-3 Configuring the accelerometer 60 Listing 4-4 Receiving an accelerometer event 60 Listing 4-5 Isolating the effects of gravity from accelerometer data 62 Listing 4-6 Getting the instantaneous portion of movement from accelerometer data 62 Listing 4-7 Configuring the motion manager and starting updates 66 Listing 4-8 Sampling and filtering accelerometer data 67 Listing 4-9 Creating the CMMotionManager object and setting up for gyroscope updates 70 Listing 4-10 Starting and stopping gyroscope updates 71 Listing 4-11 Starting and stopping device-motion updates 73 Listing 4-12 Getting the change in attitude prior to rendering 74 Remote Control of Multimedia 76 Listing 5-1 Preparing to receive remote-control events 76 Listing 5-2 Ending the receipt of remote-control events 77 Listing 5-3 Handling remote-control events 77 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 5 Figures, Tables, and ListingsEvents are objects sent to an application to inform it of user actions. In iOS, events can take many forms: multitouch events, motion events—for example, from device accelerometers—and events for controlling multimedia. (This last type of event is known as a remote-control event because it originates from a headset or other external accessory.) Multitouch events Remote-control events Accelerometer events anApp The UIKit and Core Motion frameworks are responsible for event propagation and delivery in iOS. At a Glance An Application Receives Multitouch Events When Users Touch its Views The Multi-Touch interface of iPhones, iPads, and iPod touches generates low-level events when users touch views of an application. The application sends these events (as UIEvent objects) to the view on which the touches occurred. That view typically analyzes the touches represented by each event object and responds in an appropriate manner. 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 6 About Events in iOSApplications are frequently interested in interpreting the touches a user makes as a common gesture, such as a tap or swipe gesture. These applications can make use of UIKit classes called gesture recognizers, each of which is designed to recognize a specific gesture. Relevant Chapters:: “Event Types and Delivery” (page 9), “Multitouch Events” (page 16), “Gesture Recognizers” (page 39) An Application Receives Motion Events When Users Move the Device Motion events come in different forms, and you can handle them using different frameworks. When users shake the device, the UIKit delivers a UIEvent object to an application; these shaking-motion events are gestures often used to trigger undo and redo actions. If you want your application to receive high-rate, continuous accelerometer and gyroscope data, use the Core Motion framework. (Only certain devices have a gyroscope.) You may also use the UIAccelerometer class to receive and handle accelerometer data. Relevant Chapters:: “Event Types and Delivery” (page 9), “Motion Events” (page 56) Remote-Control Events Are Sent When Users Manipulate Multimedia Controls By conforming to an Apple-provide specification, headsets and other external accessories can send (via the UIKit framework) remote-control events to an application capable of playing audio or video. The view hosting the multimedia can receive the events and thereby control the audio video according to the user’s command (for example, pausing or fast-forwarding). Relevant Chapters:: “Event Types and Delivery” (page 9), “Remote Control of Multimedia” (page 76) How to Use this Book Regardless of the type of event you’re interested in, you should first read “Event Types and Delivery” (page 9). This chapter provides essential background information. About Events in iOS How to Use this Book 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 7See Also Some iPhones and other devices have GPS and compass hardware that also generate low-level data delivered to an application for processing. Location Awareness Programming Guide discusses how to receive and handle this data. Many sample code projects in the iOS Reference Library have code that illustrates the handling of multitouch events and the use of gesture recognizers. Among these are the following projects: Touches, CopyPasteTile , and SimpleGestureRecognizers. About Events in iOS See Also 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 8An iPhone, iPad, or iPod touch device has multiple items of hardware that generate streams of input data an application can access. The Multi-Touch technology enables the direct manipulation of views, including the virtual keyboard. Three accelerometers measure acceleration along the three spatial axes. A gyroscope (only on some device models) measures the rate of rotation around the three axes. The Global Positioning System (GPS) and compass provide measurements of location and orientation. Each of these hardware systems, as they detect touches, device movements, and location changes, produce raw data that is passed to system frameworks. The frameworks package the data and deliver them as events to an application for processing. The following sections identify these frameworks and describe how events are packaged and delivered to applications for handling. Note: This document describes touch events, motion events, and remote control events only. For information on handling GPS and magnetometer (compass) data, see Location Awareness Programming Guide . UIKit Event Objects and Types An event is an object that represents a user action detected by hardware on the device and conveyed to iOS—for example, a finger touching the screen or hand shaking the device. Many events are instances of the UIEvent class of the UIKit framework. A UIEvent object may encapsulate state related to the user event,such asthe associated touches. It also recordsthe moment the event was generated. As a user action takes place—for example, as fingers touch the screen and move across its surface—the operating system continually sends event objects to an application for handling. UIKit currently recognizes three types of events: touch events, “shaking” motion events, and remote-control events. The UIEvent class declares the enum constants shown in Listing 1-1. Listing 1-1 Event-type and event-subtype constants typedef enum { UIEventTypeTouches, UIEventTypeMotion, 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 9 Event Types and DeliveryUIEventTypeRemoteControl, } UIEventType; typedef enum { UIEventSubtypeNone = 0, UIEventSubtypeMotionShake = 1, UIEventSubtypeRemoteControlPlay = 100, UIEventSubtypeRemoteControlPause = 101, UIEventSubtypeRemoteControlStop = 102, UIEventSubtypeRemoteControlTogglePlayPause = 103, UIEventSubtypeRemoteControlNextTrack = 104, UIEventSubtypeRemoteControlPreviousTrack = 105, UIEventSubtypeRemoteControlBeginSeekingBackward = 106, UIEventSubtypeRemoteControlEndSeekingBackward = 107, UIEventSubtypeRemoteControlBeginSeekingForward = 108, UIEventSubtypeRemoteControlEndSeekingForward = 109, } UIEventSubtype; Each event has one of these event type and subtype constants associated with it, which you can accessthrough the type and subtype properties of UIEvent. The event type includes touch events, motion events, and remote control events. In iOS 3.0, there is a shake-motion subtype (UIEventSubtypeMotionShake) and many remote-control subtypes; touch events always have a subtype of UIEventSubtypeNone. A remote-control event originates as commands from the system transport controls or an external accessory conforming to an Apple-provided specification, such as a headset. They are intended to allow users to control multimedia content using those controls and external accessories. Remote-control events are new with iOS 4.0 and are described in detail in “Remote Control of Multimedia” (page 76). You should never retain a UIEvent object in your code. If you need to preserve the current state of an event object for later evaluation, you should copy and store those bits of state in an appropriate manner (using an instance variable or a dictionary object, for example). A device running iOS can send other types of events, broadly considered, to an application for handling. These events are not UIEvent objects, but still encapsulate a measurement of some hardware-generated values. “Motion Event Types” (page 14) discusses these other events. Event Types and Delivery UIKit Event Objects and Types 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 10Event Delivery The delivery of an event to an object for handling occurs along a specific path. As described in “Preparing Your Application for Remote-Control Events” (page 76), when users touch the screen of a device, iOS recognizes the set of touches and packages them in a UIEvent object that it places in the active application’s event queue. If the system interprets the shaking of the device as a motion event, an event object representing that event is also placed in the application’s event queue. The singleton UIApplication object managing the application takes an event from the top of the queue and dispatches it for handling. Typically, it sends the event to the application’s key window—the window currently the focusfor user events—and the window object representing that window sends the event to an initial object for handling. That object is different for touch events and motion events. ● Touch events. The window object uses hit-testing and the responder chain to find the view to receive the touch event. In hit-testing, a window calls hitTest:withEvent: on the top-most view of the view hierarchy; this method proceeds by recursively calling pointInside:withEvent: on each view in the view hierarchy that returns YES, proceeding down the hierarchy until it finds the subview within whose bounds the touch took place. That view becomes the hit-test view. If the hit-test view cannot handle the event, the event travels up the responder chain as described in “Responder Objects and the Responder Chain” (page 11) until the system finds a view that can handle it. A touch object (described in “Events and Touches” (page 17)) is associated with its hit-test view for its lifetime, even if the touch represented by the object subsequently moves outside the view. “Hit-Testing” (page 33) discusses some of the programmatic implications of hit-testing. ● Motion and remote-control events. The window object sends each shaking-motion or remote-control event to the first responder for handling. (The first responder is described in “Responder Objects and the Responder Chain.” Although the hit-test view and the first responder are often the same view object, they do not have to be the same. The UIApplication object and each UIWindow object dispatches eventsin the sendEvent: method. (These classes declare a method with the same signature). Because these methods are funnel pointsfor events coming into an application, you can subclass UIApplication or UIWindow and override the sendEvent: method to monitor events (which is something few applications would need to do). If you override these methods, be sure to call the superclass implementation (that is, [super sendEvent:theEvent]); never tamper with the distribution of events. Responder Objects and the Responder Chain The preceding discussion mentions the concept of responders. What is a responder object and how does it fit into the architecture for event delivery? Event Types and Delivery Event Delivery 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 11A responder object is an object that can respond to events and handle them. UIResponder is the base class for all responder objects, also known as, simply, responders. It defines the programmatic interface not only for event handling but for common responder behavior. UIApplication, UIView, and all UIKit classes that descend from UIView (including UIWindow) inherit directly or indirectly from UIResponder, and thus their instances are responder objects. The first responder is the responder object in an application (usually a UIView object) that is designated to be the first recipient of events other than touch events. A UIWindow object sends the first responder these events in messages, giving it the first shot at handling them. To receive these messages, the responder object must implement canBecomeFirstResponder to return YES; it must also receive a becomeFirstResponder message (which it can invoke on itself). The first responder isthe first view in a window to receive the following type of events and messages: ● Motion events—via calls to the UIResponder motion-handling methods described in “Shaking-Motion Events” (page 56) ● Remote-control events—via calls to the UIResponder method remoteControlReceivedWithEvent: ● Action messages—sent when the user manipulates a control (such as a button or slider) and no target is specified for the action message ● Editing-menu messages—sent when userstap the commands of the editing menu (described in “Displaying and Managing the Edit Menu”) The first responder also plays a role in text editing. A text view or text field that is the focus of editing is made the first responder, which causes the virtual keyboard to appear. Note: Applications must explicitly set a first responder to handle motion events, action messages, and editing-menu messages; UIKit automatically sets the text field or text view a user taps to be the first responder. If the first responder or the hit-test view doesn’t handle an event, UIKit may pass the event (via message) to the next responder in the responder chain to see if it can handle it. The responder chain is a linked series of responder objects along which an event, action message, or editing-menu message is passed. It allows responder objects to transfer responsibility for handling an event to other, higher-level objects. An event proceeds up the responder chain as the application looks for an object Event Types and Delivery Event Delivery 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 12capable of handling the event. Because the hit-test view is also a responder object, an application may also take advantage of the responder chain when handing touch events. The responder chain consists of a series of next responders (each returned by the nextResponder method) in the sequence depicted in Figure 1-1. Figure 1-1 The responder chain in iOS superview window View View View UIApplication View controller Window superview When the system delivers a touch event, it first sends it to a specific view. For touch events, that view is the one returned by hitTest:withEvent:; for “shaking”-motion events, remote-control events, action messages, and editing-menu messages, that view is the first responder. If the initial view doesn’t handle the event, it travels up the responder chain along a particular path: 1. The hit-test view or first responder passes the event or message to its view controller if it has one; if the view doesn’t have a view controller, it passes the event or message to its superview. 2. If a view or its view controller cannot handle the event or message, it passes it to the superview of the view. 3. Each subsequentsuperview in the hierarchy followsthe pattern described in the first two stepsif it cannot handle the event or message. 4. The topmost view in the view hierarchy, if it doesn’t handle the event or message, passes it to the window object for handling. 5. The UIWindow object, if it doesn’t handle the event or message, passesit to the singleton application object. If the application object cannot handle the event or message, it discards it. If you implement a custom view to handle “shaking”-motion events, remote-control events, action messages, or editing-menu messages, you should not forward the event or message to nextResponder directly to send it up the responder chain. Instead invoke the superclass implementation of the current event-handling method—let UIKit handle the traversal of the responder chain. Event Types and Delivery Event Delivery 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 13Motion Event Types Motion events come from two hardware sources on a device: the three accelerometers and the gyroscope, which is available only some devices. An accelerometer measures changes in velocity over time along a given linear path. The combination of accelerometers lets you detect movement of the device in any direction. You can use this data to track both sudden movements in the device and the device’s current orientation relative to gravity. A gyroscope measures the rate of rotation around each of the three axes. (Although there are three accelerometers, one for each axis, the remainder of this document refers to them as a single entity.) The Core Motion framework is primarily responsible for accessing raw accelerometer and gyroscope data and feeding that data to an application for handling. In addition, Core Motion processes combined accelerometer and gyroscope data using special algorithms and presents that refined motion data to applications. Motion eventsfrom Core Motion are represented by three data objects, each encapsulating one or more measurements: ● A CMAccelerometerData object encapsulates a structure that captures the acceleration along each of the spatial axes. ● A CMGyroData object encapsulates a structure that captures the rate of rotation around each of the three spatial axes. ● A CMDeviceMotion object encapsulates several different measurements, including attitude and more useful measurements of rotation rate and acceleration. Core Motion is apart from UIKit architectures and conventions. There is no connection with the UIEvent model and there is no notion of first responder or responder chain. It delivers motion events directly to applications that request them. The CMMotionManager class is the central access point for Core Motion. You create an instance of the class, specify an update interval (either explicitly or implicitly), request that updates start, and handle the motion events as they are delivered. “Core Motion” (page 63) describes this procedure in full detail. An alternative to Core Motion, at least for accessing accelerometer data, is the UIAccelerometer class of the UIKit framework. When you use this class, accelerometer events are delivered as UIAcceleration objects. Although UIAccelerometer is part of UIKit, it is also separate from the UIEvent and responder-chain architectures. See “Accessing Accelerometer Events Using UIAccelerometer” (page 59) for information on using the UIKit facilities. Event Types and Delivery Motion Event Types 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 14Notes: The UIAccelerometer and UIAcceleration classes will be deprecated in a future release, so if your application handles accelerometer events, it should transition to the Core Motion API. In iOS 3.0 and later, if you are trying to detect specific types of motion as gestures—specifically shaking motions—you should consider handling motion events (UIEventTypeMotion) instead of using the accelerometer interfaces. If you want to receive and handle high-rate, continuous motion data, you should instead use the Core Motion accelerometer API. Motion events are described in “Shaking-Motion Events” (page 56). Event Types and Delivery Motion Event Types 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 15Note: This chapter contains information that used to be in iOS App Programming Guide . The information in this chapter has not been updated specifically for iOS 4.0. Touch events in iOS are based on a Multi-Touch model. Instead of using a mouse and a keyboard, users touch the screen of the device to manipulate objects, enter data, and otherwise convey their intentions. iOS recognizes one or more fingers touching the screen as part of a multitouch sequence . This sequence begins when the first finger touches down on the screen and ends when the last finger is lifted from the screen. iOS tracks fingers touching the screen throughout a multitouch sequence and records the characteristics of each of them, including the location of the finger on the screen and the time the touch occurred. Applications often recognize certain combinations of touches as gestures and respond to them in ways that are intuitive to users, such as zooming in on content in response to a pinching gesture and scrolling through content in response to a flicking gesture. Notes: A finger on the screen affords a much different level of precision than a mouse pointer. When a user touches the screen, the area of contact is actually elliptical and tends to be offset below the point where the user thinks he or she touched. This “contact patch” also varies in size and shape based on which finger is touching the screen, the size of the finger, the pressure of the finger on the screen, the orientation of the finger, and other factors. The underlying Multi-Touch system analyzes all of this information for you and computes a single touch point. iOS 4.0 still reports touches on iPhone 4 (and on future high-resolution devices) in a 320x480 coordinate space to maintain source compatibility, but the resolution is twice as high in each dimension for applications built for iOS 4.0 and later releases. In concrete terms, that means that touchesfor applications built for iOS 4 running on iPhone 4 can land on half-point boundaries where on older devices they land only on full point boundaries. If you have any round-to-integer code in your touch-handling path you may lose this precision. Many classes in UIKit handle multitouch events in ways that are distinctive to objects of the class. This is especially true of subclasses of UIControl, such as UIButton and UISlider. Objects of these subclasses—known as control objects—are receptive to certain types of gestures, such as a tap or a drag in a certain direction; when properly configured, they send an action message to a target object when that gesture occurs. Other UIKit classes handle gestures in other contexts; for example, UIScrollView provides scrolling behavior for table views, text views, and other views with large content areas. 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 16 Multitouch EventsSome applications may not need to handle events directly; instead, they can rely on the classes of UIKit for that behavior. However, if you create a custom subclass of UIView—a common pattern in iOS development—and if you want that view to respond to certain touch events, you need to implement the code required to handle those events. Moreover, if you want a UIKit object to respond to events differently, you have to create a subclass of that framework class and override the appropriate event-handling methods. Events and Touches In iOS, a touch is the presence or movement of a finger on the screen that is part of a unique multitouch sequence. For example, a pinch-close gesture has two touches: two fingers on the screen moving toward each other from opposite directions. There are simple single-finger gestures, such as a tap, or a double-tap, a drag, or a flick (where the user quickly swipes a finger across the screen). An application might recognize even more complicated gestures; for example, an application might have a custom control in the shape of a dial that users “turn” with multiple fingers to fine-tune some variable. A UIEvent object of type UIEventTypeTouches represents a touch event. The system continually sends these touch-event objects (or simply, touch events) to an application as fingers touch the screen and move acrossitssurface. The event provides a snapshot of all touches during a multitouch sequence, most importantly the touchesthat are new or have changed for a particular view. As depicted in Figure 2-1, a multitouch sequence begins when a finger first touches the screen. Other fingers may subsequently touch the screen, and all fingers may move across the screen. The sequence ends when the last of these fingers is lifted from the screen. An application receives event objects during each phase of any touch. Figure 2-1 A multitouch sequence and touch phases UITouchPhaseBegan UITouchPhaseEnded Touch 1 down UITouchPhaseBegan Touch 2 down UITouchPhaseMoved Touch 1 and 2 moved Touch 1 and 2 up Touches, which are represented by UITouch objects, have both temporal and spatial aspects. The temporal aspect, called a phase, indicates when a touch has just begun, whether it is moving or stationary, and when it ends—that is, when the finger is lifted from the screen. Multitouch Events Events and Touches 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 17The spatial aspect of touches concerns their association with the object in which they occur as well as their location in it. When a finger touches the screen, the touch is associated with the underlying window and view and maintains that association throughout the life of the event. If multiple touches arrive at once, they are treated together only if they are associated with the same view. Likewise, if two touches arrive in quick succession, they are treated as a multiple tap only if they are associated with the same view. A touch object stores the current location and previous location (if any) of the touch in its view or window. An event object contains all touch objects for the current multitouch sequence and can provide touch objects specific to a view or window (see Figure 2-2). A touch object is persistent for a given finger during a sequence, and UIKit mutates it as it tracks the finger throughout it. The touch attributes that change are the phase of the touch, its location in a view, its previous location, and its timestamp. Event-handling code may evaluate these attributes to determine how to respond to a touch event. Figure 2-2 Relationship of a UIEvent object and its UITouch objects UIEvent UITouch phase = UITouchPhaseBegan locationInView = (35,50) view = ViewA phase = UITouchPhaseMoved locationInView = (35,20) view = ViewA UITouch phase = UITouchPhaseEnded locationInView = (120,87) view = ViewB UITouch Because the system can cancel a multitouch sequence at any time, an event-handling application must be prepared to respond appropriately. Cancellations can occur as a result of overriding system events, such as an incoming phone call. Approaches for Handling Touch Events Most applications that are interested in users’ touches on their custom views are interested in detecting and handling well-established gestures. These gestures include tapping (one or multiple times), pinching (to zoom a view in or out), swiping , panning or dragging a view, and using two fingers to rotate a view. You could implement the touch-event handling code to recognize and handle these gestures, but that code would be complex, possibly buggy, and take some time to write. Alternatively, you could simplify the interpretation and handling of common gestures by using one of the gesture recognizer classes introduced in iOS 3.2. To use a gesture recognizer, you instantiate it, attach it to the view receiving touches, configure it, and assign it an action selector and a target object. When the gesture recognizer recognizes its gesture, it sends an action message to the target, allowing the target to respond to the gesture. Multitouch Events Approaches for Handling Touch Events 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 18You can implement a custom gesture recognizer by subclassing UIGestureRecognizer. A custom gesture recognizer requires you to analyze the stream of events in a multitouch sequence to recognize your distinct gesture; to do this, you should be familiar with the information in this chapter. For information about gesture recognizers, see “Gesture Recognizers” (page 39). Regulating Touch Event Delivery UIKit gives applications programmatic means to simplify event handling or to turn off the stream of UIEvent objects completely. The following list summarizes these approaches: ● Turning off delivery of touch events. By default, a view receives touch events, but you can set its userInteractionEnabled property to NO to turn off delivery of touch events. A view also does not receive these events if it’s hidden or if it’s transparent. ● Turning off delivery of touch events for a period. An application can call the UIApplication method beginIgnoringInteractionEvents and later call the endIgnoringInteractionEvents method. The first method stops the application from receiving touch events entirely; the second method is called to resume the receipt of such events. You sometimes want to turn off event delivery while your code is performing animations. ● Turning on delivery of multiple touches. By default, a view ignores all but the first touch during a multitouch sequence. If you want the view to handle multiple touches you must enable this capability for the view. You do this programmatically by setting the multipleTouchEnabled property of your view to YES, or in Interface Builder by setting the related attribute in the inspector for the related view. ● Restricting event delivery to a single view. By default, a view’s exclusiveTouch property is set to NO, which means that this view does not block other views in a window from receiving touches. If you set the property to YES, you mark the view so that, if it is tracking touches, it is the only view in the window that is tracking touches. Other views in the window cannot receive those touches. However, a view that is marked “exclusive touch” does not receive touches that are associated with other views in the same window. If a finger contacts an exclusive-touch view, then that touch is delivered only if that view is the only view tracking a finger in that window. If a finger touches a non-exclusive view, then that touch is delivered only if there is not another finger tracking in an exclusive-touch view. ● Restricting event delivery to subviews. A custom UIView class can override hitTest:withEvent: to restrict the delivery of multitouch events to its subviews. See “Hit-Testing” (page 33) for a discussion of this technique. Multitouch Events Regulating Touch Event Delivery 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 19Handling Multitouch Events To handle multitouch events, you must first create a subclass of a responder class. This subclass could be any one of the following: ● A custom view (subclass of UIView) ● A subclass of UIViewController or one of its UIKit subclasses ● A subclass of a UIKit view or control class, such as UIImageView or UISlider ● A subclass of UIApplication or UIWindow (although this would be rare) A view controller typically receives, via the responder chain, touch events initially sent to its view if that view does not override the touch-handling methods. For instances of your subclass to receive multitouch events, your subclass must implement one or more of the UIResponder methods for touch-event handling, described below. In addition, the view must be visible (neither transparent or hidden) and must have its userInteractionEnabled property set to YES, which is the default. The following sections describe the touch-event handling methods, describe approachesfor handling common gestures, show an example of a responder object that handles a complex sequence of multitouch events, discuss event forwarding, and suggest some techniques for event handling. The Event-Handling Methods During a multitouch sequence, the application dispatches a series of event messages to the target responder. To receive and handle these messages, the class of a responder object must implement at least one of the following methods declared by UIResponder, and, in some cases, all of these methods: - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event; - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event; - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event; - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event The application sends these messages when there are new or changed touches for a given touch phase: ● Itsendsthe touchesBegan:withEvent: message when one or more fingerstouch down on the screen. ● It sends the touchesMoved:withEvent: message when one or more fingers move. ● It sends the touchesEnded:withEvent: message when one or more fingers lift up from the screen. Multitouch Events Handling Multitouch Events 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 20● It sends the touchesCancelled:withEvent: message when the touch sequence is cancelled by a system event, such as an incoming phone call. Each of these methodsis associated with a touch phase; for example, touchesBegan:withEvent: is associated with UITouchPhaseBegan. You can get the phase of any UITouch object by evaluating its phase property. Each message that invokes an event-handling method passes in two parameters. The first is a set of UITouch objectsthat represent new or changed touchesfor the given phase. The second parameter is a UIEvent object representing this particular event. From the event object you can get all touch objectsfor the event or a subset of those touch objects filtered for specific views or windows. Some of these touch objects represent touches that have not changed since the previous event message or that have changed but are in different phases. Basics of Touch-Event Handling You frequently handle an event for a given phase by getting one or more of the UITouch objects in the passed-in set, evaluating their properties or getting their locations, and proceeding accordingly. The objects in the set represent those touchesthat are new or have changed for the phase represented by the implemented event-handling method. If any of the touch objects will do, you can send the NSSet object an anyObject message; this is the case when the view receives only the first touch in a multitouch sequence (that is, the multipleTouchEnabled property is set to NO). An important UITouch method is locationInView:, which, if passed a parameter of self, yieldsthe location of the touch in the coordinate system of the receiving view. A parallel method tells you the previous location of the touch (previousLocationInView:). Properties of the UITouch instance tell you how many taps have been made (tapCount), when the touch was created or last mutated (timestamp), and what phase it is in (phase). Multitouch Events Handling Multitouch Events 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 21If for some reason you are interested in touches in the current multitouch sequence that have not changed since the last phase or that are in a phase other than the ones in the passed-in set, you can request them from the passed-in UIEvent object. The diagram in Figure 2-3 depicts a UIEvent object that contains four touch objects. To get all these touch objects, you would invoke the allTouches on the event object. Figure 2-3 All touches for a given touch event Window B Window A UIEvent UITouch UITouch UITouch UITouch View C View A View B If on the other hand you are interested in only those touches associated with a specific window (Window A in Figure 2-4), you would send the UIEvent object a touchesForWindow: message. Figure 2-4 All touches belonging to a specific window Window B Window A UIEvent UITouch UITouch UITouch UITouch View C View A View B Multitouch Events Handling Multitouch Events 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 22If you want to get the touches associated with a specific view, you would call touchesForView: on the event object, passing in the view object (View A in Figure 2-5). Figure 2-5 All touches belonging to a specific view Window B Window A UIEvent UITouch UITouch UITouch UITouch View C View A View B If a responder creates persistent objects while handling events during a multitouch sequence, it should implement touchesCancelled:withEvent: to dispose ofthose objects when the system cancelsthe sequence. Cancellation often occurs when an external event—for example, an incoming phone call—disruptsthe current application’s event processing. Note that a responder object should also dispose of those same objects when it receivesthe last touchesEnded:withEvent: message for a multitouch sequence. (See “Forwarding Touch Events” (page 35) to find out how to determine the last UITouchPhaseEnded touch object in a multitouch sequence.) Multitouch Events Handling Multitouch Events 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 23Important: If your custom responder class is a subclass of UIView or UIViewController, you should implement all of the methods described in “The Event-Handling Methods” (page 20). If your class is a subclass of any other UIKit responder class, you do not need to override all of the event-handling methods; however, in those methods that you do override, be sure to call the superclass implementation of the method (for example, super touchesBegan:touches withEvent:theEvent];). The reason for this guideline issimple: All viewsthat processtouches, including your own, expect (orshould expect) to receive a full touch-eventstream. If you prevent a UIKit responder object from receiving touchesfor a certain phase of an event, the resulting behavior may be undefined and probably undesirable. Handling Tap Gestures A very common gesture in iOS applications is the tap: the user taps an object on the screen with his or her finger. A responder object can handle a single tap in one way, a double-tap in another, and possibly a triple-tap in yet another way. To determine the number of times the user tapped a responder object, you get the value of the tapCount property of a UITouch object. The best places to find this value are the methods touchesBegan:withEvent: and touchesEnded:withEvent:. In many cases, the latter method is preferred because it corresponds to the touch phase in which the user lifts a finger from a tap. By looking for the tap count in the touch-up phase (UITouchPhaseEnded), you ensure that the finger is really tapping and not, for instance, touching down and then dragging. Listing 2-1 shows how to determine whether a double-tap occurred in one of your views. Listing 2-1 Detecting a double-tap gesture - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { for (UITouch *touch in touches) { if (touch.tapCount >= 2) { [self.superview bringSubviewToFront:self]; } } Multitouch Events Handling Multitouch Events 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 24} - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { } A complication arises when a responder object wants to handle a single-tap and a double-tap gesture in different ways. For example, a single tap might select the object and a double tap might display a view for editing the item that was double-tapped. How is the responder object to know that a single tap is not the first part of a double tap? Listing 2-2 (page 25) illustrates an implementation of the event-handling methods that increases the size of the receiving view upon a double-tap gesture and decreases it upon a single-tap gesture. The following is a commentary on this code: 1. In touchesEnded:withEvent:, when the tap count is one, the responder object sends itself a performSelector:withObject:afterDelay: message. The selector identifies another method implemented by the responder to handle the single-tap gesture; the second parameter is an NSValue or NSDictionary object that holdssome state of the UITouch object; the delay issome reasonable interval between a single- and a double-tap gesture. Note: Because a touch object is mutated as it proceeds through a multitouch sequence, you cannot retain a touch and assume that itsstate remainsthe same. (And you cannot copy a touch object because UITouch does not adopt the NSCopying protocol.) Thusif you want to preserve the state of a touch object, you should store those bits ofstate in a NSValue object, a dictionary, or a similar object. (The code in Listing 2-2 stores the location of the touch in a dictionary but does not use it; this code is included for purposes of illustration.) 2. In touchesBegan:withEvent:, if the tap count is two, the responder object cancels the pending delayed-perform invocation by calling the cancelPreviousPerformRequestsWithTarget: method of NSObject, passing itself as the argument. If the tap count is not two, the method identified by the selector in the previous step for single-tap gestures is invoked after the delay. 3. In touchesEnded:withEvent:, if the tap count is two, the responder performs the actions necessary for handling double-tap gestures. Listing 2-2 Handling a single-tap gesture and a double-tap gesture - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *aTouch = [touches anyObject]; if (aTouch.tapCount == 2) { Multitouch Events Handling Multitouch Events 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 25[NSObject cancelPreviousPerformRequestsWithTarget:self]; } } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *theTouch = [touches anyObject]; if (theTouch.tapCount == 1) { NSDictionary *touchLoc = [NSDictionary dictionaryWithObject: [NSValue valueWithCGPoint:[theTouch locationInView:self]] forKey:@"location"]; [self performSelector:@selector(handleSingleTap:) withObject:touchLoc afterDelay:0.3]; } else if (theTouch.tapCount == 2) { // Double-tap: increase image size by 10%" CGRect myFrame = self.frame; myFrame.size.width += self.frame.size.width * 0.1; myFrame.size.height += self.frame.size.height * 0.1; myFrame.origin.x -= (self.frame.origin.x * 0.1) / 2.0; myFrame.origin.y -= (self.frame.origin.y * 0.1) / 2.0; [UIView beginAnimations:nil context:NULL]; [self setFrame:myFrame]; [UIView commitAnimations]; } } - (void)handleSingleTap:(NSDictionary *)touches { // Single-tap: decrease image size by 10%" CGRect myFrame = self.frame; myFrame.size.width -= self.frame.size.width * 0.1; myFrame.size.height -= self.frame.size.height * 0.1; myFrame.origin.x += (self.frame.origin.x * 0.1) / 2.0; myFrame.origin.y += (self.frame.origin.y * 0.1) / 2.0; Multitouch Events Handling Multitouch Events 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 26[UIView beginAnimations:nil context:NULL]; [self setFrame:myFrame]; [UIView commitAnimations]; } - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { /* no state to clean up, so null implementation */ } Handling Swipe and Drag Gestures Horizontal and vertical swipes are a simple type of gesture that you can track easily from your own code and use to perform actions. To detect a swipe gesture, you have to track the movement of the user’s finger along the desired axis of motion, but it is up to you to determine what constitutes a swipe. In other words, you need to determine whether the user’s finger moved far enough, if it moved in a straight enough line, and if it went fast enough. You do that by storing the initial touch location and comparing it to the location reported by subsequent touch-moved events. Listing 2-3 shows some basic tracking methods you could use to detect horizontal swipes in a view. In this example, the view stores the initial location of the touch in a startTouchPosition instance variable. As the user’sfinger moves, the code comparesthe current touch location to the starting location to determine whether it is a swipe. If the touch moves too far vertically, it is not considered to be a swipe and is processed differently. If it continues along its horizontal trajectory, however, the code continues processing the event as if it were a swipe. The processing routines could then trigger an action once the swipe had progressed far enough horizontally to be considered a complete gesture. To detect swipe gestures in the vertical direction, you would use similar code but would swap the x and y components. Listing 2-3 Tracking a swipe gesture in a view #define HORIZ_SWIPE_DRAG_MIN 12 #define VERT_SWIPE_DRAG_MAX 4 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; // startTouchPosition is an instance variable startTouchPosition = [touch locationInView:self]; } Multitouch Events Handling Multitouch Events 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 27- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; CGPoint currentTouchPosition = [touch locationInView:self]; // To be a swipe, direction of touch must be horizontal and long enough. if (fabsf(startTouchPosition.x - currentTouchPosition.x) >= HORIZ_SWIPE_DRAG_MIN && fabsf(startTouchPosition.y - currentTouchPosition.y) <= VERT_SWIPE_DRAG_MAX) { // It appears to be a swipe. if (startTouchPosition.x < currentTouchPosition.x) [self myProcessRightSwipe:touches withEvent:event]; else [self myProcessLeftSwipe:touches withEvent:event]; } } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { startTouchPosition = CGPointZero; } - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { startTouchPosition = CGPointZero; } Listing 2-4 shows an even simpler implementation of tracking a single touch, but this time for the purposes of dragging the receiving view around the screen. In this instance, the responder class fully implements only the touchesMoved:withEvent: method, and in this method computes a delta value between the touch's current location in the view and its previouslocation in the view. It then usesthis delta value to reset the origin of the view’s frame. Listing 2-4 Dragging a view using a single touch - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { } Multitouch Events Handling Multitouch Events 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 28- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *aTouch = [touches anyObject]; CGPoint loc = [aTouch locationInView:self]; CGPoint prevloc = [aTouch previousLocationInView:self]; CGRect myFrame = self.frame; float deltaX = loc.x - prevloc.x; float deltaY = loc.y - prevloc.y; myFrame.origin.x += deltaX; myFrame.origin.y += deltaY; [self setFrame:myFrame]; } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { } - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { } Handling a Complex Multitouch Sequence Taps, drags, and swipes are simple gestures, typically involving only a single touch. Handling a touch event consisting of two or more touches is a more complicated affair. You may have to track all touches through all phases, recording the touch attributes that have changed and altering internal state appropriately. There are a couple of things you should do when tracking and handling multiple touches: ● Set the multipleTouchEnabled property of the view to YES. ● Use a Core Foundation dictionary object (CFDictionaryRef) to track the mutations of touches through their phases during the event. When handling an event with multiple touches, you often store initial bits of each touch’s state for later comparison with the mutated UITouch instance. As an example, say you want to compare the final location of each touch with its original location. In the touchesBegan:withEvent: method, you can obtain the original location of each touch from the locationInView: method and store those in a CFDictionaryRef object using the addresses of the UITouch objects as keys. Then, in the touchesEnded:withEvent: method you can use the address of each passed-in UITouch object to obtain the object’s original location and compare Multitouch Events Handling Multitouch Events 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 29that with its current location. (You should use a CFDictionaryRef type rather than an NSDictionary object; the latter copies its keys, but the UITouch class does not adopt the NSCopying protocol, which is required for object copying.) Listing 2-5 illustrates how you might store beginning locations of UITouch objects in a Core Foundation dictionary. Listing 2-5 Storing the beginning locations of multiple touches - (void)cacheBeginPointForTouches:(NSSet *)touches { if ([touches count] > 0) { for (UITouch *touch in touches) { CGPoint *point = (CGPoint *)CFDictionaryGetValue(touchBeginPoints, touch); if (point == NULL) { point = (CGPoint *)malloc(sizeof(CGPoint)); CFDictionarySetValue(touchBeginPoints, touch, point); } *point = [touch locationInView:view.superview]; } } } Listing 2-6 illustrates how to retrieve those initial locations stored in the dictionary. It also gets the current locations of the same touches. It uses these values in computing an affine transformation (not shown). Listing 2-6 Retrieving the initial locations of touch objects - (CGAffineTransform)incrementalTransformWithTouches:(NSSet *)touches { NSArray *sortedTouches = [[touches allObjects] sortedArrayUsingSelector:@selector(compareAddress:)]; // other code here ... UITouch *touch1 = [sortedTouches objectAtIndex:0]; UITouch *touch2 = [sortedTouches objectAtIndex:1]; Multitouch Events Handling Multitouch Events 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 30CGPoint beginPoint1 = *(CGPoint *)CFDictionaryGetValue(touchBeginPoints, touch1); CGPoint currentPoint1 = [touch1 locationInView:view.superview]; CGPoint beginPoint2 = *(CGPoint *)CFDictionaryGetValue(touchBeginPoints, touch2); CGPoint currentPoint2 = [touch2 locationInView:view.superview]; // compute the affine transform... } Although the code example in Listing 2-7 doesn’t use a dictionary to track touch mutations, it also handles multiple touches during an event. It shows a custom UIView object responding to touches by animating the movement of a “Welcome” placard around the screen as a finger moves it and changing the language of the welcome when the user makes a double-tap gesture. (The code in this example comes from the MoveMe sample code project, which you can examine to get a better understanding of the event-handling context.) Listing 2-7 Handling a complex multitouch sequence - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [[event allTouches] anyObject]; // Only move the placard view if the touch was in the placard view if ([touch view] != placardView) { // On double tap outside placard view, update placard's display string if ([touch tapCount] == 2) { [placardView setupNextDisplayString]; } return; } // "Pulse" the placard view by scaling up then down // Use UIView's built-in animation [UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:0.5]; CGAffineTransform transform = CGAffineTransformMakeScale(1.2, 1.2); placardView.transform = transform; [UIView commitAnimations]; [UIView beginAnimations:nil context:NULL]; Multitouch Events Handling Multitouch Events 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 31[UIView setAnimationDuration:0.5]; transform = CGAffineTransformMakeScale(1.1, 1.1); placardView.transform = transform; [UIView commitAnimations]; // Move the placardView to under the touch [UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:0.25]; placardView.center = [self convertPoint:[touch locationInView:self] fromView:placardView]; [UIView commitAnimations]; } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [[event allTouches] anyObject]; // If the touch was in the placardView, move the placardView to its location if ([touch view] == placardView) { CGPoint location = [touch locationInView:self]; location = [self convertPoint:location fromView:placardView]; placardView.center = location; return; } } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [[event allTouches] anyObject]; // If the touch was in the placardView, bounce it back to the center if ([touch view] == placardView) { // Disable user interaction so subsequent touches don't interfere with animation self.userInteractionEnabled = NO; [self animatePlacardViewToCenter]; return; } } Multitouch Events Handling Multitouch Events 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 32Note: Custom views that redraw themselves in response to events they handle generally should only set drawing state in the event-handling methods and perform all of the drawing in the drawRect: method. To learn more about drawing view content, see View Programming Guide for iOS . To find out when the last finger in a multitouch sequence islifted from a view, compare the number of UITouch objects in the passed-in set with the number of touches for the view maintained by the passed-in UIEvent object. If they are the same, then the multitouch sequence has concluded. Listing 2-8 illustrates how to do this in code. Listing 2-8 Determining when the last touch in a multitouch sequence has ended - (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event { if ([touches count] == [[event touchesForView:self] count]) { // last finger has lifted.... } } Remember that the passed-in set contains all touch objects associated with the receiving view that are new or changed for the given phase whereas the touch objects returned from touchesForView: includes all objects associated with the specified view. Hit-Testing Your custom responder can use hit-testing to find the subview or sublayer of itself that is "under” a touch, and then handle the event appropriately. It does this by either calling the hitTest:withEvent: method of UIView or the hitTest: method of CALayer; or it can override one of these methods. Responderssometimes perform hit-testing prior to event forwarding (see “Forwarding Touch Events” (page 35)). Note: The hitTest:withEvent: and hitTest: methods have some slightly different behaviors. If the point passed into hitTest:withEvent: or hitTest: is outside the bounds of the view, it is ignored. This means that subviews that are outside their superview do not receive touch events. If you have a custom view with subviews, you need to determine whether you want to handle touches at the subview level or the superview level. If the subviews do not handle touches by implementing touchesBegan:withEvent:, touchesEnded:withEvent:, or touchesMoved:withEvent:, then these messages propagate up the responder chain to the superview. However, because multiple taps and multiple Multitouch Events Handling Multitouch Events 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 33touches are associated with the subviews where they first occurred, the superview won’t receive these touches. To ensure reception of all kinds of touches, the superview should override hitTest:withEvent: to return itself rather than any of its subviews. The example in Listing 2-9 detects when an “Info” image in a layer of the custom view is tapped. Listing 2-9 Calling hitTest: on a view’s CALayer object - (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event { CGPoint location = [[touches anyObject] locationInView:self]; CALayer *hitLayer = [[self layer] hitTest:[self convertPoint:location fromView:nil]]; if (hitLayer == infoImage) { [self displayInfo]; } } In Listing 2-10, a responder subclass (in this case, a subclass of UIWindow) overrides hitTest:withEvent:. It first gets the hit-test view returned by the superclass. Then, if that view is itself, it substitutes the view that is furthest down the view hierarchy. Listing 2-10 Overriding hitTest:withEvent: - (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event { UIView *hitView = [super hitTest:point withEvent:event]; if (hitView == self) return [[self subviews] lastObject]; else return hitView; } Multitouch Events Handling Multitouch Events 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 34Forwarding Touch Events Event forwarding is a technique used by some applications. You forward touch events by invoking the event-handling methods of another responder object. Although this can be an effective technique, you should use it with caution. The classes of the UIKit framework are not designed to receive touches that are not bound to them; in programmatic terms, this means that the view property of the UITouch object must hold a reference to the framework object in order for the touch to be handled. If you want to conditionally forward touches to other responders in your application, all of these responders should be instances of your own subclasses of UIView. For example, let’s say an application has three custom views: A, B, and C. When the user touches view A, the application’s window determines that it is the hit-test view and sends the initial touch event to it. Depending on certain conditions, view A forwards the event to either view B or view C. In this case, views A, B, and C must be aware that this forwarding is going on, and views B and C must be able to deal with touches that are not bound to them. Event forwarding often requires analysis of touch objectsto determine where they should be forwarded. There are several approaches you can take for this analysis: ● With an “overlay” view (such as a common superview), use hit-testing to intercept events for analysis prior to forwarding them to subviews (see “Hit-Testing” (page 33)). ● Override sendEvent: in a custom subclass of UIWindow, analyze touches, and forward them to the appropriate responders. In your implementation you should alwaysinvoke the superclassimplementation of sendEvent:. ● Design your application so that touch analysis isn’t necessary Listing 2-11 illustrates the second technique, that of overriding sendEvent: in a subclass of UIWindow. In this example, the object to which touch events are forwarded is a custom “helper” responder that performs affine transformations on the view that is associated with. Listing 2-11 Forwarding touch events to “helper” responder objects - (void)sendEvent:(UIEvent *)event { for (TransformGesture *gesture in transformGestures) { // collect all the touches we care about from the event NSSet *touches = [gesture observedTouchesForEvent:event]; NSMutableSet *began = nil; NSMutableSet *moved = nil; NSMutableSet *ended = nil; Multitouch Events Handling Multitouch Events 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 35NSMutableSet *cancelled = nil; // sort the touches by phase so we can handle them similarly to normal event dispatch for(UITouch *touch in touches) { switch ([touch phase]) { case UITouchPhaseBegan: if (!began) began = [NSMutableSet set]; [began addObject:touch]; break; case UITouchPhaseMoved: if (!moved) moved = [NSMutableSet set]; [moved addObject:touch]; break; case UITouchPhaseEnded: if (!ended) ended = [NSMutableSet set]; [ended addObject:touch]; break; case UITouchPhaseCancelled: if (!cancelled) cancelled = [NSMutableSet set]; [cancelled addObject:touch]; break; default: break; } } // call our methods to handle the touches if (began) [gesture touchesBegan:began withEvent:event]; if (moved) [gesture touchesMoved:moved withEvent:event]; if (ended) [gesture touchesEnded:ended withEvent:event]; if (cancelled) [gesture touchesCancelled:cancelled withEvent:event]; } [super sendEvent:event]; } Multitouch Events Handling Multitouch Events 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 36Notice that in this example that the overriding subclass does something important to the integrity of the touch-event stream: It invokes the superclass implementation of sendEvent:. Handling Events in Subclasses of UIKit Views and Controls If you subclass a view or control class of the UIKit framework (for example, UIImageView or UISwitch) for the purpose of altering or extending event-handling behavior, you should keep the following points in mind: ● Unlike in a custom view, it is not necessary to override each event-handling method. ● Always invoke the superclass implementation of each event-handling method that you do override. ● Do not forward events to UIKit framework objects. Best Practices for Handling Multitouch Events When handling events, both touch events and motion events, there are a few recommended techniques and patterns you should follow. ● Always implement the event-cancellation methods. In your implementation, you should restore the state of the view to what it was before the current multitouch sequence, freeing any transient resourcesset up for handling the event. If you don’t implement the cancellation method your view could be left in an inconsistent state. In some cases, another view might receive the cancellation message. ● If you handle events in a subclass of UIView, UIViewController, or (in rare cases) UIResponder, ● You should implement all of the event-handling methods (even if it is a null implementation). ● Do not call the superclass implementation of the methods. ● If you handle events in a subclass of any other UIKit responder class, ● You do not have to implement all of the event-handling methods. ● But in the methods you do implement, be sure to call the superclass implementation. For example, [super touchesBegan:theTouches withEvent:theEvent]; ● Do not forward events to other responder objects of the UIKit framework. The responders that you forward events to should be instances of your own subclasses of UIView, and all of these objects must be aware that event-forwarding is taking place and that, in the case of touch events, they may receive touches that are not bound to them. ● Custom views that redraw themselves in response to events should only set drawing state in the event-handling methods and perform all of the drawing in the drawRect: method. Multitouch Events Best Practices for Handling Multitouch Events 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 37● Do not explicitly send events up the responder (via nextResponder); instead, invoke the superclass implementation and let the UIKit handle responder-chain traversal. Multitouch Events Best Practices for Handling Multitouch Events 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 38Note: This chapter containsinformation that used to be in iPad ProgrammingGuide . The information in this chapter has not been updated specifically for iOS 4.0. Applicationsfor iOS are driven largely through events generated when userstouch buttons, toolbars, table-view rows and other objects in an application’s user interface. The classes of the UIKit framework provide default event-handling behavior for most of these objects. However, some applications, primarily those with custom views, have to do their own event handling. They have to analyze the stream of touch objects in a multitouch sequence and determine the intention of the user. Most event-handling views seek to detect common gestures that users make on their surface—things such as triple-tap, touch-and-hold (also called long press), pinching, and rotating gestures, The code for examining a raw stream of multitouch events and detecting one or more gestures is often complex. Prior to iOS 3.2, you cannot reuse the code except by copying it to another project and modifying it appropriately. To help applications detect gestures, iOS 3.2 introduces gesture recognizers, objects that inherit directly from the UIGestureRecognizer class. The following sections tell you about how these objects work, how to use them, and how to create custom gesture recognizers that you can reuse among your applications. Gesture Recognizers Simplify Event Handling UIGestureRecognizer is the abstract base class for concrete gesture-recognizer subclasses (or, simply, gesture recognizers). The UIGestureRecognizer class defines a programmatic interface and implements the behavioral underpinnings for gesture recognition. The UIKit framework provides six gesture recognizers for the most common gestures. For other gestures, you can design and implement your own gesture recognizer (see “Creating Custom Gesture Recognizers” (page 50) for details). Recognized Gestures The UIKit framework supports the recognition of the gestures listed in Table 3-1. Each of the listed classes is a direct subclass of UIGestureRecognizer. 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 39 Gesture RecognizersTable 3-1 Gestures recognized by the gesture-recognizer classes of the UIKit framework Gesture UIKit class Tapping (any number of taps) UITapGestureRecognizer Pinching in and out (for zooming a view) UIPinchGestureRecognizer Panning or dragging UIPanGestureRecognizer Swiping (in any direction) UISwipeGestureRecognizer Rotating (fingers moving in opposite directions) UIRotationGestureRecognizer Long press (also known as “touch and hold”) UILongPressGestureRecognizer Before you decide to use a gesture recognizer, consider how you are going to use it. Respond to gestures only in ways that users expect. For example, a pinching gesture should scale a view, zooming it in and out; it should not be interpreted as, say, a selection request, for which a tap is more appropriate. For guidelines about the proper use of gestures, see iOS Human Interface Guidelines. Gestures Recognizers Are Attached to a View To detect its gestures, a gesture recognizer must be attached to the view that a user is touching. This view is known as the hit-tested view. Recall that events in iOS are represented by UIEvent objects, and each event object encapsulates the UITouch objects of the current multitouch sequence. A set of those UITouch objects is specific to a given phase of a multitouch sequence. Delivery of events initially follows the usual path: from operating system to the application object to the window object representing the window in which the touches Gesture Recognizers Gesture Recognizers Simplify Event Handling 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 40are occurring. But before sending an event to the hit-tested view, the window object sends it to the gesture recognizer attached to that view or to any of that view’s subviews. Figure 3-1 illustrates this general path, with the numbers indicating the order in which touches are received. Figure 3-1 Path of touch objects when gesture recognizer is attached to a view UIApplication View Gesture Recognizer Touch UIWindow 1 Touch 2 Touch 3 Thus gesture recognizers act as observers of touch objects sent to their attached view or view hierarchy. However, they are not part of that view hierarchy and do not participate in the responder chain. Gesture recognizers may delay the delivery of touch objects to the view while they are recognizing gestures, and by default they cancel delivery of remaining touch objects to the view once they recognize their gesture. For more on the possible scenarios of event delivery from a gesture recognizer to its view, see “Regulating the Delivery of Touches to Views” (page 48). For some gestures, the locationInView: and the locationOfTouch:inView: methods of UIGestureRecognizer enable clients to find the location of gestures or specific touches in the attached view or its subviews. See “Responding to Gestures” (page 44) for more information. Gestures Trigger Action Messages When a gesture recognizer recognizes its gesture, it sends one or more action messages to one or more targets. When you create a gesture recognizer, you initialize it with an action and a target. You may add more target-action pairs to it thereafter. The target-action pairs are not additive; in other words, an action is only sent to the target it was originally linked with, and not to other targets (unless they’re specified in another target-action pair). Discrete Gestures and Continuous Gestures When a gesture recognizer recognizes a gesture, it sends either a single action message to its target or multiple action messages until the gesture ends. This behavior is determined by whether the gesture is discrete or continuous. A discrete gesture, such as a double-tap, happens just once; when a gesture recognizer recognizes Gesture Recognizers Gesture Recognizers Simplify Event Handling 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 41a discrete gesture, it sends its target a single action message. A continuous gesture, such as pinching, takes place over a period and ends when the user lifts the final finger in the multitouch sequence. The gesture recognizer sends action messages to its target at short intervals until the multitouch sequence ends. Figure 3-2 Discrete versus continuous gestures UITapGestureRecognizer Tapping gesture Pinching gesture Touch events Target UIPinchGestureRecognizer Target Action messages Action messages Touch events The reference documents for the gesture-recognizer classes note whether the instances of the class detect discrete or continuous gestures. Implementing Gesture Recognition To implement gesture recognition, you create a gesture-recognizer instance to which you assign a target, action, and, in some cases, gesture-specific attributes. You attach this object to a view and then implement the action method in your target object that handles the gesture. Gesture Recognizers Implementing Gesture Recognition 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 42Preparing a Gesture Recognizer To create a gesture recognizer, you must allocate and initialize an instance of a concrete UIGestureRecognizer subclass. When you initialize it, specify a target object and an action selector, as in the following code: UITapGestureRecognizer *doubleFingerDTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleDoubleTap:)]; The action methods for handling gestures—and the selector for identifying them—are expected to conform to one of two signatures: - (void)handleGesture - (void)handleGesture:(UIGestureRecognizer *)sender where handleGesture and sender can be any name you choose. Methods having the second signature allow the target to query the gesture recognizer for addition information. For example, the target of a UIPinchGestureRecognizer object can ask that object for the current scale factor related to the pinching gesture. After you create a gesture recognizer, you must attach it to the view receiving touches—that is, the hit-test view—using the UIView method addGestureRecognizer:. You can find out what gesture recognizers a view currently has attached through the gestureRecognizers property, and you can detach a gesture recognizer from a view by calling removeGestureRecognizer:. The sample method in Listing 3-1 creates and initializes three gesture recognizers: a single-finger double-tap, a panning gesture, and a rotation gesture. It then attaches each gesture-recognizer object to the same view. For the singleFingerDTap object, the code specifies that two taps are required for the gesture to be recognized. Each method adds the created gesture recognizer to a view and then releases it (because the view now retains it). Listing 3-1 Creating and initializing discrete and continuous gesture recognizers - (void)createGestureRecognizers { UITapGestureRecognizer *singleFingerDTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleDoubleTap:)]; singleFingerDTap.numberOfTapsRequired = 2; [self.theView addGestureRecognizer:singleFingerDTap]; [singleFingerDTap release]; UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] Gesture Recognizers Implementing Gesture Recognition 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 43initWithTarget:self action:@selector(handlePanGesture:)]; [self.theView addGestureRecognizer:panGesture]; [panGesture release]; UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinchGesture:)]; [self.theView addGestureRecognizer:pinchGesture]; [pinchGesture release]; } You may also add additional targets and actions to a gesture recognizer using the addTarget:action: method of UIGestureRecognizer. Remember that action messages for each target and action pair are restricted to that pair; if you have multiple targets and actions, they are not additive. Responding to Gestures To handle a gesture, the target for the gesture recognizer must implement a method corresponding to the action selector specified when you initialized the gesture recognizer. For discrete gestures, such as a tapping gesture, the gesture recognizer invokesthe method once per recognition; for continuous gestures, the gesture recognizer invokes the method at repeated intervals until the gesture ends (that is, the last finger is lifted from the gesture recognizer’s view). In gesture-handling methods, the target object often gets additional information about the gesture from the gesture recognizer; it does this by obtaining the value of a property defined by the gesture recognizer, such as scale (for scale factor) or velocity. It can also query the gesture recognizer (in appropriate cases) for the location of the gesture. Listing 3-2 shows handlers for two continuous gestures: a pinching gesture (handlePinchGesture:) and a panning gesture (handlePanGesture:). It also gives an example of a handler for a discrete gesture; in this example, when the user double-taps the view with a single finger, the handler (handleSingleDoubleTap:) centers the view at the location of the double-tap. Listing 3-2 Handling pinch, pan, and double-tap gestures - (IBAction)handlePinchGesture:(UIGestureRecognizer *)sender { CGFloat factor = [(UIPinchGestureRecognizer *)sender scale]; self.view.transform = CGAffineTransformMakeScale(factor, factor); } Gesture Recognizers Implementing Gesture Recognition 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 44- (IBAction)handlePanGesture:(UIPanGestureRecognizer *)sender { CGPoint translate = [sender translationInView:self.view]; CGRect newFrame = currentImageFrame; newFrame.origin.x += translate.x; newFrame.origin.y += translate.y; sender.view.frame = newFrame; if (sender.state == UIGestureRecognizerStateEnded) currentImageFrame = newFrame; } - (IBAction)handleSingleDoubleTap:(UIGestureRecognizer *)sender { CGPoint tapPoint = [sender locationInView:sender.view.superview]; [UIView beginAnimations:nil context:NULL]; sender.view.center = tapPoint; [UIView commitAnimations]; } These action methods handle the gestures in distinctive ways: ● In the handlePinchGesture: method, the target communicates with its gesture recognizer (sender) to get the scale factor (scale). The method uses the scale value in a Core Graphics function that scales the view and assigns the computed value to the view’s affine transform property. ● The handlePanGesture: method applies the translationInView: values obtained from its gesture recognizer to a cached frame value for the attached view. When the gesture concludes, it caches the newest frame value. ● In the handleSingleDoubleTap: method, the target gets the location of the double-tap gesture from its gesture recognizer by calling the locationInView: method. It then uses this point, converted to superview coordinates, to animate the center of the view to the location of the double-tap. The scale factor obtained in the handlePinchGesture: method, as with the rotation angle and the translation value related to other recognizers of continuous gestures, is to be applied to the state of the view when the gesture is first recognized. It is not a delta value to be concatenated over each handler invocation for a given gesture. Gesture Recognizers Implementing Gesture Recognition 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 45A hit-test with an attached gesture recognizer does not have to be passive when there are incoming touch events. Instead, it can determine which gesture recognizers, if any, are involved with a particular UITouch object by querying the gestureRecognizers property. Similarly, it can find out which touches a given gesture recognizer is analyzing for a given event by calling the UIEvent method touchesForGestureRecognizer:. Interacting with Other Gesture Recognizers More than one gesture recognizer may be attached to a view. In the default behavior, touch events in a multitouch sequence go from one gesture recognizer to another in a nondeterministic order until the events are finally delivered to the view (if at all). Often this default behavior is what you want. But sometimes you might want one or more of the following behaviors: ● Have one gesture recognizer fail before another can start analyzing touch events. ● Prevent other gesture recognizers from analyzing a specific multitouch sequence or a touch object in that sequence. ● Permit two gesture recognizers to operate simultaneously. The UIGestureRecognizer class provides client methods, delegate methods, and methods overridden by subclasses to enable you to effect these behaviors. Requiring a Gesture Recognizer to Fail You might want a relationship between two gesture recognizers so that one can operate only if the other one fails. For example, recognizer A doesn’t begin analyzing a multitouch sequence until recognizer B fails and, conversely, if recognizer B does recognize its gesture, recognizer A never looks at the multitouch sequence. An example where you might specify this relationship is when you have a gesture recognizer for a single tap and another gesture recognizer for a double tap; the single-tap recognizer requires the double-tap recognizer to fail before it begins operating on a multitouch sequence. The method you call to specify this relationship is requireGestureRecognizerToFail:. After sending the message, the receiving gesture recognizer must stay in the UIGestureRecognizerStatePossible state until the specified gesture recognizer transitions to UIGestureRecognizerStateFailed. If the specified gesture recognizer transitions to UIGestureRecognizerStateRecognized or UIGestureRecognizerStateBegan instead, then the receiving recognizer can proceed, but no actionmessage is sent if it recognizes its gesture. Gesture Recognizers Interacting with Other Gesture Recognizers 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 46Note: In the case of the single-tap versus double-tap gestures, if a single-tap gesture recognizer doesn’t require the double-tap recognizer to fail, you should expect to receive yoursingle-tap actions before your double-tap actions, even in the case of a double tap. This is expected and desirable behavior because the best user experience generally involvesstackable actions. If you want double-tap and single-tap gesture recognizersto have mutually exclusive actions, you can require the double-tap recognizer to fail. You won't get any single-tap actions on a double tap, but any single-tap actions you do receive will necessarily lag behind the user's touch input. In other words, there is no way to know if the user double tapped until after the double-tap delay,so the single-tap gesture recognizer cannot send its action until that delay has passed. For a discussion of gesture-recognition states and possible transition between these states, see “State Transitions” (page 50). Preventing Gesture Recognizers from Analyzing Touches You can prevent gesture recognizers from looking at specific touches or from even recognizing a gesture. You can specify these “prevention” relationships using either delegation methods or overriding methods declared by the UIGestureRecognizer class. The UIGestureRecognizerDelegate protocol declares two optional methods that prevent specific gesture recognizers from recognizing gestures on a case-by-case basis: ● gestureRecognizerShouldBegin: — This method is called when a gesture recognizer attempts to transition out of UIGestureRecognizerStatePossible. Return NO to make it transition to UIGestureRecognizerStateFailed instead. (The default value is YES.) ● gestureRecognizer:shouldReceiveTouch: —This method is called before the window object calls touchesBegan:withEvent: on the gesture recognizer when there are one or more new touches. Return NO to prevent the gesture recognizer from seeing the objects representing these touches. (The default value is YES.) In addition,there are two UIGestureRecognizermethods(declared in UIGestureRecognizerSubclass.h) that effect the same behavior as these delegation methods. A subclass can override these methods to define class-wide prevention rules: - (BOOL)canPreventGestureRecognizer:(UIGestureRecognizer *)preventedGestureRecognizer; - (BOOL)canBePreventedByGestureRecognizer:(UIGestureRecognizer *)preventingGestureRecognizer; Gesture Recognizers Interacting with Other Gesture Recognizers 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 47Permitting Simultaneous Gesture Recognition By default, no two gesture recognizers can attempt to recognize their gestures simultaneously. But you can change this behavior by implementing gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:, an optional method of the UIGestureRecognizerDelegate protocol. This method is called when the recognition of the receiving gesture recognizer would block the operation of the specified gesture recognizer, or vice versa. Return YES to allow both gesture recognizers to recognize their gestures simultaneously. Note: Returning YES is guaranteed to allow simultaneous recognition, but returning NO is not guaranteed to prevent simultaneous recognition because the other gesture's delegate may return YES. Regulating the Delivery of Touches to Views Generally, a window delivers UITouch objects (packaged in UIEvent objects) to a gesture recognizer before it delivers them to the attached hit-test view. But there are some subtle detours and dead-ends in this general delivery path that depend on whether a gesture is recognized. You can alter this delivery path to suit the requirements of your application. Default Touch-Event Delivery By default a window in a multitouch sequence delays the delivery of touch objects in Ended phases to the hit-test view and, if the gesture is recognized, both prevents the delivery of current touch objects to the view and cancels touch objects previously received by the view. The exact behavior depends on the phase of touch objects and on whether a gesture recognizer recognizes its gesture or fails to recognize it in a multitouch sequence. To clarify this behavior, consider a hypothetical gesture recognizer for a discrete gesture involving two touches (that is, two fingers). Touch objects enter a system and are passed from the UIApplication object to the UIWindow object for the hit-test view. The following sequence occurs when the gesture is recognized: 1. The window sendstwo touch objectsin the Began phase (UITouchPhaseBegan) to the gesture recognizer, which doesn’t recognize the gesture. The window sends these same touches to the view attached to the gesture recognizer. 2. The window sendstwo touch objectsin the Moved phase (UITouchPhaseMoved) to the gesture recognizer, and the recognizer still doesn’t detect its gesture. The window then sends these touches to the attached view. Gesture Recognizers Regulating the Delivery of Touches to Views 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 483. The window sends one touch object in the Ended phase (UITouchPhaseEnded) to the gesture recognizer. This touch object doesn’t yield enough information for the gesture, but the window withholds the object from the attached view. 4. The window sends the other touch object in the Ended phase. The gesture recognizer now recognizes its gesture and so it sets its state to UIGestureRecognizerStateRecognized. Just before the first (or only) action message issent, the view receives a touchesCancelled:withEvent: message to invalidate the touch objects previously sent (in the Began and Moved phases). The touches in the Ended phase are canceled. Now assume that the gesture recognizer in the last step instead decides that this multitouch sequence it’s been analyzing is not its gesture. It sets its state to UIGestureRecognizerStateFailed. The window then sends the two touch objects in the Ended phase to the attached view in a touchesEnded:withEvent: message. A gesture recognizer for a continuous gesture goes through a similar sequence, except that it is more likely to recognize its gesture before touch objectsreach the Ended phase. Upon recognizing its gesture, itsetsitsstate to UIGestureRecognizerStateBegan. The window sends all subsequent touch objects in the multitouch sequence to the gesture recognizer but not to the attached view. Note: For a discussion of gesture-recognition states and possible transition between these states, see “State Transitions” (page 50). Affecting the Delivery of Touches to Views You can change the values of three UIGestureRecognizer properties to alter the default delivery path of touch objects to views in certain ways. These properties and their default values are: cancelsTouchesInView (default of YES) delaysTouchesBegan (default of NO) delaysTouchesEnded (default of YES) If you change the default values of these properties, you get the following differences in behavior: ● cancelsTouchesInView set to NO — Causes touchesCancelled:withEvent: to not be sent to the view for any touches belonging to the recognized gesture. As a result, any touch objects in Began or Moved phases previously received by the attached view are not invalidated. ● delaysTouchesBegan set to YES — Ensures that when a gesture recognizer recognizes a gesture, no touch objects that were part of that gesture are delivered to the attached view. This setting provides a behavior similar to that offered by the delaysContentTouches property on UIScrollView; in this Gesture Recognizers Regulating the Delivery of Touches to Views 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 49case, when scrolling begins soon after the touch begins, subviews of the scroll-view object never receive the touch, so there is no flash of visual feedback. You should be careful about this setting because it can easily make your interface feel unresponsive. ● delaysTouchesEnded set to NO — Prevents a gesture recognizer that's recognized its gesture after a touch has ended from canceling that touch on the view. For example, say a view has a UITapGestureRecognizer object attached with its numberOfTapsRequired set to 2, and the user double-taps the view. If this property is set to NO, the view gets the following sequence of messages: touchesBegan:withEvent:, touchesEnded:withEvent:, touchesBegan:withEvent:, and touchesCancelled:withEvent:. With the property set to YES, the view gets touchesBegan:withEvent:, touchesBegan:withEvent:, touchesCancelled:withEvent:, and touchesCancelled:withEvent:. The purpose of this property is to ensure that a view won't complete an action as a result of a touch that the gesture will want to cancel later. Creating Custom Gesture Recognizers If you are going to create a custom gesture recognizer, you need to have a clear understanding of how gesture recognizers work. The following section gives you the architectural background of gesture recognition, and the subsequent section goes into details of actually creating a gesture recognizer. State Transitions Gesture recognizers operate in a predefined state machine. They transition from one state to another depending on whether certain conditions apply. The following enum constants from UIGestureRecognizer.h define the states for gesture recognizers: typedef enum { UIGestureRecognizerStatePossible, UIGestureRecognizerStateBegan, UIGestureRecognizerStateChanged, UIGestureRecognizerStateEnded, UIGestureRecognizerStateCancelled, UIGestureRecognizerStateFailed, UIGestureRecognizerStateRecognized = UIGestureRecognizerStateEnded } UIGestureRecognizerState; Gesture Recognizers Creating Custom Gesture Recognizers 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 50The sequence of states that a gesture recognizer may transition through varies, depending on whether a discrete or continuous gesture is being recognized. All gesture recognizers start in the Possible state (UIGestureRecognizerStatePossible). They then analyze the multitouch sequence targeted at their attached hit-test view, and they either recognize their gesture or fail to recognize it. If a gesture recognizer does not recognize its gesture, it transitions to the Failed state(UIGestureRecognizerStateFailed); this is true of all gesture recognizers, regardless of whether the gesture is discrete or continuous. When a gesture is recognized, however, the state transitions differ for discrete and continuous gestures. A recognizer for a discrete gesture transitions from Possible to Recognized (UIGestureRecognizerStateRecognized). A recognizer for a continuous gesture, on the other hand, transitionsfrom Possible to Began (UIGestureRecognizerStateBegan) when it first recognizesthe gesture. Then it transitionsfrom Began to Changed (UIGestureRecognizerStateChanged), and subsequently from Changed to Changed every time there is a change in the gesture. Finally, when the last finger in the multitouch sequence is lifted from the hit-test view, the gesture recognizer transitions to the Ended state (UIGestureRecognizerStateEnded), which is an aliasfor the UIGestureRecognizerStateRecognized state. A recognizer for a continuous gesture can also transition from the Changed state to a Cancelled state (UIGestureRecognizerStateCancelled) if it determines that the recognized gesture no longer fits the expected pattern for its gesture. Figure 3-3 illustrates these transitions. Figure 3-3 Possible state transitions for gesture recognizers Possible Began Changed Cancelled Gesture cancelled — continuous gestures Possible Began Changed Ended Recognizes gestures — continuous gestures Possible Recognized Recognizes gesture — discrete gestures Possible Failed Fails to recognize gesture — all gesture recognizers Gesture Recognizers Creating Custom Gesture Recognizers 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 51Note: The Began, Changed, Ended, and Cancelled states are not necessarily associated with UITouch objects in corresponding touch phases. They strictly denote the phase of the gesture itself, not the touch objects that are being recognized. When a gesture is recognized, every subsequent state transition causes an action message to be sent to the target. When a gesture recognizer reaches the Recognized or Ended state, it is asked to reset its internal state in preparation for a new attempt at recognizing the gesture. The UIGestureRecognizer class then sets the gesture recognizer’s state back to Possible. Implementing a Custom Gesture Recognizer To implement a custom gesture recognizer, first create a subclass of UIGestureRecognizer in Xcode. Then, add the following import directive in your subclass’s header file: #import Next copy the following method declarations from UIGestureRecognizerSubclass.h to your header file; these are the methods you override in your subclass: - (void)reset; - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event; - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event; - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event; - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event; You must be sure to call the superclass implementation (super) in all of the methods you override. Examine the declaration of the state property in UIGestureRecognizerSubclass.h. Notice that it is now given a readwrite option instead of readonly (in UIGestureRecognizer.h). Your subclass can now change its state by assigning UIGestureRecognizerState constants to the property. The UIGestureRecognizer class sends action messages for you and controls the delivery of touch objects to the hit-test view. You do not need to implement these tasks yourself. Gesture Recognizers Creating Custom Gesture Recognizers 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 52Implementing the Multitouch Event-Handling Methods The heart of the implementation for a gesture recognizer are the four methods touchesBegan:withEvent:, touchesMoved:withEvent:, touchesEnded:withEvent:, and touchesCancelled:withEvent:. You implement these methods much as you would implement them for a custom view. Note: See “Handling Multi-Touch Events” in iOS App Programming Guide in “Document Revision History” for information about handling events delivered during a multitouch sequence. The main difference in the implementation of these methods for a gesture recognizer is that you transition between states at the appropriate moment. To do this, you must set the value of the state property to the appropriate UIGestureRecognizerState constant. When a gesture recognizer recognizes a discrete gesture, it sets the state property to UIGestureRecognizerStateRecognized. If the gesture is continuous, it sets the state property first to UIGestureRecognizerStateBegan; then, for each change in position of the gesture, it sets (or resets) the property to UIGestureRecognizerStateChanged. When the gesture ends, it sets state to UIGestureRecognizerStateEnded. If at any point a gesture recognizer realizes that this multitouch sequence is not its gesture, it sets its state to UIGestureRecognizerStateFailed. Listing 3-3 is an implementation of a gesture recognizer for a discrete single-touch “checkmark” gesture (actually any V-shaped gesture). It records the midpoint of the gesture—the point at which the upstroke begins—so that clients can obtain this value. Listing 3-3 Implementation of a “checkmark” gesture recognizer. - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [super touchesBegan:touches withEvent:event]; if ([touches count] != 1) { self.state = UIGestureRecognizerStateFailed; return; } } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { [super touchesMoved:touches withEvent:event]; if (self.state == UIGestureRecognizerStateFailed) return; CGPoint nowPoint = [[touches anyObject] locationInView:self.view]; CGPoint prevPoint = [[touches anyObject] previousLocationInView:self.view]; if (!strokeUp) { Gesture Recognizers Creating Custom Gesture Recognizers 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 53// on downstroke, both x and y increase in positive direction if (nowPoint.x >= prevPoint.x && nowPoint.y >= prevPoint.y) { self.midPoint = nowPoint; // upstroke has increasing x value but decreasing y value } else if (nowPoint.x >= prevPoint.x && nowPoint.y <= prevPoint.y) { strokeUp = YES; } else { self.state = UIGestureRecognizerStateFailed; } } } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { [super touchesEnded:touches withEvent:event]; if ((self.state == UIGestureRecognizerStatePossible) && strokeUp) { self.state = UIGestureRecognizerStateRecognized; } } - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { [super touchesCancelled:touches withEvent:event]; self.midPoint = CGPointZero; strokeUp = NO; self.state = UIGestureRecognizerStateFailed; } If a gesture recognizer detects a touch (as represented by a UITouch object) that it determines is not part of its gesture, it can pass it on directly to its view. To do this, it calls ignoreTouch:forEvent: on itself, passing in the touch object. Ignored touches are not withheld from the attached view even if the value of the cancelsTouchesInView property is YES. Resetting State When your gesture recognizer transitions to either the UIGestureRecognizerStateRecognized state or theUIGestureRecognizerStateEnded state, the UIGestureRecognizer class calls the reset method of the gesture recognizer just before it winds back the gesture recognizer’s state to Gesture Recognizers Creating Custom Gesture Recognizers 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 54UIGestureRecognizerStatePossible. A gesture recognizer class should implement this method to reset any internal state so that it is ready for a new attempt at recognizing the gesture. After a gesture recognizer returns from this method, it receives no further updates for touches that have already begun but haven’t ended. Listing 3-4 Resetting a gesture recognizer - (void)reset { [super reset]; self.midPoint = CGPointZero; strokeUp = NO; } Gesture Recognizers Creating Custom Gesture Recognizers 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 55An iPhone, iPad, or iPod touch device generates motion events when users move the device in a certain way, such as shaking it or tilting it. All motion events have their origin in the device accelerometer or gyroscope. If you want to detect motions as gestures—specifically shaking motions—you should handle motion events as described in “Shaking-Motion Events” (page 56). If you want to receive and handle high-rate, continuous motion data, you should instead follow the approaches described in “Core Motion” (page 63) or “Accessing Accelerometer Events Using UIAccelerometer” (page 59). Notes: This chapter contains information that used to be in iOS App Programming Guide . The information in this chapter has not been updated specifically for iOS 4.0. Shaking-Motion Events When usersshake a device, the system evaluatesthe accelerometer data and, if that data meets certain criteria, interprets it as a shaking gesture. The system creates a UIEvent object representing this gesture and sends the event object to the currently active application for processing. Note: Motion events as a type of UIEvent were introduced in iOS 3.0. Currently, only shaking motions are interpreted as gestures and become motion events. Motion events are much simpler than touch events. The system tells an application when a motion starts and when it stops, and not when each individual motion occurs. And, whereas a touch event includes a set of touches and their related state, a motion event carries with it no state other than the event type, eventsubtype, and timestamp. The system interprets motion gesturesin a way that does not conflict with orientation changes. To receive motion events, the responder object that is to handle them must be the first responder. Listing 4-1 shows how a responder can make itself the first responder. Listing 4-1 Becoming first responder - (BOOL)canBecomeFirstResponder { return YES; 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 56 Motion Events} - (void)viewDidAppear:(BOOL)animated { [self becomeFirstResponder]; } To handle motion events, a class inheriting from UIResponder must implement either the motionBegan:withEvent: method or motionEnded:withEvent: method, or possibly both of these methods (see “Best Practices for Handling Multitouch Events” (page 37)). For example, if an application wants to give horizontal shakes and vertical shakes different meanings, it can cache the current acceleration axis values in motionBegan:withEvent:, compare those cached values to the same axis values in motionEnded:withEvent:, and act on the results accordingly. A responder should also implement the motionCancelled:withEvent: method to respond to events that the system sends to cancel a motion event; these events sometimes reflect the system’s determination that the motion is not a valid gesture after all. Listing 4-2 shows code that handles a shaking-motion event by resetting views that have have been altered (by translation, rotation, and scaling) to their original positions, orientations, and sizes. Listing 4-2 Handling a motion event - (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event { } - (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event { [UIView beginAnimations:nil context:nil]; [UIView setAnimationDuration:0.5]; self.view.transform = CGAffineTransformIdentity; for (UIView *subview in self.view.subviews) { subview.transform = CGAffineTransformIdentity; } [UIView commitAnimations]; for (TransformGesture *gesture in [window allTransformGestures]) { Motion Events Shaking-Motion Events 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 57[gesture resetTransform]; } } - (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event { } An application and its key window deliver a motion event to a window’s first responder for handling. If the first responder doesn’t handle it, the event progresses up the responder chain in the same way touch events do until it is either handled or ignored. (See “Event Delivery” (page 11) for details.) However, there is one important difference between touch events and shaking-motion events. When the user starts shaking the device, the system sends a motion event to the first responder in a motionBegan:withEvent: message; if the first responder doesn’t handle the event, it travels up the responder chain. If the shaking lasts less than a second or so, the system sends a motionEnded:withEvent: message to the first responder. But if the shaking lasts longer or if the system determines the motion is not a shake, the first responder receives a motionCancelled:withEvent: message. If a shaking-motion event travels up the responder chain to the window without being handled and the applicationSupportsShakeToEdit property of UIApplication is set to YES, iOS displays a sheet with Undo and Redo commands. By default, this property is set to YES. Getting the Current Device Orientation If you need to know only the general orientation of the device, and not the exact vector of orientation, you should use the methods of the UIDevice class to retrieve that information. Using the UIDevice interface is simple and does not require that you calculate the orientation vector yourself. Before getting the current orientation, you must tell the UIDevice classto begin generating device orientation notifications by calling the beginGeneratingDeviceOrientationNotifications method. Doing so turns on the accelerometer hardware (which may otherwise be off to conserve power). Shortly after enabling orientation notifications, you can get the current orientation from the orientation property of the shared UIDevice object. You can also register to receive UIDeviceOrientationDidChangeNotification notifications, which are posted whenever the general orientation changes. The device orientation is reported using the UIDeviceOrientation constants, which Motion Events Getting the Current Device Orientation 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 58indicate whether the device is in landscape or portrait mode or whether the device is face up or face down. These constants indicate the physical orientation of the device and need not correspond to the orientation of your application’s user interface. When you no longer need to know the orientation of the device, you should always disable orientation notifications by calling the endGeneratingDeviceOrientationNotifications method of UIDevice. Doing so gives the system the opportunity to disable the accelerometer hardware if it is not in use elsewhere. Setting Required Hardware Capabilities for Accelerometer and Gyroscope Events If your application requires device-related featuresin order to run—such asthe ability to receive accelerometer data—you must add a list of required capabilitiesto your application. At runtime, iOS launches your application only if those capabilities are present on the device. Furthermore, the App Store uses the information in this key to generate a list of requirements for user devices and prevent users from downloading applications that they cannot run. You declare your application’s required capabilities by adding the UIRequiredDeviceCapabilities key to your application’s Info.plist file. This key, supported in iOS 3.0 and later, has a value that is either an array or a dictionary. If you use an array, the presence of a given key indicates the corresponding feature is required. If you use a dictionary, you must specify a Boolean value for each key indicating whether the feature is required. In both cases, having no key for a feature indicates that the feature is not required. The following UIRequiredDeviceCapabilities keys are for motion events, based on hardware source: ● accelerometer (for accelerometer events) You do not need to include this key if your application detects only device orientation changes or if your application handles shaking-motion events delivered via UIEvent objects. ● gyroscope (for gyroscope events) Accessing Accelerometer Events Using UIAccelerometer Every application has a single UIAccelerometer object that can be used to receive acceleration data. You get the instance of this class using the sharedAccelerometer class method of UIAccelerometer. Using this object, you set the desired reporting interval and a custom delegate to receive acceleration events. You can set the reporting interval to be as small as 10 milliseconds (ms), which corresponds to a 100 Hz update Motion Events Setting Required Hardware Capabilities for Accelerometer and Gyroscope Events 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 59rate, although most applications can operate sufficiently with a larger interval. As soon as you assign your delegate object, the accelerometerstartssending it data. Thereafter, your delegate receives data at the requested update interval. Listing 4-3 shows the basic steps for configuring an accelerometer. In this example, the update frequency is 50 Hz, which corresponds to an update interval of 20 ms. The myDelegateObject is a custom object that you define; it must support the UIAccelerometerDelegate protocol, which defines the method used to receive acceleration data. Listing 4-3 Configuring the accelerometer #define kAccelerometerFrequency 50.0 //Hz -(void)configureAccelerometer { UIAccelerometer* theAccelerometer = [UIAccelerometer sharedAccelerometer]; theAccelerometer.updateInterval = 1 / kAccelerometerFrequency; theAccelerometer.delegate = self; // Delegate events begin immediately. } At regular intervals, the shared accelerometer object delivers event data to your delegate’s accelerometer:didAccelerate: method, shown in Listing 4-4. You can use this method to process the accelerometer data however you want. In general it is recommended that you use some sort of filter to isolate the component of the data in which you are interested. Listing 4-4 Receiving an accelerometer event - (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration { UIAccelerationValue x, y, z; x = acceleration.x; y = acceleration.y; z = acceleration.z; // Do something with the values. } Motion Events Accessing Accelerometer Events Using UIAccelerometer 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 60To stop the delivery of acceleration events, set the delegate of the shared UIAccelerometer object to nil. Setting the delegate object to nil lets the system know that it can turn off the accelerometer hardware as needed and thus save battery life. The acceleration data you receive in your delegate method represents the instantaneous values reported by the accelerometer hardware. Even when a device is completely at rest, the values reported by this hardware can fluctuate slightly. When using these values, you should be sure to account for these fluctuations by averaging out the values over time or by calibrating the data you receive. For example, the Bubble Levelsample application provides controls for calibrating the current angle against a known surface. Subsequent readings are then reported relative to the calibrated angle. If your own code requires a similar level of accuracy, you should also include a calibration option in your user interface. Choosing an Appropriate Update Interval When configuring the update interval for acceleration events, it is best to choose an interval that minimizes the number of delivered events and still meetsthe needs of your application. Few applications need acceleration events delivered 100 times a second. Using a lower frequency prevents your application from running as often and can therefore improve battery life. Table 4-1 lists some typical update frequencies and explains what you can do with the acceleration data generated at that frequency. Table 4-1 Common update intervals for acceleration events Event frequency (Hz) Usage Suitable for use in determining the vector representing the current orientation of the device. 10–20 Suitable for games and other applications that use the accelerometers for real-time user input. 30–60 Suitable for applications that need to detect high-frequency motion. For example, you might use this interval to detect the user hitting the device or shaking it very quickly. 70–100 Isolating the Gravity Component from Acceleration Data If you are using the accelerometer data to detect the current orientation of a device, you need to be able to filter out the portion of the acceleration data caused by gravity from the portion of the data that is caused by motion of the device. To do this, you can use a low-pass filter to reduce the influence of sudden changes on the accelerometer data. The resulting filtered values then reflect the more constant effects of gravity. Motion Events Accessing Accelerometer Events Using UIAccelerometer 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 61Listing 4-5 shows a simplified version of a low-pass filter. This example uses a low-value filtering factor to generate a value that uses 10 percent of the unfiltered acceleration data and 90 percent of the previously filtered value. The previous values are stored in the accelX, accelY, and accelZ member variables of the class. Because acceleration data comes in regularly, these values settle out quickly and respond slowly to sudden but short-lived changes in motion. Listing 4-5 Isolating the effects of gravity from accelerometer data #define kFilteringFactor 0.1 - (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration { // Use a basic low-pass filter to keep only the gravity component of each axis. accelX = (acceleration.x * kFilteringFactor) + (accelX * (1.0 - kFilteringFactor)); accelY = (acceleration.y * kFilteringFactor) + (accelY * (1.0 - kFilteringFactor)); accelZ = (acceleration.z * kFilteringFactor) + (accelZ * (1.0 - kFilteringFactor)); // Use the acceleration data. } Isolating Instantaneous Motion from Acceleration Data If you are using accelerometer data to detect just the instant motion of a device, you need to be able to isolate sudden changes in movement from the constant effect of gravity. You can do that with a high-pass filter. Listing 4-6 shows a simplified high-pass filter computation. The acceleration values from the previous event are stored in the accelX, accelY, and accelZ member variables of the class. This example computes the low-pass filter value and then subtracts it from the current value to obtain just the instantaneous component of motion. Listing 4-6 Getting the instantaneous portion of movement from accelerometer data #define kFilteringFactor 0.1 - (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration { Motion Events Accessing Accelerometer Events Using UIAccelerometer 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 62// Subtract the low-pass value from the current value to get a simplified high-pass filter accelX = acceleration.x - ( (acceleration.x * kFilteringFactor) + (accelX * (1.0 - kFilteringFactor)) ); accelY = acceleration.y - ( (acceleration.y * kFilteringFactor) + (accelY * (1.0 - kFilteringFactor)) ); accelZ = acceleration.z - ( (acceleration.z * kFilteringFactor) + (accelZ * (1.0 - kFilteringFactor)) ); // Use the acceleration data. } Core Motion Core Motion is a system framework that obtains motion data from sensors on a device and presents that data to applicationsfor processing. The handling of the sensor data and the application of related algorithms occurs on Core Motion’s own thread. The items of hardware that detect and originate these motion events are the accelerometer and the gyroscope. (The gyroscope is currently available only on iPhone 4.) Core Motion publishes an Objective-C programmatic interface that enables applications to receive device-motion data of various types, which they can then process in appropriate ways. As illustrated by Figure 4-1 (page 64), Core Motion defines a manager class, CMMotionManager, and three classes whose instances encapsulate measurements of motion data of various types: ● A CMAccelerometerData object encapsulates a data structure that records a measurement of device acceleration along the three spatial axes. This data derives from the accelerometer. For more on CMAccelerometerData, see “Handling Accelerometer Events Using Core Motion” (page 65). ● A CMGyroData object encapsulates a data structure that records a biased estimate of a device’s rate of rotation along the three spatial axes. This “raw” data derives from the gyroscope. (“Biased” in this context refers to an offset from the true rotation rate. Thus, if the device is not rotating, this estimate from the gyroscope will still give a non-zero value.) For more on CMGyroData, see “Handling Rotation-Rate Data” (page 68). ● A CMDeviceMotion object encapsulates processed device-motion data that derives from both the accelerometer and the gyroscope. Core Motion’s sensor fusion algorithms process both accelerometer and gyroscope data and provide an application with highly accurate measurements of device attitude, the (unbiased) rotation rate of a device, the direction of gravity on a device, and the acceleration that the Motion Events Core Motion 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 63user is giving to a device. A CMAttitude object, which is contained in an CMDeviceMotion instance, contains properties giving different measurements of attitude, including the Euler angles indicated by roll, pitch, and yaw. Attitude refers to the orientation of a device in three dimensions relative to a reference frame that is external to the device. For more on attitude and CMDeviceMotion,see “Handling Processed Device-Motion Data” (page 72). Figure 4-1 Core Motion classes Core Motion Framework CMMotionManager CMAccelerometerData CMDeviceMotion CMGyroData CMAttitude All of the data-encapsulating classes of Core Motion are subclasses of CMLogItem, which defines a timestamp so that motion data can be tagged with the event time and logged to a file. An application can also compare the timestamp of motion events with earlier motion events to determine the true update interval between events. For each of the data-motion types described above, the CMMotionManager class offers two approaches for obtaining motion data, a push approach and a pull approach: ● Push. An application requests an update interval and implements a block (of a specific type) for handling the motion data; it then starts updatesfor that type of motion data, passing into Core Motion an operation queue as well as the block. Core Motion delivers each update to the block, which executes as a task in the operation queue. ● Pull. An application starts updates of a type of motion data and periodically samples the most recent measurement of motion data. The pull approach is the recommended approach for most applications, especially games; it is generally more efficient and requires less code. The push approach is appropriate for data-collection applications and similar applications that cannot miss a sample measurement. Both approaches have benign thread-safety effects; with the push approach, your block executes on the operation-queue’sthread whereas, with the pull approach, Core Motion never interrupts your threads. Motion Events Core Motion 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 64Important: An application should create only a single instance of the CMMotionManager class. Multiple instances of this class can affect the rate at which an application receives data from the accelerometer and gyroscope. Be aware that there is no simulator support for application features related to Core Motion. You have to test and debug applications on a device. Handling Accelerometer Events Using Core Motion Core Motion provides an alternative programmatic interface to UIAccelerometer for accessing accelerometer events. Each of these events is an instance of CMAccelerometerData that encapsulates a measurement of accelerometer activity in a structure of type CMAcceleration. – Z + Z + Y – Y – X + X To start receiving and handling accelerometer data, create an instance of the CMMotionManager class and call one of the following two methods on it: ● startAccelerometerUpdates After this method is called, Core Motion continuously updates the accelerometerData property of CMMotionManager with the latest measurement of accelerometer activity. The application periodically samples this property, usually in a render loop typical of games. If you adopt this polling approach, you should set the update-interval property (accelerometerUpdateInterval) to the maximum interval at which Core Motion performs updates. (Core Motion might perform updates at a faster rate, however.) Motion Events Core Motion 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 65The code examples in this section illustrate this first approach. ● startAccelerometerUpdatesToQueue:withHandler: Before calling this method, the application assigns an update interval to the accelerometerUpdateInterval property. It also creates an instance of NSOperationQueue and implements a block of the CMAccelerometerHandler type that handles the accelerometer updates. Then it calls startAccelerometerUpdatesToQueue:withHandler: on the motion-manager object, passing in the operation queue and the block. At the specified update interval, Core Motion passes the latest sample of accelerometer activity to the block, which executes as a task in the queue. You should stop updates of motion data as soon as your application is finished processing the data. Doing so allows Core Motion to turn off motion sensors, thereby saving battery power. For Core Motion accelerometer events, you configure the update interval exactly as you do when using UIAccelerometer. You must identify an interval suitable for your application and then assign that value (expressed asseconds) to the accelerometerUpdateInterval property. If you prefer to think of the update interval in terms of cycles per second (Hertz), divide 1 by the desired Hertz value to get the update-interval value. Listing 4-3 (page 60) gives an example. (“Choosing an Appropriate Update Interval” (page 61) offers guidance for choosing a suitable update interval.) The following code examples are based on the OpenGL ES project template in Xcode. An OpenGL ES application periodically samples device-motion updates using the render loop itsets up for drawing its view. The application first declares an instance variable—a three-member C array—to hold the acceleration values: double filteredAcceleration[3]; Asshown in Listing 4-7, the application creates an instance of CMMotionManager in the same template method used for configuring and scheduling the timing mechanism of the render loop (startAnimation). The application then assigns an appropriate accelerometer-update interval to the motion manager, allocates memory for the C array, and starts accelerometer updates. Note that the application stops accelerometer updates in the same template method (stopAnimation) used for invalidating the timing mechanism of the render loop. Listing 4-7 Configuring the motion manager and starting updates - (void)startAnimation { if (!animating) { // code that configures and schedules CADisplayLink or timer here ... } Motion Events Core Motion 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 66motionManager = [[CMMotionManager alloc] init]; // motionManager is an instance variable motionManager.accelerometerUpdateInterval = 0.01; // 100Hz memset(filteredAcceleration, 0, sizeof(filteredAcceleration)); [motionManager startAccelerometerUpdates]; } - (void)stopAnimation { if (animating) { // code that invalidates CADisplayLink or timer here... } [motionManager stopAccelerometerUpdates]; } In the OpenGL ES application template, the drawView method is invoked at each cycle of the render loop. Listing 4-8 shows how the application, in this same method, gets the latest accelerometer data and runs it through a low-pass filter. It then updates the drawing model with the filtered acceleration values and renders its view. Listing 4-8 Sampling and filtering accelerometer data - (void)drawView { // alpha is the filter value (instance variable) CMAccelerometerData *newestAccel = motionManager.accelerometerData; filteredAcceleration[0] = filteredAcceleration[0] * (1.0-alpha) + newestAccel.acceleration.x * alpha; filteredAcceleration[1] = filteredAcceleration[1] * (1.0-alpha) + newestAccel.acceleration.y * alpha; filteredAcceleration[2] = filteredAcceleration[2] * (1.0-alpha) + newestAccel.acceleration.z * alpha; [self updateModelsWithAcceleration:filteredAcceleration]; [renderer render]; } Motion Events Core Motion 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 67Note: You can apply a low-pass or high-pass filter to acceleration values and thereby isolate the gravity and user-acceleration components: ● To apply a low-pass filter, thereby isolating the gravity component, see “Isolating the Gravity Component from Acceleration Data” (page 61). ● To apply a high-pass filter, thereby isolating the user-acceleration component, see “Isolating Instantaneous Motion from Acceleration Data” (page 62) (which refers to the user-acceleration component as “instantaneous motion.”) Your application can also receive the gravity-caused and user-caused components of acceleration directly from Core Motion by receiving and handling device-motion updatesinstead of accelerometer updates. See “Handling Processed Device-Motion Data” (page 72) for information. Handling Rotation-Rate Data A gyroscope measures the rate at which a device rotates around each of the three spatial axes. (Compare this with the accelerometer, which measures the acceleration of the device along each of the three spatial axes.) For each requested gyroscope update, Core Motion takes a biased estimate of the rate of rotation and returns this information to an application in the form of a CMGyroData object. The object has a rotationRate property through which you can access a CMRotationRate structure that capturesthe rotation rate (in radians per second) for each of the three axes. Motion Events Core Motion 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 68Note: The measurement of rotation rate encapsulated by a CMGyroData object is biased. You can obtain a much more accurate (unbiased) measurement by accessing the rotationRate property of CMDeviceMotion. – Z + Z + Y – Y – X + X To start receiving and handling rotation-rate data, create an instance of the CMMotionManager class and call one of the following two methods on it: ● startGyroUpdates Afterthismethod is called, Core Motion continuously updatesthe gyroData property of CMMotionManager with the latest measurement of gyroscope activity. The application periodically samples this property, usually in a render loop that is typical of games. If you adopt this polling approach, you should set the update-interval property (gyroUpdateInterval) to the maximum interval at which Core Motion performs updates. (Core Motion might perform updates at a faster rate, however.) ● startGyroUpdatesToQueue:withHandler: Before calling this method, the application assigns an update interval to the gyroUpdateInterval property. It also creates an instance of NSOperationQueue and implements a block of the CMGyroHandler type that handles the gyroscope updates. Then it calls startGyroUpdatesToQueue:withHandler: on the motion-manager object, passing in the operation queue and the block. At the specified update interval, Core Motion passes the latest sample of gyroscope activity to the block, which executes as a task in the queue. Motion Events Core Motion 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 69The code examples in this section illustrate this approach. You should stop updates of motion data as soon as your application is finished processing the data. Doing so allows Core Motion to turn off motion sensors, thereby saving battery power. When configuring the update interval for rotation-rate (gyroscope) events, identify an intervalsuitable for your application and then assign that value (expressed as seconds) to the gyroUpdateInterval property. If you prefer to think of the update interval in terms of cycles per second (Hertz), divide 1 by the desired Hertz value to get the update-interval value. Listing 4-3 (page 60) in “Choosing an Appropriate Update Interval” (page 61) gives an example in the context of accelerometer updates. The following code segments illustrate how to start gyroscope updates by calling the startGyroUpdatesToQueue:withHandler: method. In Listing 4-9, a view controller in its viewDidLoad instantiates a CMMotionManager object and assigns an update interval for gyroscope data. If the device has a gyroscope, the view controller creates an NSOperationQueue object and defines a block handler for gyroscope updates. Listing 4-9 Creating the CMMotionManager object and setting up for gyroscope updates - (void)viewDidLoad { [super viewDidLoad]; motionManager = [[CMMotionManager alloc] init]; motionManager.gyroUpdateInterval = 1.0/60.0; if (motionManager.gyroAvailable) { opQ = [[NSOperationQueue currentQueue] retain]; gyroHandler = ^ (CMGyroData *gyroData, NSError *error) { CMRotationRate rotate = gyroData.rotationRate; // handle rotation-rate data here...... }; } else { NSLog(@"No gyroscope on device."); toggleButton.enabled = NO; [motionManager release]; } } Motion Events Core Motion 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 70When analyzing rotation-rate data—that is, the fields of the CMRotationMatrix structure—follow the “right-hand rule” to determine the direction of rotation (see Figure 4-2 (page 71)). For example, if you wrap your right hand around the X axis such that the tip of the thumb points toward positive X, a positive rotation is one toward the tips of the other 4 fingers. A negative rotation goes away from the tips of those fingers. Figure 4-2 Right-hand rule When the user taps a button, an action message is sent to the view controller. The view controller implements the action method to toggle between starting updates and stopping updates. Listing 4-10 shows how it does this. Listing 4-10 Starting and stopping gyroscope updates - (IBAction)toggleGyroUpdates:(id)sender { if ([[(UIButton *)sender currentTitle] isEqualToString:@"Start"]) { [motionManager startGyroUpdatesToQueue:opQ withHandler:gyroHandler]; } else { [motionManager stopGyroUpdates]; } } Motion Events Core Motion 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 71Handling Processed Device-Motion Data If a device has an accelerometer and a gyroscope, Core Motion offers a device-motion service that reads raw motion data from both sensors. The service uses sensor fusion algorithms to refine the raw data and generate information on a device’s attitude, its unbiased rotation rate, the direction of gravity on a device, and the acceleration that the user imparts to a device. An instance of the CMDeviceMotion class encapsulates this data. You can access attitude data through the attitude property of a CMDeviceMotion object. An instance of the CMAttitude class encapsulates a measurement of attitude. This class defines three mathematical representations of attitude: ● a quaternion ● a rotation matrix ● the three Euler angles (roll, pitch, and yaw) Because the device-motion service returns gravity and user acceleration as separate items of data, there is no need to filter the acceleration data. To start receiving and handling device-motion updates, create an instance of the CMMotionManager class and call one of the following two methods on it: ● startDeviceMotionUpdates After this method is called, Core Motion continuously updates the deviceMotion property of CMMotionManager with the latest refined measurements of accelerometer and gyroscope activity (as encapsulated in a CMDeviceMotion object). The application periodically samples this property, usually in a render loop that is typical of games. If you adopt this polling approach, you should set the update-interval property (deviceMotionUpdateInterval) to the maximum interval at which Core Motion performs updates. (Core Motion might perform updates at a faster rate, however.) The code examples in this section illustrate this approach. ● startDeviceMotionUpdatesToQueue:withHandler: Before calling this method, the application assigns an update interval to the deviceMotionUpdateInterval property. It also creates an instance of NSOperationQueue and implements a block of the CMDeviceMotionHandler type that handlesthe accelerometer updates. Then it calls startDeviceMotionUpdatesToQueue:withHandler: on themotion-manager object, passing in the operation queue and the block. At the specified update interval, Core Motion passes the latest sample of combined accelerometer and gyroscope activity (asrepresented by a CMDeviceMotion object) to the block, which executes as a task in the queue. Motion Events Core Motion 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 72You should stop updates of motion data as soon as your application is finished processing the data. Doing so allows Core Motion to turn off motion sensors, thereby saving battery power. When configuring the update interval for device-motion events, identify an intervalsuitable for your application and then assign that value (expressed as seconds) to the deviceMotionUpdateInterval property. If you prefer to think of the update interval in terms of cycles per second (Hertz), divide 1 by the desired Hertz value to get the update-interval value. Listing 4-3 (page 60) in “Choosing an Appropriate Update Interval” (page 61) gives an example of this in the context of accelerometer updates. An Example of Handling Device-Motion Data The following code examples are based on the OpenGL ES project template in Xcode. An OpenGL ES application periodically samples device-motion updates using the render loop it sets up for drawing the view. In Listing 4-11, the application creates an instance of CMMotionManager in initWithCoder: and assigns this object to an instance variable. It also specifies a minimum update interval for device-motion data. The application then starts device-motion updates when the OpenGL view schedules the render loop; it stops device-motion updates when the view invalidates that loop. Listing 4-11 Starting and stopping device-motion updates - (id)initWithCoder:(NSCoder*)coder { if ((self = [super initWithCoder:coder])) { motionManager = [[CMMotionManager alloc] init]; motionManager.deviceMotionUpdateInterval = 0.02; // 50 Hz // other initialization code here... } } - (void)startAnimation { if (!animating) { // code that configures and schedules CADisplayLink or timer here ... } if ([motionManager.isDeviceMotionAvailable]) [motionManager startDeviceMotionUpdates]; } - (void)stopAnimation { if (animating) { Motion Events Core Motion 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 73// code that invalidates CADisplayLink or timer here... } if ([motionManager.isDeviceMotionActive]) [motionManager stopDeviceMotionUpdates]; } Note that if device-motion services are not available—most likely because the device lacks a gyroscope—you might want to implement an alternative approach that responds to device motion by handling accelerometer data. Device Attitude and the Reference Frame A particularly useful bit of information yielded by a CMDeviceMotion object is device attitude. From a practical standpoint, an even more useful bit of information is the change in device attitude. The attitude, or spatial orientation of a device is always measured in relation to a reference frame. Core Motion establishesthe reference frame when your application starts device-motion updates. An instance of CMAttitude gives the rotation from thisinitial reference frame to the device's current reference frame. Core Motion'sreference frame is always chosen so that the z-axis is always vertical, and the x-axis and y-axis are always orthogonal to gravity. When expressed in Core Motion's reference frame, gravity is always the vector [0, 0, -1]; this is called the gravity reference. If you multiply the rotation matrix obtained from a CMAttitude object by the gravity reference, you get gravity in the device's frame. Or, mathematically: 0 0 -1 deviceMotion.gravity = R You can change the reference frame used by a CMAttitude instance. To do that, cache the attitude object that containsthat reference frame and passthat asthe argument to multiplyByInverseOfAttitude:. The attitude argument receiving the message is changed to represent the change in attitude from that reference frame. To see how this might be useful, consider a baseball game where the user rotatesthe device to swing. Normally, at the beginning of a pitch, the bat would be atsome resting orientation. After that, the bat would be rendered at an orientation determined by how the device's attitude had changed from where it was at the start of a pitch. Listing 4-12 illustrates how you might do this. Listing 4-12 Getting the change in attitude prior to rendering -(void) startPitch { Motion Events Core Motion 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 74// referenceAttitude is an instance variable referenceAttitude = [motionManager.deviceMotion.attitude retain]; } - (void)drawView { CMAttitude *currentAttitude = motionManager.deviceMotion.attitude; [currentAttitude multiplyByInverseOfAttitude: referenceAttitude]; // render bat using currentAttitude ..... [self updateModelsWithAttitude:currentAttitude]; [renderer render]; } After multiplyByInverseOfAttitude: returns, currentAttitude in this example representsthe change in attitude (that is, the rotation) from referenceAttitude to the most recently sampled CMAttitude instance. Motion Events Core Motion 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 75Remote-control events let users control application multimedia through the system transport controls or through an external accessory. If your application plays audio or video content as a feature, you might want to write the code that enables it to respond to remote-control events. These events originate either from the transport controls or as commands issued by external accessories (such as a headset) that conform to an Apple-provided specification. iOS converts these commands into UIEvent objects that it delivers to an application. The application sends them to the first responder and, if the first responder doesn’t handle them, they go up the responder chain. The following sections describe how to prepare your application for receiving remote-control events and how to handle them. The code examples are taken from the Audio Mixer (MixerHost) sample code project. Preparing Your Application for Remote-Control Events To receive remote-control events, the view or view controller managing the presentation of multimedia content must be the first responder. It (or some other object in the application) must also tell the application object that it is ready to receive remote-control events. To make itself capable of becoming first responder, the view or view controllershould override the UIResponder method canBecomeFirstResponder to return YES. It should also send itself the becomeFirstResponder at an appropriate time, such as (for view controllers) in an override of the viewDidAppear: method. Listing 5-1 shows this call and also shows something else: The view controller calls the beginReceivingRemoteControlEvents method of UIApplication to “turn on” the delivery of remote-control events. Listing 5-1 Preparing to receive remote-control events - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; [[UIApplication sharedApplication] beginReceivingRemoteControlEvents]; [self becomeFirstResponder]; } 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 76 Remote Control of MultimediaWhen the view or view controller is no longer managing audio or video, it should turn off the delivery of remote-control events and resign first-responderstatus by implementing the viewWillDisappear:asshown in Listing 5-2. Listing 5-2 Ending the receipt of remote-control events - (void)viewWillDisappear:(BOOL)animated { [[UIApplication sharedApplication] endReceivingRemoteControlEvents]; [self resignFirstResponder]; [super viewWillDisappear:animated]; } Handling Remote-Control Events To handle remote-control events, the first responder must implement the remoteControlReceivedWithEvent: method declared by UIResponder. The method implementation should evaluate the subtype of each UIEvent object passed in and send the appropriate message to the object presenting the audio or video content. The example in Listing 5-3 sends play, pause, and stop messages to an audio object. Listing 5-3 Handling remote-control events - (void) remoteControlReceivedWithEvent: (UIEvent *) receivedEvent { if (receivedEvent.type == UIEventTypeRemoteControl) { switch (receivedEvent.subtype) { case UIEventSubtypeRemoteControlTogglePlayPause: [self playOrStop: nil]; break; case UIEventSubtypeRemoteControlPreviousTrack: [self previousTrack: nil]; break; case UIEventSubtypeRemoteControlNextTrack: Remote Control of Multimedia Handling Remote-Control Events 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 77[self nextTrack: nil]; break; default: break; } } } Other remote-control UIEvent subtypes are possible. See UIEvent Class Reference for details. You can test your application’s receipt and handling of remote-control events by using the Now Playing Controls. These controls are available on recent models of device (for iPhone, iPhone 3GS and later) that are running iOS 4.0 or later. To access these controls, double-press the Home button, then flick left or right along the bottom of the screen until you find the audio playback controls. These controlssend remote-control events to the application that is currently or was most recently playing audio; the icon to the right of the playback controls represents the application. For testing purposes, you can programmatically make your application begin audio playback and then test the remote-control events sent to your application by tapping the Now Playing Controls. Note that a deployed application should not programmatically begin playback; that should always be done by the user. Remote Control of Multimedia Handling Remote-Control Events 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 78This table describes the changes to Event Handling Guide for iOS . Date Notes 2011-03-10 Made some minor corrections. 2010-09-29 Made some minor corrections and clarifications. 2010-08-12 Corrected code snippet in "Remote Control of Multimedia" Corrected code examples and related text in "Remote Control of Multimedia" chapter. Made other minor corrections. 2010-08-03 Changed the title from "Event Handling Guide for iPhone OS" and changed "iPhone OS" to "iOS" throughout. Updated the section on the Core Motion framework. 2010-07-09 First version of a document that describes how applications can handle multitouch, motion, and other events. 2010-05-18 2011-03-10 | © 2011 Apple Inc. All Rights Reserved. 79 Document Revision HistoryApple Inc. © 2011 Apple Inc. All rights reserved. No part of this publication may be reproduced, stored in a retrievalsystem, or transmitted, in any form or by any means, mechanical, electronic, photocopying, recording, or otherwise, without prior written permission of Apple Inc., with the following exceptions: Any person is hereby authorized to store documentation on a single computer for personal use only and to print copies of documentation for personal use provided that the documentation contains Apple’s copyright notice. No licenses, express or implied, are granted with respect to any of the technology described in this document. Apple retains all intellectual property rights associated with the technology described in this document. This document is intended to assist application developers to develop applications only for Apple-labeled computers. Apple Inc. 1 Infinite Loop Cupertino, CA 95014 408-996-1010 Apple, the Apple logo, iPad, iPhone, iPod, iPod touch, Objective-C, Shake, and Xcode are trademarks of Apple Inc., registered in the U.S. and other countries. Multi-Touch is a trademark of Apple Inc. App Store is a service mark of Apple Inc. OpenGL is a registered trademark of Silicon Graphics, Inc. iOS is a trademark or registered trademark of Cisco in the U.S. and other countries and is used under license. Even though Apple has reviewed this document, APPLE MAKES NO WARRANTY OR REPRESENTATION, EITHER EXPRESS OR IMPLIED, WITH RESPECT TO THIS DOCUMENT, ITS QUALITY, ACCURACY, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.ASARESULT, THISDOCUMENT IS PROVIDED “AS IS,” AND YOU, THE READER, ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND ACCURACY. IN NO EVENT WILL APPLE BE LIABLE FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL,OR CONSEQUENTIAL DAMAGES RESULTING FROM ANY DEFECT OR INACCURACY IN THIS DOCUMENT, even if advised of the possibility of such damages. THE WARRANTY AND REMEDIES SET FORTH ABOVE ARE EXCLUSIVE AND IN LIEU OF ALL OTHERS, ORAL OR WRITTEN, EXPRESS OR IMPLIED. No Apple dealer, agent, or employee is authorized to make any modification, extension, or addition to this warranty. Some states do not allow the exclusion or limitation of implied warranties or liability for incidental or consequential damages, so the above limitation or exclusion may not apply to you. This warranty gives you specific legal rights, and you may also have other rights which vary from state to state. iPod nano Features Guide2 2 Contents Chapter 1 4 iPod nano Basics 5 iPod nano at a Glance 5 Using iPod nano Controls 8 Disabling iPod nano Controls 9 Using iPod nano Menus 10 Connecting and Disconnecting iPod nano 14 About the iPod nano Battery Chapter 2 17 Music Features 17 About iTunes 18 Importing Music into Your iTunes Library 22 Organizing Your Music 22 Adding Music and Podcasts to iPod nano 26 Playing Music 31 Watching and Listening to Podcasts 32 Listening to Audiobooks 32 Listening to FM Radio Chapter 3 33 Video Features 33 Purchasing or Renting Videos and Downloading Video Podcasts 34 Converting Your Own Videos to Work with iPod nano 35 Adding Videos to iPod nano 37 Viewing and Listening to Videos Chapter 4 40 Photo Features 40 Importing Photos 43 Viewing Photos Chapter 5 46 Extra Features and Accessories 46 Using iPod nano as an External Disk 47 Using Extra Settings 51 Syncing Contacts, Calendars, and To-Do Lists 53 Storing and Reading NotesContents 3 54 Recording Voice Memos 54 Learning About iPod nano Accessories Chapter 6 56 Tips and Troubleshooting 56 General Suggestions 61 Updating and Restoring iPod Software Chapter 7 62 Safety and Cleaning 62 Important Safety Information 64 Important Handling Information Chapter 8 65 Learning More, Service, and Support Index 681 4 1 iPod nano Basics Congratulations on purchasing iPod nano. Read this chapter to learn about the features of iPod nano, how to use its controls, and more. To use iPod nano, you put music, videos, photos, and other files on your computer and then add them to iPod nano. iPod nano is a music player and much more. Use iPod nano to:  Sync songs, videos, and digital photos for listening and viewing on the go  Listen to podcasts, downloadable audio and video shows delivered over the Internet  View video on iPod nano, or on a TV using an optional cable  View photos as a slideshow with music on iPod nano, or on a TV using an optional cable  Listen to audiobooks purchased from the iTunes Store or audible.com  Store or back up files and other data, using iPod nano as an external disk  Sync contact, calendar, and to-do list information from your computer  Play games, store text notes, set an alarm, and moreChapter 1 iPod nano Basics 5 iPod nano at a Glance Get to know the controls on iPod nano: Using iPod nano Controls The controls on iPod nano are easy to find and use. Press any button to turn on iPod nano. The main menu appears. Use the Click Wheel and Center button to navigate through onscreen menus, play songs, change settings, and view information. Move your thumb lightly around the Click Wheel to select a menu item. To choose the item, press the Center button. To go back to the previous menu, press Menu on the Click Wheel. Dock connector Menu Previous/Rewind Play/Pause Hold switch Headphones port Click Wheel Next/Fast-forward Center button6 Chapter 1 iPod nano Basics Here’s what else you can do with iPod nano controls. To Do this Turn on iPod nano Press any button. Turn off iPod nano Press and hold Play/Pause (’). Turn on the backlight Press any button or use the Click Wheel. Disable the iPod nano controls (so nothing happens if you press them accidentally) Slide the Hold switch to HOLD (an orange bar appears). Reset iPod nano (if it isn’t responding) Slide the Hold switch to HOLD and back again. Press the Menu and Center buttons at the same time for about 6 seconds, until the Apple logo appears. Choose a menu item Scroll to the item and press the Center button. Go back to the previous menu Press Menu. Go directly to the main menu Press and hold Menu. Browse for a song From the main menu, choose Music. Browse for a video From the main menu, choose Videos. Play a song or video Select the song or video and press the Center or Play/Pause (’) button. iPod nano has to be ejected from your computer to play songs and videos. Pause a song or video Press Play/Pause (’) or unplug your headphones. Change the volume From the Now Playing screen, use the Click Wheel. Play all the songs in a playlist or album Select the playlist or album and press Play/Pause (’). Play all songs in random order From the main menu, choose Shuffle Songs. You can also shuffle songs from the Now Playing screen. Skip to any point in a song or video From the Now Playing screen, press the Center button to show the scrubber bar (a diamond icon on the bar shows the current location), and then scroll to any point in the song or video. Skip to the next song or chapter in an audiobook or podcast Press Next/Fast-forward (‘). Start a song or video over Press Previous/Rewind (]). Play the previous song or chapter in an audiobook or podcast Press Previous/Rewind (]) twice. Fast-forward or rewind a song Press and hold Next/Fast-forward (‘) or Previous/Rewind (]). Add a song to the On-The-Go playlist Select a song in a playlist, and then press and hold the Center button until the song title flashes. Find the iPod nano serial number From the main menu, choose Settings > About and press the Center button until you get to the serial number, or look on the back of iPod nano.Chapter 1 iPod nano Basics 7 Browsing Music Using Cover Flow You can browse your music collection using Cover Flow, a visual way to flip through your library. To use Cover Flow: 1 From the Music menu, choose Cover Flow. 2 Use the Click Wheel to move through your album art or press the Next/Fast-forward and Previous/Rewind buttons. 3 Select an album and press the Center button. 4 Use the Click Wheel to select a song and press the Center button to play it. Scrolling Quickly Through Long Lists If you have more than 100 songs, videos, or other items, you can scroll quickly through a long list by moving your thumb quickly on the Click Wheel. Note: Not all languages are supported. To scroll quickly: 1 Move your thumb quickly on the Click Wheel, to display a letter of the alphabet on the screen. 2 Use the Click Wheel to navigate the alphabet until you find the first letter of the item you’re looking for. This takes you to the first item in the list beginning with that letter. Items beginning with a symbol or number appear before the letter “A.” 3 Lift your thumb momentarily to return to normal scrolling. 4 Use the Click Wheel to finish navigating to the item you want. Searching Music You can search iPod nano for songs, playlists, album titles, artist names, audio podcasts, and audiobooks. The search feature doesn’t search videos, notes, calendar items, contacts, or lyrics. Note: Not all languages are supported. To search iPod nano: 1 From the Music menu, choose Search. 2 Enter a search string by using the Click Wheel to navigate the alphabet and pressing the Center button to enter each character. iPod nano starts searching as soon as you enter the first character, displaying the results on the search screen. For example, if you enter “b,” then iPod nano displays all music items containing the letter “b.” If you enter “ab,” iPod nano displays all items containing that sequence of letters. To enter a space, press the Next/Fast-forward button.8 Chapter 1 iPod nano Basics To delete the previous character, press the Previous/Rewind button. 3 Press Menu to display the results list, which you can now navigate. Items appear in the results list with icons identifying their type: song, video, artist, album, audiobook, or podcast. To return to Search (if Search is highlighted in the menu), press the Center button. Turning off the Click Wheel Sound When you scroll through menu items, you can hear a clicking sound through the iPod nano internal speaker. If you like, you can turn the Click Wheel sound off. To turn off the Click Wheel sound: m Choose Settings and set Clicker to Off. To turn the Click Wheel sound on again, set Clicker to On. Disabling iPod nano Controls If you don’t want to turn iPod nano on or activate controls accidentally, you can make them inactive using the Hold switch. m Slide the Hold switch to HOLD (so you can see the orange bar).Chapter 1 iPod nano Basics 9 Using iPod nano Menus When you turn on iPod nano, you see the main menu. Choose menu items to perform functions or go to other menus. Icons along the top of the screen show iPod nano status. Adding or Removing Items from the Main Menu You might want to add often-used items to the iPod nano main menu. For example, you can add a Songs item to the main menu, so you don’t have to choose Music before you choose Songs. To add or remove items from the main menu: 1 Choose Settings > Main Menu. 2 Choose each item you want to appear in the main menu. A checkmark indicates which items have been added. Setting the Backlight Timer You can set the backlight to turn on and illuminate the screen for a certain amount of time when you press a button or use the Click Wheel. The default is 10 seconds. m Choose Settings > Backlight Timer, and then choose the time you want. Choose “Always On” to prevent the backlight from turning off. Display item Function Menu title Displays the title of the current menu. Lock icon The Lock icon appears when the Hold switch (on the bottom of iPod nano) is set to HOLD. This indicates that the iPod nano controls are disabled. Play status The Play (“) icon appears when a song, video, or other item is playing. The Pause (1) icon appears when the item is paused. Battery status The Battery icon shows the approximate remaining battery charge. Menu items Use the Click Wheel to scroll through menu items. Press the Center button to choose an item. An arrow next to a menu item indicates that choosing it leads to another menu or screen. Menu title Menu items Battery status Play status Lock icon10 Chapter 1 iPod nano Basics Setting the Screen Brightness You can adjust the brightness of the iPod nano screen by moving a slider. m Choose Settings > Brightness, and then use the Click Wheel to move the slider. Moving it to the left dims the screen; moving it to the right increases the screen brightness. You can also set the brightness during a slideshow or video. Press the Center button to bring up or dismiss the brightness slider. Setting the Language iPod nano can be set to use different languages. m Choose Settings > Language, and then choose a language from the list. Getting Information About iPod nano You can get details about your iPod nano, such as how much space is available, how many songs, videos, photos, and other items you have, and the serial number, model, and software version. To get information about iPod nano: m Choose Settings > About, and press the Center button to cycle through the screens of information. Resetting All Settings You can reset all the items on the Settings menu to their default setting. m Choose Settings > Reset Settings, and then choose Reset. Connecting and Disconnecting iPod nano You connect iPod nano to your computer to add music, videos, photos, and files, and to charge the battery. Disconnect iPod nano when you’re done. Connecting iPod nano To connect iPod nano to your computer: m Plug the included iPod Dock Connector to USB 2.0 cable into a high-powered USB 2.0 port on your computer, and then connect the other end to iPod nano. If you have an iPod Dock, you can connect the cable to a USB 2.0 port on your computer, connect the other end to the Dock, and then put iPod nano in the Dock.Chapter 1 iPod nano Basics 11 Note: The USB port on most keyboards doesn’t provide enough power. You must connect iPod nano to a USB 2.0 port on your computer, unless your keyboard has a high-powered USB 2.0 port. By default, iTunes syncs songs on iPod nano automatically when you connect it to your computer. When iTunes is finished, you can disconnect iPod nano. Note: You can sync songs while your battery is charging. If you connect iPod nano to a different computer and it’s set to sync music automatically, iTunes prompts you before syncing any music. If you click Yes, the songs and other audio files already on iPod nano will be erased and replaced with songs and other audio files on the computer iPod nano is connected to. For more information about adding music to iPod nano and using iPod nano with more than one computer, see Chapter 2, “Music Features,” on page 17.12 Chapter 1 iPod nano Basics Disconnecting iPod nano It’s important not to disconnect iPod nano from your computer while music is being synced. You can easily see if it’s OK to disconnect iPod nano by looking at the iPod nano screen. Important: Don’t disconnect iPod nano if you see the “Connected” or “Sync in Progress” messages. You could damage files on iPod nano. If you see one of these messages, you must eject iPod nano before disconnecting it. If you set iPod nano to manage songs manually (see “Managing iPod nano Manually” on page 24) or enable iPod nano for disk use (see “Using iPod nano as an External Disk” on page 46), you must always eject iPod nano before disconnecting it. If you see the main menu or a large battery icon, you can disconnect iPod nano. Important: If you see one of these messages, you must eject iPod nano before disconnecting it.Chapter 1 iPod nano Basics 13 To eject iPod nano: m Click the Eject (C) button next to iPod nano in the list of devices in the iTunes source list. If you’re using a Mac, you can also eject iPod nano by dragging the iPod nano icon on the desktop to the Trash. If you’re using a Windows PC, you can also eject iPod nano in My Computer or by clicking the Safely Remove Hardware icon in the Windows system tray and selecting iPod nano. To disconnect iPod nano: 1 Unplug the headphones if they’re attached. 2 Disconnect the cable from iPod nano. If iPod nano is in the Dock, simply remove it. If your Dock connector is larger than the one shown, squeeze both sides of the connector while removing. You can safely disconnect iPod nano while either of these messages is displayed.14 Chapter 1 iPod nano Basics About the iPod nano Battery iPod nano has an internal, non-user-replaceable battery. For best results, the first time you use iPod nano, let it charge for about three hours or until the battery icon in the status area of the display shows that the battery is fully charged. If iPod nano isn’t used for a while, the battery might need to be charged. The iPod nano battery is 80-percent charged in about 1.5 hours and fully charged in about three hours. If you charge iPod nano while adding files, playing music, viewing videos, or viewing a slideshow, it might take longer. Charging the iPod nano Battery You can charge the iPod nano battery in two ways:  Connect iPod nano to your computer.  Use the Apple USB Power Adapter, available separately. To charge the battery using your computer: m Connect iPod nano to a USB 2.0 port on your computer. The computer must be turned on and not in sleep mode (some Mac models can charge iPod nano while in sleep mode). If the battery icon on the iPod nano screen shows the Charging screen, the battery is charging. If it shows the Charged screen, the battery is fully charged. If you don’t see the charging screen, iPod nano might not be connected to a high-power USB port. Try another USB port on your computer. Chapter 1 iPod nano Basics 15 Important: If a “Charging, Please Wait” or “Connect to Power” message appears on the iPod nano screen, the battery needs to be charged before iPod nano can communicate with your computer. See “If iPod nano displays a “Connect to Power” message” on page 58. If you want to charge iPod nano when you’re away from your computer, you can purchase the Apple USB Power Adapter. To charge the battery using the Apple USB Power Adapter: 1 Connect the AC plug adapter to the power adapter (they might already be connected). 2 Connect the iPod Dock Connector to USB 2.0 cable to the power adapter, and plug the other end of the cable into iPod nano. 3 Plug the power adapter into a working electrical outlet. WARNING: Make sure the power adapter is fully assembled before plugging it into an electrical outlet. AC plug adapter (The plug on your Power Adapter may look different.) USB Power Adapter iPod Dock Connector to USB 2.0 Cable16 Chapter 1 iPod nano Basics Understanding Battery States When iPod nano isn’t connected to a power source, a battery icon in the top-right corner of the iPod nano screen shows approximately how much charge is left. If iPod nano is connected to a power source, the battery icon changes to show that the battery is charging or fully charged. You can disconnect and use iPod nano before it’s fully charged. Note: Rechargeable batteries have a limited number of charge cycles and might eventually need to be replaced. Battery life and number of charge cycles vary by use and settings. For more information, go to www.apple.com/batteries. Battery less than 20% charged Battery about halfway charged Battery fully charged Battery charging (lightning bolt) Battery fully charged (plug)2 17 2 Music Features With iPod nano, you can take your music and audio collection with you wherever you go. Read this chapter to learn about adding music and listening to iPod nano. You use iPod nano by importing songs, audiobooks, movies, TV shows, music videos, and podcasts into your computer and then adding them to iPod nano. Read on to learn more about the steps in this process, including:  Getting music from your CD collection, hard disk, or the iTunes Store (part of iTunes and available in some countries only) into the iTunes application on your computer  Organizing your music and other audio into playlists, if you want  Adding playlists, songs, audiobooks, videos, and podcasts to iPod nano  Listening to music or other audio on the go About iTunes iTunes is the software application you use with iPod nano. iTunes can sync music, audiobooks, podcasts, and more with iPod nano. When you connect iPod nano to your computer, iTunes opens automatically. This guide explains how to use iTunes to download songs and other audio and video to your computer, create personal compilations of your favorite songs (called playlists), add them to iPod nano, and adjust iPod nano settings. iTunes also has many other features. You can make your own CDs that play in standard CD players (if your computer has a CD-recordable drive); listen to streaming Internet radio; watch videos and TV shows; rate songs according to preference; and much more. For information about using these iTunes features, open iTunes and choose Help > iTunes Help.18 Chapter 2 Music Features Importing Music into Your iTunes Library To listen to music on iPod nano, you first need to get that music into iTunes on your computer. There are three ways of getting music and other audio into iTunes:  Purchase music, audiobooks, and videos, or download podcasts online from the iTunes Store.  Import music and other audio from audio CDs.  Add music and other audio that’s already on your computer to your iTunes library. Purchasing Songs and Downloading Podcasts Using the iTunes Store If you have an Internet connection, you can easily purchase and download songs, albums, audiobooks, and videos online using the iTunes Store. You can also subscribe to and download podcasts. To purchase music online using the iTunes Store, you set up an Apple account in iTunes, find the songs you want, and then buy them. If you already have an Apple account, or if you have an America Online (AOL) account (available in some countries only), you can use that account to sign in to the iTunes Store and buy songs. Note: You don’t need an iTunes Store account to download or subscribe to podcasts. To sign in to the iTunes Store: m Open iTunes and then:  If you already have an iTunes account, choose Store > Sign In.  If you don’t already have an iTunes account, choose Store > Create Account and follow the onscreen instructions to set up an Apple account or enter your existing Apple account or AOL account information.Chapter 2 Music Features 19 To find songs, audiobooks, videos, and podcasts: You can browse or search the iTunes Store to find the album, song, or artist you’re looking for. Open iTunes and select iTunes Store in the source list.  To browse the iTunes Store, choose a category (for example, Music) on the left side of the main page in the iTunes Store. You can choose a genre, look at new releases, click one of the featured songs, look at Top Songs and more, or click Browse under Quick Links in the main iTunes Store window.  To browse for podcasts, click the Podcasts link on the left side of the main page in the iTunes Store.  To browse for videos, click the Movies, TV Shows, or Music Videos link on the left side of the main page in the iTunes Store.  To search the iTunes Store, type the name of an album, song, artist, or composer in the search field.  To narrow your search, type something in the search field, press Return or Enter on your keyboard, and then click links in the Search Bar at the top of the results page. For example, to narrow your search to songs and albums, click the Music link.  To search for a combination of items, click Power Search in the Search Results window.  To return to the main page of the iTunes Store, click the Home button in the status line at the top of the window. To buy a song, album, movie, TV show, music video, or audiobook: 1 Select iTunes Store in the source list, and then find the item you want to buy. You can double-click a song or other item to listen to a portion of it and make sure it’s what you want. You can view movie trailers or TV show previews. (If your network connection is slower than 128 kbps, choose iTunes > Preferences, and in the Store pane, select the “Load complete preview before playing” checkbox.) 2 Click Buy Song, Buy Album, Buy Movie, Buy Episode, Buy Video, or Buy Book. Some items have other options, such as TV shows that let you buy a season pass for all episodes. The song or other item is downloaded to your computer and charged to the credit card listed on your Apple or AOL account. To download or subscribe to a podcast: 1 Select iTunes Store in the source list. 2 Click the Podcasts link on the left side of the main page in the iTunes Store. 3 Browse for the podcast you want to download.  To download a single podcast episode, click the Get Episode button next to the episode.20 Chapter 2 Music Features  To subscribe to a podcast, click the Subscribe button next to the podcast graphic. iTunes downloads the most recent episode. As new episodes become available, they are automatically downloaded to iTunes when you connect to the Internet. For more information, see “Adding Podcasts to iPod nano” on page 25 and “Watching and Listening to Podcasts” on page 31. Adding Songs Already on Your Computer to Your iTunes Library If you have songs on your computer encoded in file formats that iTunes supports, you can easily add the songs to iTunes. To add songs on your computer to your iTunes library: m Drag the folder or disk containing the audio files to Library in the iTunes source list (or choose File > Add to Library and select the folder or disk). If iTunes supports the song file format, the songs are automatically added to your iTunes library. You can also drag individual song files to iTunes. Note: Using iTunes for Windows, you can convert nonprotected WMA files to AAC or MP3 format. This can be useful if you have a library of music encoded in WMA format. For more information, open iTunes and choose Help > iTunes Help. Importing Music From Your Audio CDs Into iTunes Follow these instructions to get music from your CDs into iTunes. To import music from an audio CD into iTunes: 1 Insert a CD into your computer and open iTunes. If you have an Internet connection, iTunes gets the names of the songs on the CD from the Internet (if available) and lists them in the window. If you don’t have an Internet connection, you can import your CDs and, later, when you’re connected to the Internet, choose Advanced > Get CD Track Names. iTunes will bring in the track names for the imported CDs. If the CD track names aren’t available online, you can enter the names of the songs manually. For more information, see “Entering Song Names and Other Details” on page 21. With song information entered, you can browse for songs in iTunes or on iPod by title, artist, album, and more. 2 Click to remove the checkmark next to any song you don’t want to import. 3 Click the Import button. The display area at the top of the iTunes window shows how much time it will take to import each song. Note: By default, iTunes plays songs as they are imported. If you’re importing a lot of songs, you might want to stop the songs from playing to improve performance.Chapter 2 Music Features 21 4 To eject the CD, click the Eject (C) button. You cannot eject a CD until the import is done. 5 Repeat these steps for any other CDs with songs you want to import. Entering Song Names and Other Details To enter CD song names and other information manually: 1 Select the first song on the CD and choose File > Get Info. 2 Click Info. 3 Enter the song information. 4 Click Next to enter information for the next song. 5 Click OK when you finish. Adding Lyrics You can enter song lyrics in plain text format into iTunes so that you can view the song lyrics on iPod nano while the song is playing. To enter lyrics into iTunes: 1 Select a song and choose File > Get Info. 2 Click Lyrics. 3 Enter song lyrics in the text box. 4 Click Next to enter lyrics for the next song. 5 Click OK when you finish. For more information, see “Viewing Lyrics on iPod nano” on page 30. Adding Album Artwork Music you purchase from the iTunes Store includes album artwork, which your iPod nano can display. You can add album artwork for music you’ve imported from CDs, if you have the album art on your computer. To add album artwork to iTunes: 1 Select a song and choose File > Get Info. 2 Click Artwork. 3 Click Add, navigate to the artwork file, and click Choose. 4 Use the slider to adjust the size of the artwork. 5 Click Next to add artwork for the next song or album. 6 Click OK when you finish. For more information, see “Viewing Album Artwork on iPod nano” on page 31.22 Chapter 2 Music Features Organizing Your Music Using iTunes, you can organize songs and other items into lists, called playlists, in any way you want. For example, you can make playlists with songs to listen to while exercising, or playlists with songs for a particular mood. You can also make Smart Playlists that update automatically based on rules you define. When you add songs to iTunes that match the rules, they automatically get added to the Smart Playlist. You can make as many playlists as you like using any of the songs in your iTunes library. Adding a song to a playlist or later removing it doesn’t remove it from your library. To make a playlist in iTunes: 1 Click the Add (+) button or choose File > New Playlist. 2 Type a name for the playlist. 3 Click Music in the Library list, and then drag a song or other item to the playlist. To select multiple songs, hold down the Shift key or the Command (x) key on a Mac, or the Shift key or the Control key on a Windows PC, as you click each song. To make a Smart Playlist: m Choose File > New Smart Playlist and define the rules for your playlist. Note: To make playlists on iPod nano when iPod nano isn’t connected to your computer, see “Making On-The-Go Playlists on iPod nano” on page 27. Adding Music and Podcasts to iPod nano After your music is imported and organized in iTunes, you can easily add it to iPod nano. To set how music is added from your computer to iPod nano, you connect iPod nano to your computer, and then use iTunes preferences to choose iPod nano settings.Chapter 2 Music Features 23 You can set iTunes to add music to iPod nano in three ways:  Sync all songs and playlists: When you connect iPod nano, it’s automatically updated to match the songs and other items in your iTunes library. Any other songs on iPod nano are deleted.  Sync selected playlists: When you connect iPod nano, it’s automatically updated to match the songs in playlists you select in iTunes.  Manually add music to iPod nano: When you connect iPod nano, you can drag songs and playlists individually to iPod nano, and delete songs and playlists individually from iPod nano. Using this option, you can add songs from more than one computer without erasing songs from iPod nano. When you manage music yourself, you must always eject iPod nano from iTunes before you can disconnect it. Syncing Music Automatically By default, iPod nano is set to sync all songs and playlists when you connect it to your computer. This is the simplest way to add music to iPod nano. You just connect iPod nano to your computer, let it add songs, audiobooks, videos, and other items automatically, and then disconnect it and go. If you added any songs to iTunes since the last time you connected iPod nano, they are synced with iPod nano. If you deleted songs from iTunes, they are removed from iPod nano. To sync music with iPod nano: m Simply connect iPod nano to your computer. If iPod nano is set to sync automatically, the update begins. Important: The first time you connect iPod nano to a computer, a message asks if you want to sync songs automatically. If you accept, all songs, audiobooks, and videos are erased from iPod nano and replaced with the songs and other items from that computer. If you don’t accept, you can still add songs to iPod nano manually without erasing any of the songs already on iPod nano. While music is being synced from your computer onto iPod nano, the iTunes status window shows progress, and you see a sync icon next to the iPod nano icon in the source list. When the update is done, a message in iTunes says “iPod update is complete.” Syncing Music From Selected Playlists onto iPod nano Setting iTunes to sync selected playlists to iPod nano is useful if the music in your iTunes library doesn’t all fit on iPod nano. Only the music in the playlists you select is synced to iPod nano. To set iTunes to sync music from selected playlists onto iPod nano: 1 In iTunes, select iPod nano in the source list and click the Music tab. 2 Select “Sync music” and then choose “Selected playlists.”24 Chapter 2 Music Features 3 Select the playlists you want. 4 To include music videos and display album artwork, select those options. 5 Click Apply. Note: If “Sync only checked songs and videos” is selected in the Summary pane, iTunes syncs only items that are checked. Managing iPod nano Manually Setting iTunes to let you manage iPod nano manually gives you the most flexibility for managing music and video on iPod nano. You can add and remove individual songs (including music videos) and videos (movies and TV shows). Also, you can add music and videos from multiple computers to iPod nano without erasing items already on iPod nano. Note: Setting iPod nano to manually manage music and video turns off the automatic sync options in the Music, Movies, and TV Shows panes. You cannot manually manage one and automatically sync another at the same time. To set iTunes to let you manage music and video on iPod nano manually: 1 In iTunes, select iPod nano in the source list and click the Summary tab. 2 In the Options section, select “Manually manage music and video.” 3 Click Apply. Note: When you manage songs and video yourself, you must always eject iPod nano from iTunes before you disconnect it. To add a song, video, or other item to iPod nano: 1 Click Music or another Library item in the iTunes source list. 2 Drag a song or other item to the iPod nano icon in the source list. To remove a song, video, or other item from iPod nano: 1 In iTunes, select iPod nano in the source list. 2 Select a song or other item on iPod nano and press the Delete or Backspace key on your keyboard. If you manually remove a song or other item from iPod nano, it isn’t deleted from your iTunes library. To make a new playlist on iPod nano: 1 In iTunes, select iPod nano in the source list, and then click the Add (+) button or choose File > New Playlist. 2 Type a name for the playlist. 3 Click an item, such as Music, in the Library list, and then drag songs or other items to the playlist.Chapter 2 Music Features 25 To add songs to or remove songs from a playlist on iPod nano: m Drag a song to a playlist on iPod nano to add the song. Select a song in a playlist and press the Delete key on your keyboard to delete the song. If you set iTunes to manage music manually, you can reset it later to sync automatically. To reset iTunes to sync all music automatically on iPod nano: 1 In iTunes, select iPod nano in the source list and click the Music tab. 2 Select “Sync music” and then choose “All songs and playlists.” 3 Click Apply. The update begins automatically. Note: If “Only sync checked items” is selected in the Summary pane, iTunes syncs only items that are checked in your Music and other libraries. Adding Podcasts to iPod nano The settings for adding podcasts to iPod nano are unrelated to the settings for adding songs. Podcast update settings don’t affect song update settings, and vice versa. You can set iTunes to automatically sync all or selected podcasts, or you can add podcasts to iPod nano manually. To set iTunes to update the podcasts on iPod nano automatically: 1 In iTunes, select iPod nano in the source list and click the Podcasts tab. 2 In the Podcasts pane, select “Sync … episodes” and choose the number of episodes you want in the pop-up menu. 3 Click “All podcasts” or “Selected podcasts.” If you click “Selected podcasts,” also select the podcasts in the list that you want to sync. 4 Click Apply. When you set iTunes to sync iPod nano podcasts automatically, iPod nano is updated each time you connect it to your computer. Note: If “Only sync checked items” is selected in the Summary pane, iTunes syncs only items that are checked in your Podcasts and other libraries. To manually manage podcasts: 1 In iTunes, select iPod nano in the source list and click the Summary tab. 2 Select “Manually manage music and videos” and click Apply. 3 Select the Podcasts library in the source list and drag the podcasts you want to iPod nano.26 Chapter 2 Music Features Playing Music After you add music and other audio to iPod nano, you can listen to it. Use the Click Wheel and Center button to browse for a song, audiobook, video, or podcast. To browse for and play a song: m Choose Music, browse for a song, and press the Play/Pause button. Note: When you browse for music videos in the Music menu, you only hear the music. When you browse for them in the Videos menu, you also see the video. When a song is playing, the Now Playing screen appears. The following table describes the elements on the Now Playing screen of iPod nano. When you see the Now Playing screen, you can use the Click Wheel to change the volume. You can press the Center button multiple times from the Now Playing screen to get to other information and options, such as the scrubber bar, rating bullets, shuffle settings, lyrics, podcast information, and more. The scrubber bar displays a diamond to show where you are in the track, along with elapsed and remaining times. Press the Menu button to return to the previous screen. Now Playing screen item Function Shuffle (¡) icon Appears if iPod nano is set to shuffle songs or albums. Repeat (⁄) icon Appears if iPod nano is set to repeat all songs. The Repeat Once (!) icon appears if iPod nano is set to repeat one song. Album art Shows the album art, if it’s available. Song information Displays the song title, artist, and album title. Rating Displays stars if you rate the song. Song number Shows the number of the song that’s playing within the current sequence of songs. Song time progress bar Shows the elapsed and remaining times for the song that’s playing. Shuffle icon Repeat icon Song time Song information, rating, and sequence number Album artChapter 2 Music Features 27 Setting iPod nano to Shuffle Songs You can set iPod nano to play songs, albums, or your entire library in random order. To set iPod nano to shuffle and play all your songs: m Choose Shuffle Songs from the iPod nano main menu. iPod nano begins playing songs from your entire music library in random order, skipping audiobooks and podcasts. To set iPod nano to always shuffle songs or albums: 1 Choose Settings from the iPod nano main menu. 2 Set Shuffle to either Songs or Albums. When you set iPod nano to shuffle songs by choosing Settings > Shuffle, iPod nano shuffles songs within the list (for example, album or playlist) you choose to play. When you set iPod nano to shuffle albums, it plays all the songs on an album in order, and then randomly selects another album in the list and plays through it in order. To set shuffle options from the Now Playing screen: m Press the Center button until you see the shuffle icon. Choose Songs, Albums, or Off. Setting iPod nano to Repeat Songs You can set iPod nano to repeat a song over and over, or repeat songs within the list you choose to play. To set iPod nano to repeat songs: m Choose Settings from the iPod nano main menu.  To repeat all songs in the list, set Repeat to All.  To repeat one song over and over, set Repeat to One. Customizing the Music Menu You can add items to or remove them from the Music menu, just as you do with the main menu. For example, you can add a Compilations item to the Music menu, so you can easily choose compilations that are put together from various sources. To add or remove items from the Music menu: 1 Choose Settings > Music Menu. 2 Choose each item you want to appear in the main menu. A checkmark indicates which items have been added. To revert to the original Music menu settings, choose Reset Menu. Making On-The-Go Playlists on iPod nano You can make playlists on iPod nano, called On-The-Go Playlists, when iPod nano isn’t connected to your computer.28 Chapter 2 Music Features To make an On-The-Go playlist: 1 Select a song, and then press and hold the Center button until the song title flashes. 2 Choose other songs you want to add. 3 Choose Music > Playlists > On-The-Go to view and play your list of songs. You can also add a list of songs. For example, to add an album, highlight the album title and press and hold the Center button until the album title flashes. To play songs in the On-The-Go playlist: m Choose Music > Playlists > On-The-Go and choose a song. To remove a song from the On-The-Go playlist: m Select a song in the playlist, and hold down the Center button until the song title flashes. To clear the entire On-The-Go playlist: m Choose Music > Playlists > On-The-Go > Clear Playlist and then click Clear. To save the On-The-Go playlists on iPod nano: m Choose Music > Playlists > On-The-Go > Save Playlist. The first playlist is saved as “New Playlist 1” in the Playlists menu. The On-The-Go playlist is cleared. You can save as many playlists as you like. After you save a playlist, you can no longer remove songs from it. To copy the On-The-Go playlists to your computer: m If iPod nano is set to update songs automatically (see “Syncing Music Automatically” on page 23), and you make an On-The-Go playlist, the playlist is automatically copied to iTunes when you connect iPod nano. You see the new On-The-Go playlist in the list of playlists in iTunes. You can rename, edit, or delete the new playlist, just as you would any playlist in iTunes. Rating Songs You can assign a rating to a song (from 1 to 5 stars) to indicate how much you like it. You can use song ratings to help you create Smart Playlists automatically in iTunes. To rate a song: 1 Start playing the song. 2 From the Now Playing screen, press the Center button until the five Rating bullets appear. 3 Use the Click Wheel to choose a rating (represented by stars). Note: You cannot assign ratings to video podcasts.Chapter 2 Music Features 29 Setting the Maximum Volume Limit You can choose to set a limit for the maximum volume on iPod nano and assign a combination to prevent the setting from being changed. To set the maximum volume limit for iPod nano: 1 Choose Settings > Volume Limit. The volume control shows the current volume. 2 Use the Click Wheel to select the maximum volume limit. You can press Play to hear the currently selected song play while you select the maximum volume limit. 3 Press Play/Pause to set the maximum volume limit. A triangle on the volume bar indicates the maximum volume limit. 4 Press the Menu button to accept the maximum volume limit without requiring a combination to change it. Or, on the Enter Combination screen, set a combination to require that the combination be entered to change the maximum volume limit. 5 To enter a combination:  Use the Click Wheel to select a number for the first position. Press the Center button to confirm your choice and move to the next position.  Use the same method to set the remaining numbers of the combination. You can use the Next/Fast-forward button to move to the next position and the Previous/Rewind button to move to the previous position. Press the Center button in the final position to confirm the entire combination. Note: The volume of songs and other audio may vary depending on how the audio was recorded or encoded. See “Setting Songs to Play at the Same Volume Level” on page 30 for information about how to set a relative volume level in iTunes and on iPod nano. Volume level may also vary if you use different earphones or headphones. With the exception of the iPod Radio Remote, accessories that connect through the iPod Dock Connector don’t support volume limits. If you set a combination, you must enter it before you can change or remove the maximum volume limit. To change the maximum volume limit: 1 Choose Settings > Volume Limit. 2 If you set a combination, enter it by using the Click Wheel to select the numbers and pressing the Center button to confirm them. 3 Use the Click Wheel to change the maximum volume limit. 4 Press the Play/Pause button to accept the change.30 Chapter 2 Music Features To remove the maximum volume limit: 1 If you’re currently listening to iPod nano, press Pause. 2 Choose Settings > Volume Limit. 3 If you set a combination, enter it by using the Click Wheel to select the numbers and pressing the Center button to confirm them. 4 Use the Click Wheel to move the volume limit to the maximum level on the volume bar. This removes any restriction on volume. 5 Press the Play/Pause button to accept the change. Note: If you forget the combination, you can restore iPod nano. See “Updating and Restoring iPod Software” on page 61 for more information. Setting Songs to Play at the Same Volume Level iTunes can automatically adjust the volume of songs, so they play at the same relative volume level. You can set iPod nano to use the iTunes volume settings. To set iTunes to play songs at the same sound level: 1 In iTunes, choose iTunes > Preferences if you’re using a Mac, or choose Edit > Preferences if you’re using a Windows PC. 2 Click Playback and select Sound Check, and then click OK. To set iPod nano to use the iTunes volume settings: m Choose Settings and set Sound Check to On. If you haven’t activated Sound Check in iTunes, setting it on iPod nano has no effect. Using the Equalizer You can use equalizer presets to change the sound on iPod nano to suit a particular music genre or style. For example, to make rock music sound better, set the equalizer to Rock. To use the equalizer to change the sound on iPod nano: m Choose Settings > EQ and choose an equalizer preset. If you assigned an equalizer preset to a song in iTunes and the iPod nano equalizer is set to Off, the song plays using the iTunes setting. See iTunes Help for more information. Viewing Lyrics on iPod nano If you enter lyrics for a song in iTunes (see “Adding Lyrics” on page 21) and then add the song to iPod nano, you can view the lyrics on iPod nano. To view lyrics on iPod nano while a song is playing: m On the Now Playing screen, press the Center button until you see the lyrics. The screen displays the lyrics, which you can scroll through as the song plays.Chapter 2 Music Features 31 Viewing Album Artwork on iPod nano By default, iTunes is set to allow you to view album artwork on iPod nano. If the artwork is available, you’ll see it on iPod nano in the album list and when you play music from the album. To set iTunes to display album artwork on iPod nano: 1 In iTunes, select iPod nano in the source list and click the Music tab. 2 Choose “Display album artwork on your iPod.” To see album artwork on iPod nano: m Play a song that has album artwork. For more information about album artwork, open iTunes and choose Help > iTunes Help. Watching and Listening to Podcasts Podcasts are downloadable audio or video shows you get at the iTunes Store. You can listen to audio podcasts and watch video podcasts. Podcasts are organized by shows, episodes within shows, and chapters within episodes. If you stop watching or listening to a podcast and go back to it later, the podcast begins playing from where you left off. To watch or listen to a podcast: 1 From the main menu, choose Podcasts, and then choose a show. Shows appear in reverse chronological order so that you can watch or listen to the most recent one first. You see a blue dot next to shows and episodes you haven’t watched or listened to yet. 2 Choose an episode to play it. The Now Playing screen displays the show, episode, and date information, along with elapsed and remaining time. Press the Center button to see more information about the podcast. If the podcast includes artwork, you also see a picture. Podcast artwork can change during an episode, so you might see several pictures during the podcast. If the podcast you’re watching or listening to has chapters, you can press the Next/Fast-forward or Previous/Rewind button to skip to the next chapter or the beginning of the current chapter in the podcast. For more information about podcasts, open iTunes and choose Help > iTunes Help. Then search for “podcasts.”32 Chapter 2 Music Features Listening to Audiobooks You can purchase and download audiobooks from the iTunes Store or from audible.com and listen to them on iPod nano. You can use iTunes to add audiobooks to iPod nano the same way you add songs. If you stop listening to an audiobook on iPod nano and go back to it later, the audiobook begins playing from where you left off. iPod nano skips audiobooks when set to shuffle. If the audiobook you’re listening to has chapters, you can press the Next/Fast-forward or Previous/Rewind button to skip to the next chapter or the beginning of the current chapter in the audiobook. You can play audiobooks at speeds faster or slower than normal. To set audiobook play speed: m Choose Settings > Audiobooks and choose a speed. Setting the play speed only affects audiobooks purchased from the iTunes Store or audible.com. Listening to FM Radio You can listen to radio using the optional iPod Radio Remote accessory for iPod nano. iPod Radio Remote attaches to iPod nano using the Dock connector cable. When you’re using iPod Radio Remote, you see a Radio menu item on the iPod nano main menu. For more information, see the iPod Radio Remote documentation.3 33 3 Video Features You can purchase movies, TV shows, and music videos, rent movies, and download video podcasts at the iTunes Store, and then add them to your iPod nano. You can watch videos on iPod nano or on a TV connected to iPod nano. Read this chapter to learn about downloading and viewing videos. Purchasing or Renting Videos and Downloading Video Podcasts To purchase videos—movies, TV shows, and music videos—or rent movies online from the iTunes Store (part of iTunes and available in some countries only), you set up an Apple account in iTunes, find the videos you want, and then buy or rent them. If you already have an Apple account, or if you have an America Online (AOL) account (available in some countries only), you can use that account to sign in to the iTunes Store and buy videos or rent movies. To sign in to the iTunes Store: m Open iTunes and then:  If you already have an iTunes account, choose Store > Sign In.  If you don’t already have an iTunes account, choose Store > Create Account and follow the onscreen instructions to set up an Apple account or enter your existing Apple account or AOL account information.34 Chapter 3 Video Features To browse videos in the iTunes Store: 1 In iTunes, select iTunes Store in the source list. 2 Click an item (Movies, TV Shows, or Music Videos) in the iTunes Store list on the left. You can also find some music videos as part of an album or other offer. Videos in iTunes and in the iTunes Store have a display ( ) icon next to them. To buy or rent a video: 1 Select iTunes Store in the source list, and then find the item you want to buy or rent. 2 Click Buy Video, Buy Episode, Buy Season, Buy Movie, or Rent Movie. Purchased videos appear when you select Movies (under Library) or Purchased (under Store) in the source list. Rented videos appear when you select Rented Movies (under Library). To download a video podcast: Video podcasts appear alongside other podcasts in the iTunes Store. You can subscribe to them and download them just as you would other podcasts. You don’t need an iTunes Store account to download podcasts. See “Purchasing Songs and Downloading Podcasts Using the iTunes Store” on page 18 for instructions. Converting Your Own Videos to Work with iPod nano You can view other video files on iPod nano, such as videos you create in iMovie on a Mac or videos you download from the Internet. Import the video into iTunes, convert it for use with iPod nano, if necessary, and then add it to iPod nano. iTunes supports all the video formats that QuickTime supports. For more information, choose Help > QuickTime Player Help from the QuickTime Player menu bar. To import a video into iTunes: m Drag the video file to your iTunes library. Some videos may be ready for use with iPod nano after you import them to iTunes. If you try to add a video to iPod nano (see “Syncing Videos Automatically” on page 35 for instructions), and a message says the video can’t play on iPod nano, then you must convert the video for use with iPod nano. To convert a video for use with iPod nano: 1 Select the video in your iTunes library. 2 Choose Advanced > “Convert Selection to iPod.” Depending on the length and content of a video, converting it for use with iPod nano can take several minutes to several hours. Note: When you convert a video for use with iPod nano, the original video remains in your iTunes library. Chapter 3 Video Features 35 For more information about converting video for iPod nano, go to www.info.apple.com/kbnum/n302758. Adding Videos to iPod nano You add movies and TV shows to iPod nano much the same way you add songs. You can set iTunes to sync all movies and TV shows to iPod nano automatically when you connect iPod nano, or you can set iTunes to sync only selected playlists. Alternatively, you can manage movies and TV shows manually. Using this option, you can add videos from more than one computer without erasing videos already on iPod nano. Note: Music videos are managed with songs, under the Music tab in iTunes. See “Adding Music and Podcasts to iPod nano” on page 22. Important: If you rent a movie from the iTunes Store and add it to iPod nano, you will only be able to view it on iPod nano. Once you add a rented movie to iPod nano, it can’t be transferred again. Syncing Videos Automatically By default, iPod nano is set to sync all videos when you connect it to your computer. This is the simplest way to add videos to iPod nano. You just connect iPod nano to your computer, let it add videos and other items automatically, and then disconnect it and go. If you added any videos to iTunes since the last time you connected iPod nano, they are added to iPod nano. If you deleted videos from iTunes, they are removed from iPod nano. You can set iPod nano to sync videos automatically when you connect it to your computer. To sync videos to iPod nano: m Simply connect iPod nano to your computer. If iPod nano is set to sync automatically, the syncing begins.36 Chapter 3 Video Features Important: The first time you connect iPod nano to a different computer and have the automatic sync option set, a message asks if you want to sync songs and videos automatically. If you accept, all songs, videos, and other items are deleted from iPod nano and replaced with the songs, videos, and other items in the iTunes library on that computer. If you don’t accept, you can still add videos to iPod nano manually without deleting any of the videos already on iPod nano. iTunes includes a feature to sync purchased items from iPod nano to another computer. For more information, see iTunes Help. While videos are being synced from your computer to iPod nano, the iTunes status window shows progress and the iPod nano icon in the source list flashes red. When the update is done, a message in iTunes says “iPod update is complete.” Syncing Selected Videos to iPod nano Setting iTunes to sync selected videos to iPod nano is useful if you have more videos in your iTunes library than will fit on iPod nano. Only the videos you specify are synced with iPod nano. You can sync selected videos or selected playlists that contain videos. To set iTunes to sync unwatched or selected movies to iPod nano: 1 In iTunes, select iPod nano in the source list and click the Movies tab. 2 Select “Sync movies.” 3 Select the movies or playlists you want. Unwatched movies: Select “… unwatched movies” and choose the number you want from the pop-up menu. Selected movies or playlists: Click “Selected …,” choose “movies” or “playlists” from the pop-up menu, and then select the movies or playlists you want. 4 Click Apply. Note: If “Only sync checked items” is selected in the Summary pane, iTunes syncs only items that are checked in your Movies and other libraries. To set iTunes to sync most recent episodes or selected TV shows to iPod nano: 1 In iTunes, select iPod nano in the source list and click the TV Shows tab. 2 Select “Sync … episodes” and choose the number of episodes you want from the popup menu. 3 Click “Selected …” and choose “TV shows” or “playlists” from the pop-up menu. 4 Select the movies or playlists you want to sync. 5 Click Apply. Note: If “Only sync checked items” is selected in the Summary pane, iTunes syncs only items that are checked in your TV Shows and other libraries.Chapter 3 Video Features 37 Managing Videos Manually Setting iTunes to let you manage iPod nano manually gives you the most flexibility for managing videos on iPod nano. You can add and remove movies, TV shows, and other items individually. You can also add videos from multiple computers to iPod nano without removing videos already on iPod nano. See “Managing iPod nano Manually” on page 24. Adding Video Podcasts to iPod nano You add video podcasts to iPod nano the same way you add other podcasts (see page 25). If a podcast has a video component, the video plays when you choose it from Podcasts. If you set iTunes to manage movies and TV shows manually, you can reset iTunes later to sync them automatically. If you set iTunes to sync automatically after you’ve been manually managing iPod nano, you lose any items on iPod nano that aren’t part of your iTunes library. To reset iTunes to sync all movies automatically on iPod nano: 1 In iTunes, select iPod nano in the source list and click the Movies tab. 2 Select “Sync movies” and then select “All movies.” 3 Click Apply. Note: If “Only sync checked items” is selected in the Summary pane, iTunes syncs only items that are checked in your Movies and other libraries. To reset iTunes to sync all TV shows automatically on iPod nano: 1 In iTunes, select iPod nano in the source list and click the TV Shows tab. 2 Select “Sync … episodes” and choose “all” from the pop-up menu. 3 Select “All TV shows.” 4 Click Apply. Note: If “Only sync checked items” is selected in the Summary pane, iTunes syncs only items that are checked in your TV Shows and other libraries. Viewing and Listening to Videos You can view and listen to videos on iPod nano. If you have an AV cable from Apple (available separately at www.apple.com/ipodstore), you can watch videos from iPod nano on TV.38 Chapter 3 Video Features Viewing and Listening to Videos on iPod nano Videos you add to iPod nano appear in the Videos menus. Music videos also appear in Music menus. To view a video on iPod nano: m Choose Videos and browse for a video. When you play the video, you see and hear it. To listen to a music video’s sound or a video podcast’s sound without playing the video: m Choose Music and browse for a music video or a video podcast. When you play the video, you hear it but don’t see the video. Watching Videos on a TV Connected to iPod nano If you have an AV cable from Apple, you can watch videos on a TV connected to your iPod nano. First you set iPod nano to display videos on a TV, then connect iPod nano to your TV, and then play a video. Note: Use the Apple Component AV Cable, the Apple Composite AV Cable, or the Apple AV Connection Kit. Other similar RCA-type cables might not work. You can purchase the cables at www.apple.com/ipodstore. To set iPod nano to display videos on a TV: m Choose Videos > Settings, and then set TV Out to Ask or On. If you set TV Out to Ask, iPod nano gives you the option of displaying videos on TV or on iPod nano every time you play a video. You can also set video to display full screen or widescreen, and set video to display on PAL or NTSC devices. To set TV settings: m Choose Videos > Settings, and then follow the instructions below. To set Do this Video to display on PAL or NTSC TVs Set TV Signal to PAL or NTSC. PAL and NTSC refer to TV broadcast standards. Your TV might use either of these, depending on the region where it was purchased. If you aren’t sure which your TV uses, check the documentation that came with your TV. The format of your external TV Set TV Screen to Widescreen for 16:9 format or Standard for 4:3 format. Video to fit to your screen Set “Fit to Screen” to On. If you set “Fit to Screen” to Off, widescreen videos display in letterbox format on iPod nano or a standard (4:3) TV screen. Captions to display Set Captions to On.Chapter 3 Video Features 39 To use the Apple Component AV Cable to connect iPod nano to your TV: 1 Plug the red, green, and blue video connectors into the component video input (Y, Pb, and Pr) ports on your TV. You can also use the Apple Composite AV cable. If you do, plug in the yellow video connector into the video input port on your TV. Your TV must have RCA video and audio ports. 2 Plug the white and red audio connectors into the left and right analog audio input ports, respectively, on your TV. 3 Plug the iPod Dock Connector into your iPod nano or Universal Dock. 4 Plug the USB connector into your USB Power Adapter or your computer to keep your iPod nano charged. 5 Turn on iPod nano and your TV or receiver to start playing. Make sure you set TV Out on your iPod nano to On. Note: The ports on your TV or receiver may differ from the ports in the illustration. To view a video on your TV: 1 Connect iPod nano to your TV (see above). 2 Turn on your TV and set it to display from the input ports connected to iPod nano. See the documentation that came with your TV for more information. 3 On iPod nano, choose Videos and browse for a video. USB Power Adapter iPod Left audio (white) Dock Connector USB connector Television Video in (Y, Pb, Pr) Right audio (red)4 40 4 Photo Features You can import digital photos to your computer and add them to iPod nano. You can view your photos on iPod nano or as a slideshow on your TV. Read this chapter to learn about importing and viewing photos. Importing Photos You can import digital photos from a digital camera to your computer, and then add them to iPod nano for viewing. You can connect iPod nano to a TV and view photos as a slideshow with music. Importing Photos from a Camera to Your Computer You can import photos from a digital camera or a photo card reader. To import photos to a Mac using iPhoto: 1 Connect the camera or photo card reader to your computer. Open iPhoto (located in the Applications folder) if it doesn’t open automatically. 2 Click Import. Images from the camera are imported into iPhoto. You can import other digital images into iPhoto, such as images you download from the web. For more information about importing and working with photos and other images, open iPhoto and choose Help > iPhoto Help.Chapter 4 Photo Features 41 iPhoto is available for purchase as part of the iLife suite of applications at www.apple.com/ilife. iPhoto might already be installed on your Mac, in the Applications folder. If you don’t have iPhoto, you can import photos using Image Capture. To import photos to a Mac using Image Capture: 1 Connect the camera or photo card reader to your computer. 2 Open Image Capture (located in the Applications folder) if it doesn’t open automatically. 3 To choose specific items to import, click Download Some. Or to download all items, click Download All. To import photos to a Windows PC: m Follow the instructions that came with your digital camera or photo application. Adding Photos From Your Computer to iPod nano You can add photos to iPod nano from a folder on your hard disk. If you have a Mac and iPhoto 4.0.3 or later, you can sync iPhoto albums automatically. If you have a Windows PC and Adobe Photoshop Album 2.0 or later, or Adobe Photoshop Elements 3.0 or later, you can sync photo collections automatically. Adding photos to iPod nano the first time might take some time, depending on how many photos are in your photo library. To sync photos from a Mac or Windows PC to iPod nano using a photo application: 1 In iTunes, select iPod nano in the source list and click the Photos tab. 2 Select “Sync photos from: …”  On a Mac, choose iPhoto from the pop-up menu.  On a Windows PC, choose Photoshop Album or Photoshop Elements from the pop-up menu. Note: Some versions of Photoshop Album and Photoshop Elements don’t support collections. You can still use them to add all your photos.42 Chapter 4 Photo Features 3 If you want to add all your photos, select “All photos and albums.” If you want to keep your photos organized by event, select “… events” and choose an option from the popup menu. If you want to add photos from only certain albums, select “Selected albums” and select the albums you want. 4 Click Apply. Each time you connect iPod nano to your computer, photos are synced automatically. To add photos from a folder on your hard disk to iPod nano: 1 Drag the images you want into a folder on your computer. If you want images to appear in separate photo albums on iPod nano, create folders inside the main image folder, and drag images into the new folders. 2 In iTunes, select iPod nano in the source list and click the Photos tab. 3 Select “Sync photos from: …” 4 Choose “Choose Folder” from the pop-up menu and select your image folder. 5 Click Apply. When you add photos to iPod nano, iTunes optimizes the photos for viewing. Full-resolution image files aren’t transferred by default. Adding full-resolution image files is useful, for example if you want to move them from one computer to another, but isn’t necessary for viewing the images at full quality on iPod nano. To add full-resolution image files to iPod nano: 1 In iTunes, select iPod nano in the source list and click the Photos tab. 2 Select “Include full-resolution photos.” 3 Click Apply. iTunes copies the full-resolution versions of the photos to the Photos folder on iPod nano. To delete photos from iPod nano: 1 In iTunes, select iPod nano in the source list and click the Photos tab. 2 Select “Sync photos from: …”  On a Mac, choose iPhoto from the pop-up menu.  On a Windows PC, choose Photoshop Album or Photoshop Elements from the pop-up menu. 3 Choose “Selected albums” and deselect the albums you no longer want on iPod nano. 4 Click Apply.Chapter 4 Photo Features 43 Adding Photos from iPod nano to a Computer If you add full-resolution photos from your computer to iPod nano using the previous steps, they’re stored in a Photos folder on iPod nano. You can connect iPod nano to a computer and put these photos onto the computer. iPod nano must be enabled for disk use (see “Using iPod nano as an External Disk” on page 46). To add photos from iPod nano to a computer: 1 Connect iPod nano to the computer. 2 Drag image files from the Photos folder or DCIM folder on iPod nano to the desktop or to a photo editing application on the computer. Note: You can also use a photo editing application, such as iPhoto, to add photos stored in the Photos folder. See the documentation that came with the application for more information. To delete photos from the Photos folder on iPod nano: 1 Connect iPod nano to the computer. 2 Navigate to the Photos folder on iPod nano and delete the photos you no longer want. Viewing Photos You can view photos on iPod nano manually or as a slideshow. If you have an optional AV cable from Apple (for example, Apple Component AV Cable), you can connect iPod nano to a TV and view photos as a slideshow with music. Viewing Photos on iPod nano To view photos on iPod nano: 1 On iPod nano, choose Photos > All Photos. Or choose Photos and a photo album to see only the photos in the album. Thumbnail views of the photos might take a moment to appear. 2 Select the photo you want and press the Center button to view a full-screen version.44 Chapter 4 Photo Features From any photo-viewing screen, use the Click Wheel to scroll through photos. Press the Next/Fast-forward or Previous/Rewind button to skip to the next or previous screen of photos. Press and hold the Next/Fast-forward or Previous/Rewind button to skip to the last or first photo in the library or album. Viewing Slideshows You can view a slideshow, with music and transitions if you choose, on iPod nano. If you have an optional AV cable from Apple, you can view the slideshow on a TV. To set slideshow settings: m Choose Photos > Settings, and then follow these instructions: To set Do this Slideshows to display on iPod nano Set TV Out to Ask or Off. Slideshows to display on TV Set TV Out to Ask or On. If you set TV Out to Ask, iPod nano gives you the option of showing slideshows on TV or on iPod nano every time you start a slideshow. How long each slide is shown Choose Time Per Slide and pick a time. The music that plays during slideshows Choose Music and choose a playlist. If you’re using iPhoto, you can choose From iPhoto to copy the iPhoto music setting. Only the songs that you’ve added to iPod nano play. Slides to repeat Set Repeat to On. Slides to display in random order Set Shuffle Photos to On. Slides to display with transitions Choose Transitions and choose a transition type. Slides to show on PAL or NTSC TVs Set TV Signal to PAL or NTSC. PAL and NTSC refer to TV broadcast standards. Your TV might use either of these, depending on the region where it was purchased. If you aren’t sure which your TV uses, check the documentation that came with your TV.Chapter 4 Photo Features 45 To view a slideshow on iPod nano: m Select any photo, album, or roll, and press the Play/Pause button. Or select any full-screen photo and press the Center button. To pause, press the Play/Pause button. To skip to the next or previous photo, press the Next/Fast-forward or Previous/Rewind button. To connect iPod nano to a TV: 1 Connect the optional Apple Component or Composite AV cable to iPod nano. Note: Use the Apple Component AV Cable, Apple Composite AV Cable, or Apple AV Connection Kit. Other similar RCA-type cables won’t work. You can purchase the cables at www.apple.com/ipodstore. 2 Connect the video and audio connectors to the ports on your TV (for an illustration, see page 39). Your TV must have RCA video and audio ports. To view a slideshow on a TV: 1 Connect iPod nano to a TV (see above). 2 Turn on your TV and set it to display from the input ports connected to iPod nano. See the documentation that came with your TV for more information. 3 On iPod nano, select any photo or album and press the Play/Pause button. Or select any full-screen photo and press the Center button. To pause, press the Play/Pause button. To skip to the next or previous photo, press the Next/Fast-forward or Previous/ Rewind button. If you selected a playlist in Photos > Settings > Music, the playlist plays automatically when you start the slideshow. The photos display on your TV and advance automatically according to settings in the Slideshow > Settings menu.5 46 5 Extra Features and Accessories iPod nano can do a lot more than play songs. And you can do a lot more with it than listen to music. Read this chapter to find out more about the extra features of iPod nano, including how to use it as an external disk, alarm, or sleep timer; show the time of day in other parts of the world; display notes; and sync contacts, calendars, and to-do lists. Learn about how to use iPod nano as a stopwatch and to lock the screen, and about the accessories available for iPod nano. Using iPod nano as an External Disk You can use iPod nano as an external disk to store data files. Note: To add music and other audio or video files to iPod nano, you must use iTunes. For example, you won’t see songs you add using iTunes in the Mac Finder or in Windows Explorer. Likewise, if you copy music files to iPod nano in the Mac Finder or Windows Explorer, you won’t be able to play them on iPod nano. To enable iPod nano as an external disk: 1 In iTunes, select iPod nano in the source list and click the Summary tab. 2 In the Options section, select “Enable disk use.” 3 Click Apply. When you use iPod nano as an external disk, the iPod nano disk icon appears on the desktop on Mac, or as the next available drive letter in Windows Explorer on a Windows PC. Note: Clicking Summary and selecting “Manually manage music and videos” in the Options section also enables iPod nano to be used as an external disk. Drag files to and from iPod nano to copy them. If you use iPod nano primarily as a disk, you might want to keep iTunes from opening automatically when you connect iPod nano to your computer.Chapter 5 Extra Features and Accessories 47 To prevent iTunes from opening automatically when you connect iPod nano to your computer: 1 In iTunes, select iPod nano in the source list and click the Summary tab. 2 In the Options section, deselect “Open iTunes when this iPod is connected.” 3 Click Apply. Using Extra Settings You can set the date and time, clocks in different time zones, and alarm and sleep features on iPod nano. You can use iPod nano as a stopwatch or to play games, and you can lock the iPod nano screen. Setting and Viewing the Date and Time The date and time are set automatically from your computer’s clock when you connect iPod nano, but you can change the settings. To set date and time options: 1 Choose Settings > Date & Time. 2 Choose one or more of the following options: Adding Clocks for Other Time Zones To add clocks for other time zones: 1 Choose Extras > Clocks. 2 On the Clocks screen, click the Center button and choose Add. 3 Choose a region and then choose a city. The clocks you add appear in a list. The last clock you added appears last. To Do this Set the date Choose Date. Use the Click Wheel to change the selected value. Press the Center button to move to the next value. Set the time Choose Time. Use the Click Wheel to change the selected value. Press the Center button to move to the next value. Specify the time zone Choose Time Zone and use the Click Wheel to select a city in another time zone. Specify the status of Daylight Savings Time (DST) Choose DST and press the Center button to turn DST on or off. Display the time in 24-hour format Choose 24 Hour Clock and press the Center button to turn the 24-hour format on or off. Display the time in the title bar Choose Time in Title and press the Center button to turn the option on or off. 48 Chapter 5 Extra Features and Accessories To delete a clock: 1 Choose Extras > Clocks. 1 Choose the clock. 2 Choose Delete. Setting the Alarm You can set an alarm for any clock on iPod nano. To use iPod nano as an alarm clock: 1 Choose Extras > Alarms. 2 Choose Create Alarm and set one or more of the following options: To delete an alarm: 1 Choose Extras > Alarms. 2 Choose the alarm and then choose Delete. Setting the Sleep Timer You can set iPod nano to turn off automatically after playing or other content for a specific period of time. To set the sleep timer: 1 Choose Extras > Alarms. 2 Choose Sleep Timer and choose how long you want iPod nano to play. Using the Stopwatch You can use the stopwatch as you exercise to track your overall time and, if you’re running on a track, your lap times. You can play music while you use the stopwatch. To Do this Turn the alarm on Choose Alarm and choose On. Set the time Choose Time. Use the Click Wheel to change the selected value. Press the Center button to move to the next value. Set the date Choose Date. Use the Click Wheel to change the selected value. Press the Center button to move to the next value. Choose a sound Choose Tones or a playlist. If you choose Tones, select Beep to hear the alarm through the internal speaker. If you choose a playlist, you’ll need to connect iPod nano to speakers or headphones to hear the alarm. Set a repeat option Choose Repeat and choose an option (for example, “weekdays”). Name the alarm Choose Label and choose an option (for example, “Wake up”).Chapter 5 Extra Features and Accessories 49 To use the stopwatch: 1 Choose Extras > Stopwatch. 2 Press the Play/Pause button to start the timer. 3 Press the Center button to record lap times. Up to three lap times show beneath the overall time. 4 Press the Play/Pause button to stop the overall timer, or choose Resume to start the timer again. 5 Choose New Timer to start a new stopwatch session. Note: After you start the stopwatch, iPod nano stays on as long as you display the Timer screen and the timer continues to run. If you start the stopwatch and then go to another menu, and iPod nano isn’t playing music or a video, the stopwatch timer stops and iPod nano turns off automatically after a few minutes. To review or delete a logged stopwatch session: 1 Choose Extras > Stopwatch. The current log and a list of saved sessions appear. 2 Choose a log to view session information. iPod nano stores stopwatch sessions with dates, times, and lap statistics. You see the date and time the session started; the total time of the session; the shortest, longest, and average lap times; and the last several lap times. 3 Press the Center button and choose Delete Log to delete the chosen log, or Clear Logs to delete all current logs. Playing Games iPod nano comes with three games: iQuiz, Klondike, and Vortex. To play a game: m Choose Extras > Games and choose a game. You can purchase additional games from the iTunes Store (in some countries) to play on iPod nano. After purchasing games in iTunes, you can add them to iPod nano by syncing them automatically or by managing them manually. To buy a game: 1 In iTunes, select iTunes Store in the source list. 2 Choose iPod Games from the iTunes Store list. 3 Select the game you want and click Buy Game.50 Chapter 5 Extra Features and Accessories To sync games automatically to iPod nano: 1 In iTunes, select iPod nano in the source list and click the Games tab. 2 Select “Sync games.” 3 Click “All games” or “Selected games.” If you click “Selected games,” also select the games you want to sync. 4 Click Apply. Locking the iPod nano Screen You can set a combination to prevent iPod nano from being used by someone without your permission. When you lock an iPod nano that isn’t connected to a computer, you must enter a combination to unlock and use it. Note: This is different from the Hold button in that the Hold button prevents iPod nano buttons from being pressed accidentally. The combination prevents another person from using iPod nano. To set a combination for iPod nano: 1 Choose Extras > Screen Lock. 2 On the New Combination screen, enter a combination:  Use the Click Wheel to select a number for the first position. Press the Center button to confirm your choice and move to the next position.  Use the same method to set the remaining numbers of the combination. You can use the Next/Fast-forward button to move to the next position and the Previous/Rewind button to move to the previous position. Press the Center button in the final position. 3 On the Confirm Combination screen, enter the combination to confirm it, or press Menu to exit without locking the screen. When you finish, you return to the Screen Lock screen, where you can lock the screen or reset the combination. Press the Menu button to exit without locking the screen. To lock the iPod nano screen: m Choose Extras > Screen Lock > Lock. If you just finished setting your combination, Lock will already be selected on the screen. Just press the Center button to lock iPod. When the screen is locked, you see a picture of a lock. Note: You might want to add the Screen Lock menu item to the main menu so that you can quickly lock the iPod nano screen. See “Adding or Removing Items from the Main Menu” on page 9.Chapter 5 Extra Features and Accessories 51 When you see the lock on the screen, you can unlock the iPod nano screen in two ways:  Press the Center button to enter the combination on iPod nano. Use the Click Wheel to select the numbers and press the Center button to confirm them. If you enter the wrong combination, the lock remains. Try again.  Connect iPod nano to the primary computer you use it with, and iPod nano automatically unlocks. Note: If you try these methods and you still can’t unlock iPod nano, you can restore iPod nano. See “Updating and Restoring iPod Software” on page 61. To change a combination you’ve already set: 1 Choose Extras > Screen Lock > Reset. 2 On the Enter Combination screen, enter the current combination. 3 On the New Combination screen, enter and confirm a new combination. Note: If you can’t remember the current combination, the only way to clear it and enter a new one is to restore the iPod nano software. See “Updating and Restoring iPod Software” on page 61. Syncing Contacts, Calendars, and To-Do Lists iPod nano can store contacts, calendar events, and to-do lists for viewing on the go. If you’re using Mac OS X v10.4 or later, you can use iTunes to sync the contact and calendar information on iPod nano with Address Book and iCal. If you’re using any version of Mac OS X earlier than 10.4, you can use iSync to sync your information. Syncing information using iSync requires iSync 1.1 or later, and iCal 1.0.1 or later. If you’re using Windows 2000 or Windows XP, and you use Windows Address Book or Microsoft Outlook 2003 or later to store your contact information, you can use iTunes to sync the address book information on iPod nano. If you use Microsoft Outlook 2003 or later to keep a calendar, you can also sync calendar information. To sync contacts or calendar information using Mac OS X v10.4 or later: 1 Connect iPod nano to your computer. 2 In iTunes, select iPod nano in the source list and click the Contacts tab. 3 Do one of the following:  To sync contacts, in the Contacts section, select “Sync Address Book contacts,” and select an option:  To sync all contacts automatically, select “All contacts.”  To sync selected groups of contacts automatically, select “Selected groups” and select the groups you want to sync.52 Chapter 5 Extra Features and Accessories  To copy contacts’ photos to iPod nano, when available, select “Include contacts’ photos.” When you click Apply, iTunes updates iPod nano with the Address Book contact information you specified.  To sync calendars, in the Calendars section, select “Sync iCal calendars,” and choose an option:  To sync all calendars automatically, choose “All calendars.”  To sync selected calendars automatically, choose “Selected calendars” and select the calendars you want to sync. When you click Apply, iTunes updates iPod nano with the calendar information you specified. To sync contacts and calendars with a Mac and iSync using a version of Mac OS X earlier than v10.4: 1 Connect iPod nano to your computer. 2 Open iSync and choose Devices > Add Device. You need to do this step only the first time you use iSync with iPod nano. 3 Select iPod nano and click Sync Now. iSync puts information from iCal and Mac Address Book onto iPod nano. The next time you want to sync iPod nano, you can simply open iSync and click Sync Now. You can also choose to have iPod nano sync automatically when you connect it. Note: iSync syncs information from your computer with iPod nano. You can’t use iSync to sync information from iPod nano to your computer. To sync contacts or calendars using Windows Address Book or Microsoft Outlook for Windows: 1 Connect iPod nano to your computer. 2 In iTunes, select iPod nano in the source list and click the Contacts tab. 3 Do one of the following:  To sync contacts, in the Contacts section, select “Sync contacts from” and choose Windows Address Book or Microsoft Outlook from the pop-up menu. Then select which contact information you want to sync.  To sync calendars from Microsoft Outlook, in the Calendars section, select “Sync calendars from Microsoft Outlook.” 4 Click Apply. You can also add contact and calendar information to iPod nano manually. iPod nano must be enabled as an external disk (see “Using iPod nano as an External Disk” on page 46).Chapter 5 Extra Features and Accessories 53 To add contact information manually: 1 Connect iPod nano and open your favorite email or contacts application. You can add contacts using Palm Desktop, Microsoft Outlook, Microsoft Entourage, and Eudora, among others. 2 Drag contacts from the application’s address book to the Contacts folder on iPod nano. In some cases, you might need to export contacts and then drag the exported file or files to the Contacts folder. See the documentation for your email or contacts application. To add appointments and other calendar events manually: 1 Export calendar events from any calendar application that uses the standard iCal format (filenames end in .ics) or vCal format (filenames end in .vcs). 2 Drag the files to the Calendars folder on iPod nano. Note: To add to-do lists to iPod nano manually, save them in a calendar file with a .ics or .vcs extension. To view contacts on iPod nano: m Choose Extras > Contacts. To sort contacts by first or last name: m Choose Settings > Sort By, and press the Center button to choose First or Last. To view calendar events: m Choose Extras > Calendars. To view to-do lists: m Choose Extras > Calendars > To Do’s. Storing and Reading Notes You can store and read text notes on iPod nano if it’s enabled as an external disk (see page 46). 1 Save a document in any word-processing application as a text (.txt) file. 2 Place the file in the Notes folder on iPod nano. To view notes: m Choose Extras > Notes.54 Chapter 5 Extra Features and Accessories Recording Voice Memos You can record voice memos using an optional iPod nano-compatible microphone (available for purchase at www.apple.com/ipodstore). You can store voice memos on iPod nano and sync them with your computer. You can set iPod nano to record at lowquality mono (22.05 kHz) to save space, or high-quality stereo (44.1 kHz) for better sound. Note: Voice memos cannot be longer than two hours. If you record for more than two hours, iPod nano automatically starts a new voice memo to continue your recording. To record a voice memo: 1 Connect a microphone to the Dock connector port on iPod nano. 2 Set Quality to Low or High. 3 To begin recording, choose Record. 4 Hold the microphone a few inches from your mouth and speak. To pause recording, choose Pause. 5 When you finish, choose Stop and Save. Your saved recording is listed by date and time. To play a recording: m Choose Extras > Voice Memos and select the recording. Note: You won’t see a Voice Memos menu item if you’ve never connected a microphone to iPod nano. To sync voice memos with your computer: Voice memos are saved in a Recordings folder on iPod in the WAV file format. If you enable iPod nano for disk use, you can drag voice memos from the folder to copy them. If iPod nano is set to sync songs automatically (see “Syncing Music Automatically” on page 23) and you record voice memos, the voice memos are automatically synced to a playlist in iTunes (and removed from iPod nano) when you connect iPod nano. You see the new Voice Memos playlist in the source list. Learning About iPod nano Accessories iPod nano comes with some accessories, and many other accessories are available at www.apple.com/ipodstore. To purchase iPod nano accessories, go to www.apple.com/ipodstore. Chapter 5 Extra Features and Accessories 55 Available accessories include:  iPod Radio Remote  Nike + iPod Sport Kit  Apple Universal Dock  Apple Component AV Cable  Apple Composite AV Cable  Apple AV Connection Kit  Apple USB Power Adapter  iPod In-Ear Headphones  World Travel Adapter Kit  iPod Socks  iPod Earphones  Third-party accessories—such as speakers, headsets, cases, car stereo adapters, power adapters, and more To use the earphones: m Plug the earphones into the Headphones port. Then place the earbuds in your ears as shown. WARNING: Permanent hearing loss may occur if earbuds or headphones are used at high volume. You can adapt over time to a higher volume of sound that may sound normal but can be damaging to your hearing. If you experience ringing in your ears or muffled speech, stop listening and have your hearing checked. The louder the volume, the less time is required before your hearing could be affected. Hearing experts suggest that to protect your hearing:  Limit the amount of time you use earbuds or headphones at high volume.  Avoid turning up the volume to block out noisy surroundings.  Turn the volume down if you can’t hear people speaking near you. For information about setting a maximum volume limit on iPod, see “Setting the Maximum Volume Limit” on page 29. The earphones cord is adjustable.6 56 6 Tips and Troubleshooting Most problems with iPod nano can be solved quickly by following the advice in this chapter. General Suggestions Most problems with iPod nano can be solved by resetting it. First, make sure iPod nano is charged. To reset iPod nano: 1 Toggle the Hold switch on and off (slide it to HOLD and then back again). 2 Press and hold the Menu and Center buttons for at least 6 seconds, until the Apple logo appears. If iPod nano won’t turn on or respond  Make sure the Hold switch isn’t set to HOLD.  The iPod nano battery might need to be recharged. Connect iPod nano to your computer or to an Apple USB Power Adapter and let the battery recharge. Look for the lightning bolt icon on the iPod nano screen to verify that iPod nano is receiving a charge. The 5 Rs: Reset, Retry, Restart, Reinstall, Restore Remember these five basic suggestions if you have a problem with iPod nano. Try these steps one at a time until your issue is resolved. If one of the following doesn’t help, read on for solutions to specific problems.  Reset iPod nano. See “General Suggestions,” below.  Retry with a different USB port if you cannot see iPod nano in iTunes.  Restart your computer, and make sure you have the latest software updates installed.  Reinstall iTunes software from the latest version on the web.  Restore iPod nano. See “Updating and Restoring iPod Software” on page 61.Chapter 6 Tips and Troubleshooting 57 To charge the battery, connect iPod nano to a USB 2.0 on your computer. Connecting iPod nano to a USB port on your keyboard won’t charge the battery, unless your keyboard has a high-powered USB 2.0 port.  Try the 5 Rs, one by one, until iPod nano responds. If you want to disconnect iPod nano, but you see the message “Connected” or “Sync in Progress”  If iPod nano is syncing music, wait for it to complete.  Select iPod nano in the iTunes source list and click the Eject (C) button.  If iPod nano disappears from the list of devices in the iTunes source list, but you still see the “Connected” or “Sync in Progress” message on the iPod nano screen, disconnect iPod nano.  If iPod nano doesn’t disappear from the list of devices in the iTunes source list, drag the iPod nano icon from the desktop to the Trash (if you’re using a Mac) or, if you’re using a Windows PC, eject the device in My Computer or click the Safely Remove Hardware icon in the system tray and select iPod nano. If you still see the “Connected” or “Sync in Progress” message, restart your computer and eject iPod nano again. If iPod nano isn’t playing music  Make sure the Hold switch isn’t set to HOLD.  Make sure the headphone connector is pushed in all the way.  Make sure the volume is adjusted properly. A maximum volume limit might have been set. You can change or remove it by using Settings > Volume Limit. See “Setting the Maximum Volume Limit” on page 29.  iPod nano might be paused. Try pressing the Play/Pause button.  Make sure you’re using iTunes 7.4 or later (go to www.apple.com/ipod/start). Songs purchased from the iTunes Store using earlier versions of iTunes won’t play on iPod nano until you upgrade iTunes.  If you’re using the iPod Universal Dock, make sure the iPod nano is seated firmly in the Dock and make sure all cables are connected properly. If you connect iPod nano to your computer and nothing happens  Make sure you have installed the latest iTunes software from www.apple.com/ipod/start.  Try connecting to a different USB port on your computer. Note: A USB 2.0 port is recommended to connect iPod nano. USB 1.1 is significantly slower than USB 2.0. If you have a Windows PC that doesn’t have a USB 2.0 port, in some cases you can purchase and install a USB 2.0 card. For more information, go to www.apple.com/ipod.  iPod nano might need to be reset (see page 56). 58 Chapter 6 Tips and Troubleshooting  If you’re connecting iPod nano to a portable or laptop computer using the iPod Dock Connector to USB 2.0 Cable, connect the computer to a power outlet before connecting iPod nano.  Make sure you have the required computer and software. See “If you want to doublecheck the system requirements” on page 60.  Check the cable connections. Unplug the cable at both ends and make sure no foreign objects are in the USB ports. Then plug the cable back in securely. Make sure the connectors on the cables are oriented correctly. They can be inserted only one way.  Try restarting your computer.  If none of the previous suggestions solves your problems, you might need to restore iPod nano software. See “Updating and Restoring iPod Software” on page 61. If iPod nano displays a “Connect to Power” message This message may appear if iPod nano is exceptionally low on power and the battery needs to be charged before iPod nano can communicate with your computer. To charge the battery, connect iPod nano to a USB 2.0 port on your computer. Leave iPod nano connected to your computer until the message disappears and iPod nano appears in iTunes or the Finder. Depending on how depleted the battery is, you may need to charge iPod nano for up to 30 minutes before it will start up. To charge iPod nano more quickly, use the optional Apple USB Power Adapter. Note: Connecting iPod nano to a USB port on your keyboard won’t charge the battery, unless your keyboard has a high-powered USB 2.0 port. If iPod nano displays a “Use iTunes to restore” message  Make sure you have the latest version of iTunes on your computer (download it from www.apple.com/ipod/start).  Connect iPod nano to your computer. When iTunes opens, follow the onscreen prompts to restore iPod nano.  If restoring iPod nano doesn’t solve the problem, iPod nano may need to be repaired. You can arrange for service at the iPod Service & Support website: www.apple.com/support/ipod If songs or data sync more slowly over USB 2.0  If you sync a large number of songs or amount of data using USB 2.0 and the iPod nano battery is low, iPod nano syncs the information at a reduced speed in order to conserve battery power.  If you want to sync at higher speeds, you can stop syncing and keep the iPod nano connected so that it can recharge, or connect it to the optional iPod USB 2.0 Power Adapter. Let iPod nano charge for about an hour, and then resume syncing your music or data.Chapter 6 Tips and Troubleshooting 59 If you can’t add a song or other item to iPod nano The song may have been encoded in a format that iPod nano doesn’t support. The following audio file formats are supported by iPod nano. These include formats for audiobooks and podcasting:  AAC (M4A, M4B, M4P, up to 320 Kbps)  Apple Lossless (a high-quality compressed format)  MP3 (up to 320 Kbps)  MP3 Variable Bit Rate (VBR)  WAV  AA (audible.com spoken word, formats 2, 3, and 4)  AIFF A song encoded using Apple Lossless format has full CD-quality sound, but takes up only about half as much space as a song encoded using AIFF or WAV format. The same song encoded in AAC or MP3 format takes up even less space. When you import music from a CD using iTunes, it’s converted to AAC format by default. Using iTunes for Windows, you can convert nonprotected WMA files to AAC or MP3 format. This can be useful if you have a library of music encoded in WMA format. iPod nano doesn’t support WMA, MPEG Layer 1, MPEG Layer 2 audio files, or audible.com format 1. If you have a song in iTunes that isn’t supported by iPod nano, you can convert it to a format iPod nano supports. For more information, see iTunes Help. If you accidentally set iPod nano to use a language you don’t understand You can reset the language. 1 Press and hold Menu until the main menu appears. 2 Choose the sixth menu item (Settings). 3 Choose the last menu item (Reset Settings). 4 Choose the left item (Reset) and select a language. Other iPod nano settings, such as song repeat, are also reset. Note: If you added or removed items from the iPod nano main menu (see “Adding or Removing Items from the Main Menu” on page 9) the Settings menu item may be in a different place. If you can’t find the Reset Settings menu item, you can restore iPod nano to its original state and choose a language you understand. See “Updating and Restoring iPod Software” on page 61. If you can’t see videos or photos on your TV  You must use RCA-type cables made specifically for iPod nano, such as the Apple Component or Apple Composite AV cables, to connect iPod nano to your TV. Other similar RCA-type cables won’t work.60 Chapter 6 Tips and Troubleshooting  Make sure your TV is set to display images from the correct input source (see the documentation that came with your TV for more information).  Make sure all cables are connected correctly (see “Watching Videos on a TV Connected to iPod nano” on page 38).  Make sure the yellow end of the Apple Composite AV Cable is connected to the video port on your TV.  If you’re trying to watch a video, go to Videos > Settings and set TV Out to On, and then try again. If you’re trying to view a slideshow, go to Photos > Slideshow Settings and set TV Out to On, and then try again.  If that doesn’t work, go to Videos > Settings (for video) or Photos > Settings (for a slideshow) and set TV Signal to PAL or NTSC, depending on which type of TV you have. Try both settings. If you want to double-check the system requirements To use iPod nano, you must have:  One of the following computer configurations:  A Mac with a USB 2.0 port  A Windows PC with a USB 2.0 or a USB 2.0 card installed  One of the following operating systems:  Mac OS X v10.4.9 or later  Windows Vista  Windows XP Home or Professional with Service Pack 2 or later  iTunes 7.6 or later (iTunes can be downloaded from www.apple.com/ipod/start) If your Windows PC doesn’t have a USB 2.0 port, you can purchase and install a USB 2.0 card. For more information on cables and compatible USB cards, go to www.apple.com/ipod. On the Mac, iPhoto 4.0.3 or later is recommended for adding photos and albums to iPod nano. This software is optional. iPhoto might already be installed on your Mac. Check the Applications folder. If you have iPhoto 4 you can update it by choosing Apple () > Software Update. On a Windows PC, iPod nano can sync photo collections automatically from Adobe Photoshop Album 2.0 or later, and Adobe Photoshop Elements 3.0 or later, available at www.adobe.com. This software is optional. On both Mac and Windows PC, iPod nano can sync digital photos from folders on your computer’s hard disk.Chapter 6 Tips and Troubleshooting 61 If you want to use iPod nano with a Mac and a Windows PC If you’re using iPod nano with a Mac and you want to use it with a Windows PC, you must restore the iPod software for use with the PC (see “Updating and Restoring iPod Software” on page 61). Restoring the iPod software erases all data from iPod nano, including all songs. You cannot switch from using iPod nano with a Mac to using it with a Windows PC without erasing all data on iPod nano. If you lock the iPod nano screen and can’t unlock it Normally, if you can connect iPod nano to the computer it’s authorized to work with, iPod nano automatically unlocks. If the computer authorized to work with iPod nano is unavailable, you can connect iPod nano to another computer and use iTunes to restore iPod software. See the next section for more information. If you want to change the screen lock combination and you can’t remember the current combination, you must restore the iPod software and then set a new combination. Updating and Restoring iPod Software You can use iTunes to update or restore iPod software. It’s recommended that you update iPod nano to use the latest software. You can also restore the software, which puts iPod nano back to its original state.  If you choose to update, the software is updated, but your settings and songs aren’t affected.  If you choose to restore, all data is erased from iPod nano, including songs, videos, files, contacts, photos, calendar information, and any other data. All iPod nano settings are restored to their original state. To update or restore iPod nano: 1 Make sure you have an Internet connection and have installed the latest version of iTunes from www.apple.com/ipod/start. 2 Connect iPod nano to your computer. 3 In iTunes, select iPod nano in the source list and click the Summary tab. The Version section tells you whether iPod nano is up to date or needs a newer version of the software. 4 Click Update to install the latest version of the software. 5 If necessary, click Restore to restore iPod nano to its original settings (this erases all data from iPod nano). Follow the onscreen instructions to complete the restore process.7 62 7 Safety and Cleaning Read the following important safety and handling information for Apple iPods. Keep the iPod Safety Guide and the features guide for your iPod handy for future reference. Important Safety Information Handling iPod Do not bend, drop, crush, puncture, incinerate, or open iPod. Avoiding water and wet locations Do not use iPod in rain, or near washbasins or other wet locations. Take care not to spill any food or liquid into iPod. In case iPod gets wet, unplug all cables, turn iPod off, and slide the Hold switch (if available) to HOLD before cleaning, and allow it to dry thoroughly before turning it on again. Repairing iPod Never attempt to repair iPod yourself. iPod does not contain any userserviceable parts. For service information, choose iPod Help from the Help menu in iTunes or go to www.apple.com/support/ipod. The rechargeable battery in iPod should be replaced only by an Apple Authorized Service Provider. For more information about batteries, go to www.apple.com/batteries. ± Read all safety information below and operating instructions before using iPod to avoid injury. WARNING: Failure to follow these safety instructions could result in fire, electric shock, or other injury or damage.Chapter 7 Safety and Cleaning 63 Using the Apple USB Power Adapter (available separately) If you use the Apple USB Power Adapter (sold separately at www.apple.com/ipodstore) to charge iPod, make sure that the power adapter is fully assembled before you plug it into a power outlet. Then insert the Apple USB Power Adapter firmly into the power outlet. Do not connect or disconnect the Apple USB Power Adapter with wet hands. Do not use any power adapter other than an Apple iPod power adapter to charge your iPod. The iPod USB Power Adapter may become warm during normal use. Always allow adequate ventilation around the iPod USB Power Adapter and use care when handling. Unplug the iPod USB Power Adapter if any of the following conditions exist:  The power cord or plug has become frayed or damaged.  The adapter is exposed to rain, liquids, or excessive moisture.  The adapter case has become damaged.  You suspect the adapter needs service or repair.  You want to clean the adapter. Avoiding hearing damage Permanent hearing loss may occur if earbuds or headphones are used at high volume. Set the volume to a safe level. You can adapt over time to a higher volume of sound that may sound normal but can be damaging to your hearing. If you experience ringing in your ears or muffled speech, stop listening and have your hearing checked. The louder the volume, the less time is required before your hearing could be affected. Hearing experts suggest that to protect your hearing:  Limit the amount of time you use earbuds or headphones at high volume.  Avoid turning up the volume to block out noisy surroundings.  Turn the volume down if you can’t hear people speaking near you. For information about how to set a maximum volume limit on iPod, see “Setting the Maximum Volume Limit” on page 29. Using headphones safely Use of headphones while operating a vehicle is not recommended and is illegal in some areas. Be careful and attentive while driving. Stop using iPod if you find it disruptive or distracting while operating any type of vehicle or performing any other activity that requires your full attention. Avoiding seizures, blackouts, and eye strain If you have experienced seizures or blackouts, or if you have a family history of such occurrences, please consult a physician before playing video games on iPod (if available). Discontinue use and consult a physician if you experience: convulsion, eye or muscle twitching, loss of awareness, involuntary movements, or disorientation. When watching videos or playing games on iPod (if available), avoid prolonged use and take breaks to prevent eye strain.64 Chapter 7 Safety and Cleaning Important Handling Information Carrying iPod iPod contains sensitive components, including, in some cases, a hard drive. Do not bend, drop, or crush iPod. If you are concerned about scratching iPod, you can use one of the many cases sold separately. Using connectors and ports Never force a connector into a port. Check for obstructions on the port. If the connector and port don’t join with reasonable ease, they probably don’t match. Make sure that the connector matches the port and that you have positioned the connector correctly in relation to the port. Keeping iPod within acceptable temperatures Operate iPod in a place where the temperature is always between 0º and 35º C (32º to 95º F). iPod play time might temporarily shorten in low-temperature conditions. Store iPod in a place where the temperature is always between -20º and 45º C (-4º to 113º F). Don’t leave iPod in your car, because temperatures in parked cars can exceed this range. When you’re using iPod or charging the battery, it is normal for iPod to get warm. The exterior of iPod functions as a cooling surface that transfers heat from inside the unit to the cooler air outside. Keeping the outside of iPod clean To clean iPod, unplug all cables, turn iPod off, and slide the Hold switch (if available) to HOLD. Then use a soft, slightly damp, lint-free cloth. Avoid getting moisture in openings. Don’t use window cleaners, household cleaners, aerosol sprays, solvents, alcohol, ammonia, or abrasives to clean iPod. Disposing of iPod properly For information about the proper disposal of iPod, including other important regulatory compliance information, see “Regulatory Compliance Information” on page 66. NOTICE: Failure to follow these handling instructions could result in damage to iPod or other property.8 65 8 Learning More, Service, and Support You can find more information about using iPod nano in onscreen help and on the web. The following table describes where to get more iPod-related software and service information. To learn about Do this Service and support, discussions, tutorials, and Apple software downloads Go to: www.apple.com/support/ipodnano Using iTunes Open iTunes and choose Help > iTunes Help. For an online iTunes tutorial (available in some areas only), go to: www.apple.com/support/itunes Using iPhoto (on Mac OS X) Open iPhoto and choose Help > iPhoto Help. Using iSync (on Mac OS X) Open iSync and choose Help > iSync Help. Using iCal (on Mac OS X) Open iCal and choose Help > iCal Help. The latest information on iPod nano Go to: www.apple.com/ipodnano Registering iPod nano To register iPod nano, install iTunes on your computer and connect iPod nano. Finding the iPod nano serial number Look at the back of iPod nano or choose Settings > About and press the Center button. In iTunes (with iPod nano connected to your computer), select iPod nano in the source list and click the Settings tab. Obtaining warranty service First follow the advice in this booklet, the onscreen help, and online resources. Then go to: www.apple.com/support/ipodnano/ service66 Regulatory Compliance Information FCC Compliance Statement This device complies with part 15 of the FCC rules. Operation is subject to the following two conditions: (1) This device may not cause harmful interference, and (2) this device must accept any interference received, including interference that may cause undesired operation. See instructions if interference to radio or TV reception is suspected. Radio and TV Interference This computer equipment generates, uses, and can radiate radio-frequency energy. If it is not installed and used properly—that is, in strict accordance with Apple’s instructions—it may cause interference with radio and TV reception. This equipment has been tested and found to comply with the limits for a Class B digital device in accordance with the specifications in Part 15 of FCC rules. These specifications are designed to provide reasonable protection against such interference in a residential installation. However, there is no guarantee that interference will not occur in a particular installation. You can determine whether your computer system is causing interference by turning it off. If the interference stops, it was probably caused by the computer or one of the peripheral devices. If your computer system does cause interference to radio or TV reception, try to correct the interference by using one or more of the following measures:  Turn the TV or radio antenna until the interference stops.  Move the computer to one side or the other of the TV or radio.  Move the computer farther away from the TV or radio.  Plug the computer in to an outlet that is on a different circuit from the TV or radio. (That is, make certain the computer and the TV or radio are on circuits controlled by different circuit breakers or fuses.) If necessary, consult an Apple Authorized Service Provider or Apple. See the service and support information that came with your Apple product. Or, consult an experienced radio/TV technician for additional suggestions. Important: Changes or modifications to this product not authorized by Apple Inc. could void the EMC compliance and negate your authority to operate the product. This product was tested for EMC compliance under conditions that included the use of Apple peripheral devices and Apple shielded cables and connectors between system components. It is important that you use Apple peripheral devices and shielded cables and connectors between system components to reduce the possibility of causing interference to radios, TV sets, and other electronic devices. You can obtain Apple peripheral devices and the proper shielded cables and connectors through an Apple Authorized Reseller. For non-Apple peripheral devices, contact the manufacturer or dealer for assistance. Responsible party (contact for FCC matters only): Apple Inc. Product Compliance, 1 Infinite Loop M/S 26-A, Cupertino, CA 95014-2084, 408-974-2000. Industry Canada Statement This Class B device meets all requirements of the Canadian interference-causing equipment regulations. Cet appareil numérique de la classe B respecte toutes les exigences du Règlement sur le matériel brouilleur du Canada. VCCI Class B Statement Korea Class B Statement (૶ ૺૺဧ ઠધබ 67 Russia European Community Disposal and Recycling Information Your iPod must be disposed of properly according to local laws and regulations. Because this product contains a battery, the product must be disposed of separately from household waste. When your iPod reaches its end of life, contact Apple or your local authorities to learn about recycling options. For information about Apple’s recycling program, go to: www.apple.com/environment/recycling Deutschland: Dieses Gerät enthält Batterien. Bitte nicht in den Hausmüll werfen. Entsorgen Sie dieses Gerätes am Ende seines Lebenszyklus entsprechend der maßgeblichen gesetzlichen Regelungen. Nederlands: Gebruikte batterijen kunnen worden ingeleverd bij de chemokar of in een speciale batterijcontainer voor klein chemisch afval (kca) worden gedeponeerd. China: Taiwan: European Union—Disposal Information: This symbol means that according to local laws and regulations your product should be disposed of separately from household waste. When this product reaches its end of life, take it to a collection point designated by local authorities. Some collection points accept products for free. The separate collection and recycling of your product at the time of disposal will help conserve natural resources and ensure that it is recycled in a manner that protects human health and the environment. Apple and the Environment At Apple, we recognize our responsibility to minimize the environmental impacts of our operations and products. For more information, go to: www.apple.com/environment © 2008 Apple Inc. All rights reserved. Apple, the Apple logo, FireWire, iCal, iLife, iPhoto, iPod, iPod Socks, iTunes, Mac, Macintosh, and Mac OS are trademarks of Apple Inc., registered in the U.S. and other countries. Finder, the FireWire logo, and Shuffle are trademarks of Apple Inc. iTunes Store is a service mark of Apple Inc. NIKE is a trademark of NIKE, Inc. and its affiliates and is used under license. Other company and product names mentioned herein may be trademarks of their respective companies. Mention of third-party products is for informational purposes only and constitutes neither an endorsement nor a recommendation. Apple assumes no responsibility with regard to the performance or use of these products. All understandings, agreements, or warranties, if any, take place directly between the vendors and the prospective users. Every effort has been made to ensure that the information in this manual is accurate. Apple is not responsible for printing or clerical errors. The product described in this manual incorporates copyright protection technology that is protected by method claims of certain U.S. patents and other intellectual property rights owned by Macrovision Corporation and other rights owners. Use of this copyright protection technology must be authorized by Macrovision Corporation and is intended for home and other limited viewing uses only unless otherwise authorized by Macrovision Corporation. Reverse engineering or disassembly is prohibited. Apparatus Claims of U.S. Patent Nos. 4,631,603, 4,577,216, 4,819,098 and 4,907,093 licensed for limited viewing uses only. 019-1149/01-2008Index 68 Index A accessories for iPod 54 adding album artwork 21 adding menu items 9, 27 adding music disconnecting iPod 12 from more than one computer 23, 35 manually 24 methods 22 On-The-Go playlists 28 tutorial 65 adding photos about 40 all or selected photos 41, 42 automatically 41 from computer to iPod 41 from iPod to computer 43 full-resolution image 42 address book, syncing 51 Adobe Photoshop Album 60 Adobe Photoshop Elements 60 alarms deleting 48 setting 48 album artwork adding 21 viewing 31 albums, purchasing 19 audiobooks purchasing 19 setting play speed 32 AV cables 38, 39, 45 B backlight setting timer 9 turning on 6, 9 battery charge states when disconnected 16 charging 14 rechargeable 16 replacing 16 very low 15, 58 viewing charge status 14 brightness setting 10 browsing iTunes Store 19 podcasts 19 quickly 7 songs 6, 26 videos 6, 19 with Cover Flow 7 buttons Center 5 disabling with Hold switch 6 Eject 13 buying. See purchasing C calendar events, syncing 51 Center button, using 5, 26 Charging, Please Wait message 15, 58 charging the battery about 14 using the iPod USB Power Adapter 15 using your computer 14 when battery very low 15, 58 cleaning iPod 64 Click Wheel browsing songs 26 turning off the Click Wheel sound 8 using 5 clocks adding for other time zones 47 settings 47 close captions 38 compilations 27 component AV cable 38, 39, 45 composite AV cable 38, 39, 45 computer adding photos to iPod 41 charging the battery 14 connecting iPod 10 getting photos from iPod 43 importing photos from camera 40Index 69 problems connecting iPod 57 requirements 60 connecting iPod about 10 charging the battery 14 to a TV 39, 45 Connect to Power message 15 contacts sorting 53 syncing 51 controls disabling with Hold switch 8 using 5 converting unprotected WMA files 59 converting videos for use with iPod 34 Cover Flow 7 customizing the Music menu 27 D data files, storing on iPod 46 date and time setting 47 viewing 47 determining battery charge 16 diamond icon on scrubber bar 6 digital photos. See photos disconnecting iPod about 10 during music update 12 ejecting first 12 instructions 13 troubleshooting 57 disk, using iPod as 46 displaying time in title bar 47 downloading podcasts 19 video podcasts 34 See also adding; syncing E Eject button 13 ejecting before disconnecting 12 external disk, using iPod as 46 F fast-forwarding a song or video 6 features of iPod 4 file formats, supported 59 finding your iPod serial number 6 fit video to screen 38 full-resolution images 42 G games 49 getting help 65 getting information about your iPod 10 getting started with iPod 60 H handling information 62 hearing loss warning 55 help, getting 65 Hold switch 6, 8 I iCal, getting help 65 Image Capture, importing photos to a Mac 41 images. See photos importing contacts, calendars, and to-do lists. See syncing importing photos from camera to computer 40 See also adding photos importing videos 34 iPhoto getting help 40, 65 importing photos from camera 40 recommended version 60 iPod Dock 10 iPod Dock Connector 10 iPod Updater application 61 iPod USB power adapter 14 iSync, getting help 65 iTunes ejecting iPod 13 getting help 65 setting not to open automatically 46 Sound Check 30 Store 19 iTunes Library, adding songs 20 iTunes Store browsing 19 browsing videos 34 searching 19 signing in 18, 33 L language resetting 59 specifying 10 letterbox 38 library, adding songs 20 lightning bolt on battery icon 14 locating your iPod serial number 6 locking iPod screen 50 lyrics adding 21 viewing on iPod 3070 Index M Mac OS X operating system 60 main menu adding or removing items 9 opening 5 settings 9, 27 main menu, returning to 6 managing iPod manually 24 manually adding 24 maximum volume limit, setting 29 memos, recording 54 menu items adding or removing 9, 27 choosing 6 returning to main menu 6 returning to previous menu 6 modifying playlists 24 movies syncing 37 syncing selected 36 See also videos music iPod not playing 57 purchasing 19 rating 28 setting for slideshows 44 tutorial 65 See also adding music; songs Music menu, customizing 27 music videos syncing 24 See also videos N navigating quickly 7 notes, storing and reading 53 Now Playing screen moving to any point in a song or video 6 scrubber bar 6 shuffling songs or albums 27 NTSC TV 38, 44 O On-The-Go playlists copying to computer 28 making 27 rating songs 28 saving 28 operating system requirements 60 overview of iPod features 4 P PAL TV 38, 44 pausing a song 6 a video 6 phone numbers, syncing 51 photo collections, adding automatically 41 photo library 41 photos adding and viewing 40 deleting 42, 43 full-resolution 42 importing to Windows PC 41 importing using Image Capture 41 syncing 41, 42 viewing on iPod 43 playing games 49 songs 6 videos 6 playlists adding songs 6, 24 making on iPod 27 modifying 24 On-The-Go 27 setting for slideshows 45 plug on battery icon 14 podcasting 31 podcasts browsing 19 downloading 19 downloading video podcasts 34 listening 31 subscribing 19 updating 25 ports RCA video and audio 39, 45 USB 60 power adapter safety 63 Power Search in iTunes Store 19 previous menu, returning to 6 problems. See troubleshooting purchasing songs, albums, audiobooks 19 purchasing videos 34 Q quick navigation 7 R radio accessory 32 random play 6 rating songs 28 RCA video and audio ports 39, 45 rechargeable batteries 16 recording voice memos 54 registering iPod 65 relative volume, playing songs at 30 removing menu items 9, 27 repairing iPod 62Index 71 replacing battery 16 replaying a song or video 6 requirements computer 60 operating system 60 reset all settings 10 resetting iPod 6, 56 resetting the language 59 restore message 58 restoring iPod software 61 rewinding a song or video 6 S Safely Remove Hardware icon 13 safety considerations setting up iPod 62 safety information 62 saving On-The-Go playlists 28 screen lock 50 scrolling quickly 7 scrubber bar 6 searching iPod 7 iTunes Store 19 Select button. See Center button serial number 6, 10 serial number, locating 65 service and support 65 sets of songs. See playlists setting combination for iPod 50 settings about your iPod 10 alarm 48 audiobook play speed 32 backlight timer 9 brightness 10 Click Wheel sound 8 date and time 47 language 10 main menu 9, 27 PAL or NTSC TV 38, 44 playing songs at relative volume 30 repeating songs 27 reset all 10 shuffle songs 27 sleep timer 48 slideshow 44 TV 38 volume limit 29 shuffling songs on iPod 6, 27 sleep mode and charging the battery 14 sleep timer, setting 48 slideshows background music 44 random order 44 setting playlist 45 settings 44 viewing on iPod 45 software getting help 65 iPhoto 60 iPod Updater 61 support versions 60 updating 61 songs adding to On-The-Go playlists 6 browsing 6 browsing and playing 26 entering names 21 fast-forwarding 6 pausing 6 playing 6 playing at relative volume 30 purchasing 19 rating 28 repeating 27 replaying 6 rewinding 6 shuffling 6, 27 skipping ahead 6 viewing lyrics 21 See also music sorting contacts 53 Sound Check 30 standard TV 38 stopwatch 48, 49 storing data files on iPod 46 notes on iPod 53 subscribing to podcasts 19 supported operating systems 60 suppressing iTunes from opening 46 syncing address book 51 movies 37 music 22 music videos 24 photos 41, 42 selected movies 36 selected videos 36 to-do lists 51 TV shows 37 videos 35 See also adding T third-party accessories 55 time, displaying in title bar 47 timer, setting for backlight 9 time zones, clocks for 4772 Index title bar, displaying time 47 to-do lists, syncing 51 transitions for slides 44 troubleshooting connecting iPod to computer 57 cross-platform use 61 disconnecting iPod 57 iPod not playing music 57 iPod won’t respond 56 resetting iPod 56 restore message 58 safety considerations 62 setting incorrect language 59 slow syncing of music or data 58 software update and restore 61 TV slideshows 59 unlocking iPod screen 61 turning iPod on and off 6 tutorial 65 TV connecting to iPod 39, 45 PAL or NTSC 38, 44 settings 38 viewing slideshows 39, 45 TV shows syncing 37 See also videos U unlocking iPod screen 51, 61 unresponsive iPod 56 unsupported audio file formats 59 updating and restoring software 61 USB 2.0 port recommendation 60 slow syncing of music or data 58 USB port on keyboard 11, 57 Use iTunes to restore message in display 58 V video captions 38 video podcasts downloading 33, 34 viewing on a TV 38 videos adding to iPod 35 browsing 6 browsing in iTunes Store 19, 34 converting 34 fast-forwarding 6 importing into iTunes 34 pausing 6 playing 6 purchasing 33, 34 replaying 6 rewinding 6 skipping ahead 6 syncing 35 viewing on a TV 38 viewing on iPod 38 viewing album artwork 31 viewing lyrics 30 viewing music videos 38 viewing photos 43 viewing slideshows on a TV 39, 45 on iPod 45 settings 44 troubleshooting 59 voice memos recording 54 syncing with your computer 54 volume changing 6 setting maximum limit 29 W warranty service 65 widescreen TV 38 Windows importing photos 41 supported operating systems 60 troubleshooting 61 WMA files, converting 59 iTunes Video and Audio Asset Guide 5.0  Contents Overview 4 Introduction 4 Changes Made in this Release 4 What’s New in the iTunes Video and Audio Asset Guide 5.0? 4 Music Audio Content Profiles 6 Music Audio Source Profile 6 Pre-Cut Ringtone Source Profile 6 Music Album Cover Art Profile 7 Music Digital Booklet Profile 7 Content Considerations 8 Music Video Content Profiles 9 Music Video SD Source Profile 9 NTSC 9 PAL 10 Music Video HD Source Profile 10 Music Video Audio Source Profile 11 Music Video Audio/Video Container 11 Music Video Screen Capture Image Profile 12 Television Content Profiles 13 HD TV Source Profile 13 SD TV Source Profile 14 NTSC 14 PAL 14 TV Audio Source Profile 15 MPEG-2 Program Stream Container 15 QuickTime Container 16 TV Audio/Video Container 16 MPEG-2 Program Stream Container 16 QuickTime Container 16 TV Closed Captioning Profile 17 TV Cover Art Profile 18 2012-05-22 | © 2012 Apple Inc. All Rights Reserved. 2TV Content Considerations 19 Film Content Profiles 20 Film HD Source Profile 20 Film SD Source Profile 20 NTSC 20 PAL 21 Film Audio Source Profile 21 Film Audio/Video and Alt-Audio Container 22 Film Closed Captioning Profile 23 Film iTunes Timed Text Profile 23 Film Dub Card Video Profile 24 Dub Card Video Profile 24 Film Chapter Image Profile 25 Film Poster Art Profile 25 Film Content Considerations 26 XML 27 Revision History 28 Previous Spec Revisions 28 Audio Channel Assignments 30 How to Apply Audio Channel Assignments 30 Table 1: Audio Channel Assignment Labels 36 2012-05-22 | © 2012 Apple Inc. All Rights Reserved. 3 ContentsThis document provides detailed delivery information for all accepted media and files for the iTunes Store, including music, music video, television, and movies. If further details are required, contact your iTunes Technical Representative. Introduction Quality is important to us at iTunes. We expect to receive the highest-quality assets available. Our product must meet or exceed the quality of the physical product already out in the marketplace. For example, if 5.1 surround sound or closed captions exist on the physical version of the product, those must be provided. If the physical product gives the chapters actual names (as opposed to Chapter 1, Chapter 2, and so on), then our product should have those same chapter titles. If the album is in stereo, stereo audio must be provided. Changes Made in this Release Date/Version Changes Made Album cover art and poster art requirements have changed. Removed TIFF from the list of recommended image formats and removed DPI requirements. Added delivery requirements for dub card video. 96Khz audio is now supported. May 30, 2012 - Version 5.0 For a complete history of changes, see “Previous Spec Revisions” (page 28). What’s New in the iTunes Video and Audio Asset Guide 5.0? Music: Album Cover Art Album cover art must be at least 1400 x 1400 pixels (2400 x 2400 pixels recommended for best results) with a 1:1 aspect ratio. The file must be a high-quality JPEG with .jpg extension or PNG with .png extension. Do not increase the size of a smaller image to meet the minimum size standard. Excessively blurry or pixelated images will be rejected. 2012-05-22 | © 2012 Apple Inc. All Rights Reserved. 4 Overviewdummy tet to make page break Music: Audio Source Profile The iTunes Store accepts audio with a sampling rate of 96Khz and 24-bit resolution for album tracks and ringtones. TV: Cover Art TV cover art must be at least 1400 x 1400 pixels (2400 x 2400 pixels recommended for best results) with a 1:1 aspect ratio. The file must be a high-quality JPEG with .jpg extension or PNG with .png extension. Do not increase the size of a smaller image to meet the minimum size standard. Excessively blurry or pixelated images will be rejected. Film: Poster Art Poster art must be at least 1400 x 2100 pixels with a 2:3 aspect ratio. The file must be a high-quality JPEG with .jpg extension or PNG with .png extension. Don't increase the size of a smaller image to meet the minimum size standard. Excessively blurry or pixelated images will be rejected. Film: Dub Card Video Added delivery requirements for dub card video files. See “Film Dub Card Video Profile” (page 24). Overview Changes Made in this Release 2012-05-22 | © 2012 Apple Inc. All Rights Reserved. 5Music Audio Source Profile The iTunes Store accepts audio with a sampling rate of 44.1Khz and 16-bit or 24-bit resolution and 96Khz with 24-bit resolution. Note that the audio source must be stereo unless it does not exist. Uncompressed audio formats supported are: Format Container Type Qualified CODEC Pulse-Code Modulation (PCM) WAV (.wav) QuickTime http://www.apple.com/quicktime iTunes http://www.apple.com/itunes Apple Lossless (ALAC) M4A (.m4a) CAF (.caf) iTunes Producer Free Lossless Audio Codec (FLAC) FLAC (.flac) FLAC http://flac.sourceforge.net All other audio formats will be rejected. Important All audio must be generated using a CODEC qualified and approved by Apple. Pre-Cut Ringtone Source Profile The iTunes Store accepts pre-cut ringtones with a sampling rate of 44.1 kHz and 16-bit or 24-bit resolution and 96Khz with 24-bit resolution. Note that the audio source must be stereo unless it does not exist. The audio file must be lossless and be one of these formats: WAV, FLAC, ALAC. The minimum length is 5 seconds and the maximum length is 30 seconds. See the table above for the uncompressed audio formats that are supported. All other audio formats will be rejected. 2012-05-22 | © 2012 Apple Inc. All Rights Reserved. 6 Music Audio Content ProfilesImportant All audio must be generated using a CODEC qualified and approved by Apple. Music Album Cover Art Profile ● JPEG with .jpg extension (quality unconstrained) or PNG with .png extension ● Color space: RGB (screen standard) ● Minimum size of 1400 x 1400 pixels. 2400 x 2400 pixels recommended for best results. ● Images must be square ● File formats: JPEG or PNG (100% quality) ● 1:1 aspect ratio Do not increase the size of a smaller image to meet the minimum size standard. Excessively blurry or pixelated images will be rejected. Important CMYK (print standard) images will not be accepted. Music Digital Booklet Profile ● PDF format with .pdf extension ● Four-page minimum ● No more than 10 MB in size ● All fonts embedded ● 11 in x 8.264 in (28 cm x 21 cm) ● RGB color ● Horizontal presentation ● All images full-bleed as shown in sample pages Important These booklets are expressly designed for the iTunes Store format, and cannot be reproductions of the liner notes with borders to increase their size. Music Audio Content Profiles Music Album Cover Art Profile 2012-05-22 | © 2012 Apple Inc. All Rights Reserved. 7Content Considerations ● When saving as PDF, make sure the document opens full screen with no negative space surrounding the document. ● If the digital booklet is many pages, consider using fewer images or optimizing images to achieve lower overall file size. ● Printer’s marks are not allowed. ● You cannot sell or advertise other products or services. No other promotional sites are allowed. ● No links to anything outside of the booklet, except to the artist and/or label website(s). ● No time-sensitive information (for example, a promotion or dates for an upcoming tour or concert). Music Audio Content Profiles Music Digital Booklet Profile 2012-05-22 | © 2012 Apple Inc. All Rights Reserved. 8Note Chaptering is not supported for music videos. Music Video SD Source Profile NTSC ● MPEG-2 Program Stream Main Profile ● 4:2:0 chroma sampling ● ITU-R BT.601 color space ● 15 Mbps minimum ● Long GOP ● 640 fixed horizontal dimension ● Variable size vertical dimension depending on aspect ratio of source, maximum size of 480 ● Square pixel aspect ratio (1:1) ● Native frame rate of original source: ● 29.97 interlaced frames per second video source can be delivered either interlaced or de-interlaced properly tagged as progressive ● 24 frames per second must be delivered progressive ● 23.976 frames per second for inverse telecine must be delivered progressive; must not be delivered interlaced or delivery will fail ● Field dominance must be properly tagged (top field first, bottom field first, or progressive) ● Telecine materials will not be accepted ● For mixed frame rate material please contact your iTunes Technical Representative ● Interlaced content must be tagged non-progressive and field ordering must be defined in the stream. ● Crop inactive pixels and maintain fields. All edges must have active pixels for greater than 90% of the duration of the video. 2012-05-22 | © 2012 Apple Inc. All Rights Reserved. 9 Music Video Content ProfilesPAL ● MPEG-2 Program Stream Main Profile ● 4:2:0 chroma sampling ● ITU-R BT.601 color space ● 15 Mbps minimum ● Long GOP ● 640 fixed horizontal dimension ● Variable size vertical dimension depending on aspect ratio of source, maximum size of 480 ● Square pixel aspect ratio (1:1) ● Native frame rate of original source: ● 25 interlaced frames per second sourced from video must be delivered de-interlaced and properly tagged as progressive ● 24 and 25 frames per second sourced from film must be delivered progressive ● 23.976 frames per second for inverse telecine must be delivered progressive; must not be delivered interlaced or delivery will fail ● Field dominance must be properly tagged (top field first, bottom field first, or progressive) ● Telecine or interlaced materials will not be accepted ● For mixed frame rate material please contact your iTunes Technical Representative ● Crop inactive pixels. All edges must have active pixels for greater than 90% of the duration of the video. Important All video must begin and end with at least one black frame. Music Video HD Source Profile ● Apple ProRes 422 (HQ) ● VBR expected at ~220 Mbps ● 1920 x 1080 square pixel aspect ratio material ● Native frame rate of original source: ● 29.97 interlaced frames per second for video sourced ● 24 or 25 progressive frames per second for film sourced ● 23.976 progressive frames for inverse telecine sourced from film Music Video Content Profiles Music Video HD Source Profile 2012-05-22 | © 2012 Apple Inc. All Rights Reserved. 10● Telecine materials will not be accepted ● HD source may be delivered matted: letterbox, pillarbox, or windowbox. ● The HD source may be delivered in its full-frame state with metadata included to specify the crop rectangle. See “Music Video Single” in the iTunes Package Music Specification for details. ● If the HD source file is not delivered matted or if there are no inactive pixels, we recommend setting all crop dimension attributes to '0' (zero). Important All video must begin and end with at least one black frame. Music Video Audio Source Profile If 5.1 Surround is available for a music video audio source, the audio should be delivered in 5.1 Surround in addition to providing a stereo version; otherwise the audio may be delivered in Stereo only. Surround ● LPCM in either Big Endian or Little Endian, 16-bit or 24-bit, at least 48kHz ● Expected channels: L, R, C, LFE, Ls, Rs Stereo ● MPEG-1 layer II stereo ● 384 kpbs ● 48Khz ● Included in the same file as the delivered video Music Video Audio/Video Container ● Deliver all content in an MPEG-2 Program Stream file container ● The .mpg file extension is expected for all MPEG-2 content ● Audio must be delivered muxed with the video stream Music Video Content Profiles Music Video Audio Source Profile 2012-05-22 | © 2012 Apple Inc. All Rights Reserved. 11Note Closed-captioning is currently not supported for music videos. Music Video Screen Capture Image Profile ● Screen capture from delivered video ● JPEG with .jpg extension (quality unconstrained) or PNG with .png extension ● RGB (screen standard) ● Minimum dimensions: Must be 640 x 100 pixels. ● Variable size vertical dimension. Must be same aspect ratio as video source, with a maximum size of 480. ● Only the active pixel area may be included. Do not increase the size of a smaller image to meet the minimum size standard. Excessively blurry or pixelated images will be rejected. Images must be taken directly from the video. Important CMYK (print standard) images will not be accepted. Music Video Content Profiles Music Video Screen Capture Image Profile 2012-05-22 | © 2012 Apple Inc. All Rights Reserved. 12HD TV Source Profile ● Apple ProRes 422 (HQ) ● ITU-R BT.709 color space, file tagged correctly as 709 ● VBR expected at 88-220 Mbps ● 1920 x 1080 or 1280 x 720 square pixel aspect ratio material* ● 23.976, 24, 25, 29.97 frame rates are supported ● Native frame rate of original source: ● 29.97 interlaced frames per second video source can be delivered either interlaced or de-interlaced properly tagged as progressive ● 24 and 25 frames per second must be delivered progressive ● 23.976 frames per second for inverse telecine must be delivered progressive; must not be delivered interlaced or delivery will fail ● Field dominance must be properly tagged (top field first, bottom field first, or progressive) ● Fields and frames may not be duplicated or eliminated to create a broadcast frame rate (for example, telecine, NTSC to PAL conversion) ● For mixed frame rate material please contact your iTunes Technical Representative ● Interlaced content must be correctly tagged as interlaced and field ordering must be defined in the QuickTime container. ● Crop dimensions should be supplied in the metadata for content with inactive pixels due to letterbox, pillarbox, or windowbox. Please refer to the iTunes Package TV Specification for further information. ● Content upscaled from SD will be rejected. * If your mezzanine library is not stored in HD D5 or HDCam-SR, contact your iTunes Technical Representative. 2012-05-22 | © 2012 Apple Inc. All Rights Reserved. 13 Television Content ProfilesSD TV Source Profile NTSC ● MPEG-2 Program Stream Main Profile ● 4:2:0 chroma sampling ● ITU-R BT.601 color space ● 15 Mbps minimum ● Long GOP ● 640 fixed horizontal dimension ● Variable size vertical dimension depending on aspect ratio of source, maximum size of 480 ● Square pixel aspect ratio (1:1) ● Native frame rate of original source: ● 29.97 interlaced frames per second video source can be delivered either interlaced or de-interlaced properly tagged as progressive ● 24 frames per second must be delivered progressive ● 23.976 frames per second for inverse telecine must be delivered progressive; must not be delivered interlaced or delivery will fail ● Field dominance must be properly tagged (top field first, bottom field first, or progressive) ● Fields and frames may not be duplicated or eliminated to create a broadcast frame rate (for example, telecine, NTSC to PAL conversion) ● For mixed frame rate material please contact your iTunes Technical Representative ● Interlaced content must be tagged non-progressive and field ordering must be defined in the stream. ● Crop inactive pixels and maintain fields. All edges must have active pixels for greater than 90% of the duration of the video. ● Content may NOT be delivered letterbox, pillarbox, or windowbox. PAL ● MPEG-2 Program Stream Main Profile ● 4:2:0 chroma sampling ● ITU-R BT.601 color space ● 15 Mbps minimum Television Content Profiles SD TV Source Profile 2012-05-22 | © 2012 Apple Inc. All Rights Reserved. 14● Long GOP ● 640 fixed horizontal dimension ● Variable size vertical dimension depending on aspect ratio of source, maximum size of 480 ● Square pixel aspect ratio (1:1) ● Native frame rate of original source: ● 25 interlaced frames per second sourced from video must be delivered de-interlaced and properly tagged as progressive ● 24 and 25 frames per second sourced from film must be delivered progressive ● 23.976 frames per second for inverse telecine must be delivered progressive; must not be delivered interlaced or delivery will fail ● Field dominance must be properly tagged (top field first, bottom field first, or progressive) ● Interlaced materials will not be accepted ● Fields and frames may not be duplicated or eliminated to create a broadcast frame rate (for example, telecine, NTSC to PAL conversion) ● For mixed frame rate material please contact your iTunes Technical Representative ● Crop inactive pixels. All edges must have active pixels for greater than 90% of the duration of the video. ● Content may NOT be delivered letterbox, pillarbox, or windowbox. Important All video must begin and end with at least one black frame. TV Audio Source Profile MPEG-2 Program Stream Container Stereo ● MPEG-1 layer II ● 384 kpbs ● 48Khz ● Included in the same file as the delivered video Television Content Profiles TV Audio Source Profile 2012-05-22 | © 2012 Apple Inc. All Rights Reserved. 15QuickTime Container Surround ● LPCM in either Big Endian or Little Endian, 16-bit or 24-bit, at least 48kHz ● Expected channels: L, R, C, LFE, Ls, Rs Stereo ● LPCM in either Big Endian or Little Endian, 16-bit or 24-bit, at least 48kHz ● Expected Dolby Pro Logic channels: Lt, Rt or expected stereo channels: L, R TV Audio/Video Container MPEG-2 Program Stream Container ● Deliver all content in an MPEG-2 Program Stream file container. ● The .mpg file extension is expected for all MPEG-2 content. ● Audio must be delivered muxed with the video stream. QuickTime Container ● Deliver all content in a QuickTime .mov file container. ● The QuickTime .mov file extension is expected for all audio and video content. Television Content Profiles TV Audio/Video Container 2012-05-22 | © 2012 Apple Inc. All Rights Reserved. 16● Each audio channel must have an assignment. The channel assignments must match one of the options below. Note that "Lt" and "Rt" are only used for Dolby matrix audio mixdown. If audio doesn't conform, contact your iTunes Technical Representative. Option 1 5.1 Surround Tracks Stereo Tracks L R C Lfe Ls Rs Lt Rt Track 1 -- six channels Track 2 L R C Lfe Ls Rs Lt Rt Track 3 One track containing all Surround channels; Matrix Stereo with Lt in one track and Rt channel in another track L R C Lfe Ls Rs Lt Rt Option 2 Track 1 Track 2 Track 3 Track 4 Track 5 Track 6 Track 7 Track 8 One track for each channel Option 3 Track 1 -- six channels Track 2 -- two channels L R C Lfe Ls Rs Lt Rt One track containing all Surround channels; Matrix Stereo with Lt and Rt channels in one track L R C Lfe Ls Rs Option 4 Track 1 Track 2 Track 3 Track 4 Track 5 Track 6 One track for each Surround channel; Matrix Stereo with Lt and Rt channels in one track Track 7 -- two channels Lt Rt Option 5 No Surround. Stereo with L in one track and R in another track L R Track 1 Track 2 Option 6 No Surround. Stereo with both L and R channels in one track Track 1 -- two channels L R Important Refer to “Table 1: Audio Channel Assignment Labels” (page 36) for label descriptions and “How to Apply Audio Channel Assignments” (page 30) for instructions on applying audio channel assignments. TV Closed Captioning Profile Note Closed captioning can only be sent with ProRes files. ● English text in EIA 608 format. ● Delivered in the same package with the video it references. ● In a Scenarist SCC formatted file, using .scc file extension. Television Content Profiles TV Closed Captioning Profile 2012-05-22 | © 2012 Apple Inc. All Rights Reserved. 17● SCC files must be 29.97 regardless of frame rate of the movie file. Note: Captioning workflows utilizing 23.976 FPS timecodes can be accepted but the timecodes will be regarded as 29.97 FPS. ● SCC files should preserve the timecode mode (drop or non-drop) used in your captioning process, not necessarily the mode represented in the QuickTime movie source. ● SCC files must be validated for proper sync against the associated video file using QuickTime 7 Pro. ● Captionsshould display and synchronize to within one second of the initial, audible dialog to be represented in text. The timecodes of the captions are relative to the start of the program, and not the QuickTime movie'stimecode track. Currently, the iTunes Store does not support EIA 708 (ATSC closed captioning) or Teletext. MacCaption is a tool you can use to create .scc files: http://www.cpcweb.com/products/. (Note that this product is not endorsed by Apple. Apple cannot and does not provide support for third-party products.) Note If closed caption data is available for any broadcast or web delivery system, it must be suppled to iTunes. TV Cover Art Profile ● JPEG with .jpg extension (quality unconstrained) or PNG with .png extension ● RGB (screen standard) ● 1400 x 1400 pixels minimum size (2400 x 2400 recommended for best results) ● 1:1 aspect ratio Do not increase the size of a smaller image to meet the minimum size standard. Excessively blurry or pixelated images will be rejected. Important CMYK (print standard) images will not be accepted. Television Content Profiles TV Cover Art Profile 2012-05-22 | © 2012 Apple Inc. All Rights Reserved. 18TV Content Considerations ● No bugs or logos should be visible during the body of the video. ● No tune-ins should be visible during the body of the video. Tune-ins are only acceptable at the end of the video. ● No ratings or advisories should be displayed at any time during the video. ● Network cards at the beginning and end of the video are accepted as long as they are visible less than five (5) seconds. ● Commercials or other promotional material, including URLs, are NOT accepted. For more details, please contact your iTunes Technical Representative. ● Commercial black may be a maximum of 5 seconds. ● Previews must contain content suitable for a general audience. ● Previews must not have opening or ending credits and should not start on a black frame. ● A minimum of 1 black frame at the beginning and end of each video is required. Television Content Profiles TV Content Considerations 2012-05-22 | © 2012 Apple Inc. All Rights Reserved. 19Film HD Source Profile ● Apple ProRes 422 (HQ) ● ITU-R BT.709 color space, file tagged correctly as 709 ● VBR expected at ~220 Mbps ● 1920 x 1080 square pixel aspect ratio material ● Native frame rate of original source: ● 29.97 interlaced frames per second for video sourced ● 24 or 25 progressive frames per second for film sourced ● 23.976 progressive frames for inverse telecine sourced from film ● Telecine materials will not be accepted ● Content may be delivered matted: letterbox, pillarbox, or windowbox. Important All videos must begin and end with at least one black frame. Film SD Source Profile NTSC ● Apple ProRes 422 (HQ) ● VBR expected at 40-60 Mbps ● 720 x 480 or 720 x 486 encoded pixels; for display at either 853 x 480 for 16:9 content or 640 x 480 for 4:3 content ● All encoded content must include pixel aspect ratio (pasp) that defines content as either 4:3 or 16:9. ● Native frame rate of original source: ● 29.97 frames per second video source can be delivered interlaced ● 24 frames per second must be delivered progressive 2012-05-22 | © 2012 Apple Inc. All Rights Reserved. 20 Film Content Profiles● 23.976 frames per second for inverse telecine must be delivered progressive; must not be delivered interlaced or delivery will fail ● Telecine materials will not be accepted ● Content may be delivered matted: letterbox, pillarbox, or windowbox. PAL ● Apple ProRes 422 (HQ) ● VBR expected at 40-60 Mbps ● 720 x 576 encoded pixels; for display at either 1024 x 576 for 16:9 content or 768 x 576 for 4:3 content ● All encoded content must include pixel aspect ratio (pasp) that defines content as either 4:3 or 16:9. ● Native frame rate of original source: ● 24 and 25 frames per second sourced from film must be delivered progressive ● 23.976 frames per second for inverse telecine must be delivered progressive; must not be delivered interlaced or delivery will fail ● Telecine materials will not be accepted ● Content may be delivered matted: letterbox, pillarbox, or windowbox. 25 fps interlaced PAL films are NOT supported. Important All videos must begin and end with at least one black frame. Film Audio Source Profile For every film that 5.1 Surround audio is available in any competing format or market, it must be provided to iTunes in addition to the stereo tracks. Surround ● LPCM in either Big Endian or Little Endian, 16-bit or 24-bit, at least 48kHz ● Expected channels: L, R, C, LFE, Ls, Rs Stereo ● LPCM in either Big Endian or Little Endian, 16-bit or 24-bit, at least 48kHz ● Expected Dolby Pro Logic channels: Lt, Rt or expected stereo channels: L, R Film Content Profiles Film Audio Source Profile 2012-05-22 | © 2012 Apple Inc. All Rights Reserved. 21Film Audio/Video and Alt-Audio Container ● Deliver all content in a QuickTime .mov file container. ● The QuickTime .mov file extension is expected for all audio and video content. ● Each audio channel must have an assignment. The channel assignments must match one of the options below: Option 1 5.1 Surround Tracks Stereo Tracks L R C Lfe Ls Rs Lt Rt Track 1 -- six channels Track 2 L R C Lfe Ls Rs Lt Rt Track 3 One track containing all Surround channels; Matrix Stereo with Lt in one track and Rt channel in another track L R C Lfe Ls Rs Lt Rt Option 2 Track 1 Track 2 Track 3 Track 4 Track 5 Track 6 Track 7 Track 8 One track for each channel Option 3 Track 1 -- six channels Track 2 -- two channels L R C Lfe Ls Rs Lt Rt One track containing all Surround channels; Matrix Stereo with Lt and Rt channels in one track L R C Lfe Ls Rs Option 4 Track 1 Track 2 Track 3 Track 4 Track 5 Track 6 One track for each Surround channel; Matrix Stereo with Lt and Rt channels in one track Track 7 -- two channels Lt Rt Option 5 No Surround. Stereo with L in one track and R in another track L R Track 1 Track 2 Option 6 No Surround. Stereo with both L and R channels in one track Track 1 -- two channels L R Important Refer to “Table 1: Audio Channel Assignment Labels” (page 36) for label descriptions and “How to Apply Audio Channel Assignments” (page 30) for instructions on applying audio channel assignments. Note For more information on alternate audio, see the “Assets and Data Files” section in the iTunes Package Film Specification . Film Content Profiles Film Audio/Video and Alt-Audio Container 2012-05-22 | © 2012 Apple Inc. All Rights Reserved. 22Film Closed Captioning Profile ● English text in EIA 608 format. ● Delivered in the same package with the video it references. ● In a Scenarist SCC formatted file, using .scc file extension. ● SCC files must be 29.97 regardless of frame rate of the movie file. Note: Captioning workflows utilizing 23.976 FPS timecodes can be accepted but the timecodes will be regarded as 29.97 FPS. ● SCC files should preserve the timecode mode (drop or non-drop) used in your captioning process, not necessarily the mode represented in the QuickTime movie source. ● SCC files must be validated for proper sync against the associated video file using QuickTime 7 Pro. ● Captionsshould display and synchronize to within one second of the initial, audible dialog to be represented in text. The timecodes of the captions are relative to the start of the program, and not the QuickTime movie'stimecode track. Currently, the iTunes Store does not support EIA 708 (ATSC closed captioning) or Teletext. MacCaption is a tool you can use to create .scc files: http://www.cpcweb.com/products/. (Note that this product is not endorsed by Apple. Apple cannot and does not provide support for third-party products.) Note The closed caption file must be provided unless it does not exist. Film iTunes Timed Text Profile Below is a summary of delivery requirements for iTunes Timed Text. Refer to Chapter 5 in the iTunes Package Film Specification for complete details. ● Delivered in an iTunes Timed Text (iTT) formatted file, using .itt file extension. ● Delivered in the same package with the video it references as an asset in the block. ● Only one div element is allowed in an iTT document. ● timeBase must be set to smpte. ● dropMode must be set to "dropNTSC" or "nonDrop"; iTunes Timed Text does not support dropPAL. ● Only sansSerif may be specified as the typeface in fontFamily. Film Content Profiles Film Closed Captioning Profile 2012-05-22 | © 2012 Apple Inc. All Rights Reserved. 23The iTT file format is a subset of the Timed Text Markup Language, Version 1.0 W3C Candidate Recommendation 23 February 2010 (TTML) (http://www.w3.org/TR/2010/CR-ttaf1-dfxp-20100223/) from the World Wide Web Consortium (W3C) (http://w3.org/). All iTT documents are TTML documents that use the restricted subset of TTML. Film Dub Card Video Profile The full feature-length video asset is comprised of a set of data files, which play specific roles for their asset. The following table describes the optional data file for dub card video. Asset Data File Description Type A video-only sequence containing one or more still credits specific to the locale-matched audio. iTunes products will include dub credit video sequencesfor the associated audio dubs following the main program. Locale: Required Role: video.end.dub_credits An optional data file containing the credits associated with an audio track. Full Dub Card Video Profile ● Apple ProRes 422 (HQ) ● Movie correctly tagged with color parameter: ITU BT.709 ● Video dimensions, pixel aspect ratio, and frame rate must match full program video ● Minimum of 4 seconds per dub card ● Crop dimensions from full program video will be applied to all dub card video — effective crop must match full program video ● Crop attributes must not be supplied for dub card video ● Sound tracks should not be supplied for dub card video — sound tracks will be ignored ● Dub card video will be deinterlaced if necessary so the field order does not need to match — progressive is preferred ● Dissolves and scrolling credits are not supported ● First and last frames do not need to be black frames Film Content Profiles Film Dub Card Video Profile 2012-05-22 | © 2012 Apple Inc. All Rights Reserved. 24Film Chapter Image Profile ● JPEG with .jpg extension (quality unconstrained) ● RGB (screen standard) ● Must be same aspect ratio as video source ● 640 minimum horizontal dimension (larger for HD sourced) ● Variable size vertical dimension (based on aspect ratio of video source) ● Only active pixel area may be included ● Chapter images must be cropped (no letterbox, pillarbox, or windowbox) ● Chapter images must contain picture content ● Chapter image files must be unique with different checksums Important CMYK (print standard) images will not be accepted. Film Poster Art Profile ● JPEG with .jpg extension (quality unconstrained) or PNG with .png extension ● RGB (screen standard) ● 1400 x 2100 pixels minimum size ● 2:3 aspect ratio ● Poster art (one-sheet) from film. Must contain key art and title. DVD cover, release date, website, or promotional tagging may not be included. ● Poster art must not display film ratings. Do not increase the size of a smaller image to meet the minimum size standard. Excessively blurry or pixelated images will be rejected. Important CMYK (print standard) images will not be accepted. Film Content Profiles Film Chapter Image Profile 2012-05-22 | © 2012 Apple Inc. All Rights Reserved. 25Film Content Considerations ● The full movie asset should not contain FBI, MPAA, or release date tagging. ● The trailer asset should not contain FBI, MPAA, or release date tagging. ● A minimum of 1 black frame at the beginning and end of each video is required. ● Trailer should be same aspect ratio as the full asset. ● Promotional bumpers, including URLs, are NOT accepted. For more details, please contact your iTunes Technical Representative. ● Trailers must contain content suitable for a general audience. ● Poster art should not contain DVD tagging, release date tagging, or website tagging. Film Content Profiles Film Content Considerations 2012-05-22 | © 2012 Apple Inc. All Rights Reserved. 26● All XML must be encoded in UTF-8. ● No byte order markers (BOM) can be used. ● There should be no null data or empty tags in the XML. If not used, elements should be removed. ● The XML must be formatted to use line breaks and indentations. For further information, please refer to the appropriate media type metadata specification, or consult with your iTunes Technical Representative. 2012-05-22 | © 2012 Apple Inc. All Rights Reserved. 27 XMLPrevious Spec Revisions The following table lists the previously-released specifications and the revisions: Date/Version Summary Added crop dimensions for TV. Clarified content considerations for TV. Clarified closed captioning for TV. Added delivery requirements for iTT files. September 22, 2011 - Version 4.8 Clarified delivery requirements for 5.1 audio and closed captioning. Added the profile for closed captioning for TV. Film poster art requirements have changed. July 13, 2011 - Version 4.7 Revision 2 Clarified HD cropping for TV. Added color space requirement for HD film source. Clarified closed captioning text for film. April 15, 2011 - Version 4.7 Removed assetspecificationsfor books(a new iBookstore asset guide has been created). Renamed this asset guide to: iTunes Video and Audio Asset Guide . February 9, 2011 - Version 4.6 Clarified surround sound for HD music video audio source profile. Clarified delivery of HD source for music videos. Added a chapter for book source profiles. Put back 25 fps in the HD TV source profile that was incorrectly removed. Added two new best practice items to the TV Content Considerations section. November 5, 2010 - Version 4.5 Added source profile for HD music video and cropping information. Clarified album cover art. Added surround sound to HD music video audio source profile. August 5, 2010 - Version 4.4 Clarified that ALAC in a CAF container is allowed. Added source profile for pre-cut ringtones. Clarified that film ratings should not appear on poster art. February 3, 2010 - Version 4.3 December 18, 2009 - Version Clarified quality standards. Clarified closed captioning. 4.2 November 10, 2009 - Version Clarified audio requirements for music and film. 4.1 2012-05-22 | © 2012 Apple Inc. All Rights Reserved. 28 Revision HistoryDate/Version Summary Added best practices content for Film. Clarified requirements for SCC files. September 11, 2009 - Version 4.0 Clarified image and audio requirements. Clarified frame rate requirements for TV. July 1, 2009 - Version 3.3.2 Added support for PNG format images for cover art, poster art, and video screen captures. PNG images are not currently supported for chapter thumbnail images. May 12, 2009 - Version 3.3.1 Added updated PAL support for film. Added closed-captioning to Film Content Profile. Added 24-bit support for audio. Added best practices content for TV. Clarified how to send stereo sound for Film and TV. March 17, 2009 - Version 3.3 Added audio source specification to Music Audio Content Profile, added HD format to Television Content Profile and Appendix I, which provides audio channel assignments instructions. October 1, 2008 - Version 3.2 Complete reformatting of the Guide. Separation of content type profiles. Addition of Movie HD and SD specification. Addition of image specifications for TV and Film. May 8, 2008 - Version 3.1.1 April 2, 2007 - Version 2.3 Introduction of Asset Specification Guide. Revision History Previous Spec Revisions 2012-05-22 | © 2012 Apple Inc. All Rights Reserved. 29How to Apply Audio Channel Assignments Step 1: Open the Movie Properties window from the Window > Show Movie Properties menu. Important You must use the Pro version of QuickTime. 2012-05-22 | © 2012 Apple Inc. All Rights Reserved. 30 Audio Channel AssignmentsStandard Movie Properties window: Audio Channel Assignments How to Apply Audio Channel Assignments 2012-05-22 | © 2012 Apple Inc. All Rights Reserved. 31Step 2: Go to the View > Columns menu and choose Channels. You may add additional columns like ID, Data Rate, and so on. Audio Channel Assignments How to Apply Audio Channel Assignments 2012-05-22 | © 2012 Apple Inc. All Rights Reserved. 32Notice the Channels column in the following screenshot indicates the audio tracks are Mono. Step 3: Select the sound track to make the audio channel assignment and click the Audio Settings tab. Audio Channel Assignments How to Apply Audio Channel Assignments 2012-05-22 | © 2012 Apple Inc. All Rights Reserved. 33Step 4: To make the Channel Assignment, choose the appropriate setting from the pop-up menu. Repeat this process for each audio track. In this example all the tracks have been properly assigned for the channel assignments of Option 2 asindicated in the Audio/Video Containersection for“Television Content Profiles” (page 13) and “Film Content Profiles” (page 20). Audio Channel Assignments How to Apply Audio Channel Assignments 2012-05-22 | © 2012 Apple Inc. All Rights Reserved. 34Notice the Channels column in the following screenshot no longer indicates the audio tracks are Mono. Noticethisindicatestheassignment. Thisshouldnotindicatemono. Step 5: Save the file. Step 6: Open the Movie Inspector from the Window > Show Movie Inspector menu to verify assignments were applied correctly. Audio Channel Assignments How to Apply Audio Channel Assignments 2012-05-22 | © 2012 Apple Inc. All Rights Reserved. 35Table 1: Audio Channel Assignment Labels Label Description L Left R Right C Center LFE LFE Screen Ls Left Surround Rs Right Surround Lt* Left Total Rt* Right Total * Lt and Rt are supported in the latest version of QuickTime. Audio Channel Assignments How to Apply Audio Channel Assignments 2012-05-22 | © 2012 Apple Inc. All Rights Reserved. 36Apple Inc. © 2012 Apple Inc. All rights reserved. No part of this publication may be reproduced, stored in a retrievalsystem, or transmitted, in any form or by any means, mechanical, electronic, photocopying, recording, or otherwise, without prior written permission of Apple Inc., with the following exceptions: Any person is hereby authorized to store documentation on a single computer for personal use only and to print copies of documentation for personal use provided that the documentation contains Apple’s copyright notice. The Apple logo is a trademark of Apple Inc. No licenses, express or implied, are granted with respect to any of the technology described in this document. Apple retains all intellectual property rights associated with the technology described in this document. This document is intended to assist application developers to develop applications only for Apple-labeled computers. Apple Inc. 1 Infinite Loop Cupertino, CA 95014 408-996-1010 .Mac is a registered service mark of Apple Inc. iBookstore is a service mark of Apple Inc. iTunes Store is a registered service mark of Apple Inc. Apple, the Apple logo, iBook, iBooks, iTunes, Logic, Mac, and QuickTime are trademarks of Apple Inc., registered in the United States and other countries. DEC is a trademark of Digital Equipment Corporation. Dolby and Pro Logic are trademarks of Dolby Laboratories. Even though Apple has reviewed this document, APPLE MAKES NO WARRANTY OR REPRESENTATION, EITHER EXPRESS OR IMPLIED, WITH RESPECT TO THIS DOCUMENT, ITS QUALITY, ACCURACY, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.ASARESULT, THISDOCUMENT IS PROVIDED “AS IS,” AND YOU, THE READER, ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND ACCURACY. IN NO EVENT WILL APPLE BE LIABLE FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL,OR CONSEQUENTIAL DAMAGES RESULTING FROM ANY DEFECT OR INACCURACY IN THIS DOCUMENT, even if advised of the possibility of such damages. THE WARRANTY AND REMEDIES SET FORTH ABOVE ARE EXCLUSIVE AND IN LIEU OF ALL OTHERS, ORAL OR WRITTEN, EXPRESS OR IMPLIED. No Apple dealer, agent, or employee is authorized to make any modification, extension, or addition to this warranty. Some states do not allow the exclusion or limitation of implied warranties or liability for incidental or consequential damages, so the above limitation or exclusion may not apply to you. This warranty gives you specific legal rights, and you may also have other rights which vary from state to state. Apple Remote Desktop Administrator’s Guide Version 3K Apple Computer, Inc. © 2006 Apple Computer, Inc. All rights reserved. The owner or authorized user of a valid copy of Apple Remote Desktop software may reproduce this publication for the purpose of learning to use such software. No part of this publication may be reproduced or transmitted for commercial purposes, such as selling copies of this publication or for providing paid for support services. The Apple logo is a trademark of Apple Computer, Inc., registered in the U.S. and other countries. Use of the “keyboard” Apple logo (Option-Shift-K) for commercial purposes without the prior written consent of Apple may constitute trademark infringement and unfair competition in violation of federal and state laws. Apple, the Apple logo, AirPort, AppleScript, AppleTalk, AppleWorks, FireWire, iBook, iMac, iSight, Keychain, Mac, Macintosh, Mac OS, PowerBook, QuickTime, and Xserve are trademarks of Apple Computer, Inc., registered in the U.S. and other countries. Apple Remote Desktop, Bonjour, eMac, Finder, iCal, and Safari are trademarks of Apple Computer, Inc. Adobe and Acrobat are trademarks of Adobe Systems Incorporated. Java and all Java-based trademarks and logos are trademarks or registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. UNIX is a registered trademark in the United States and other countries, licensed exclusively through X/Open Company, Ltd. 019-0629/02-28-06 3 3 Contents Preface 9 About This Book 10 Using This Guide 10 Remote Desktop Help 10 Notation Conventions 11 Where to Find More Information About Apple Remote Desktop Chapter 1 13 Using Apple Remote Desktop 13 Administering Computers 15 Deploying Software 18 Taking Inventory 21 Housekeeping 22 Supporting Users 23 Providing Help Desk Support 25 Interacting with Students 26 Finding More Information Chapter 2 28 Getting to Know Remote Desktop 28 Remote Desktop Human Interface Guide 29 Remote Desktop Main Window 31 Task Dialogs 32 Control and Observe Window 33 Multiple-Client Observe Window 34 Report Window 35 Changing Report Layout 36 Configuring Remote Desktop 36 Customizing the Remote Desktop Toolbar 36 Setting Preferences for the Remote Desktop Administrator Application 37 Interface Tips and Shortcuts Chapter 3 39 Installing Apple Remote Desktop 39 System Requirements for Apple Remote Desktop 40 Network Requirements 40 Installing the Remote Desktop Administrator Software 41 Setting Up an Apple Remote Desktop Client Computer for the First Time4 Contents 41 Upgrading the Remote Desktop Administrator Software 42 Upgrading the Client Software 42 Method #1—Remote Upgrade Installation 43 Method #2—Manual Installation 43 Upgrading Apple Remote Desktop Clients Using SSH 44 Creating a Custom Client Installer 46 Considerations for Managed Clients 46 Removing or Disabling Apple Remote Desktop 46 Uninstalling the Administrator Software 47 Disabling the Client Software 48 Uninstalling the Client Software from Client Computers Chapter 4 49 Organizing Client Computers Into Computer Lists 49 Finding and Adding Clients to Apple Remote Desktop Computer Lists 50 Finding Clients by Searching the Local Network 50 Finding Clients by Searching a Network Range 51 Finding Clients by Network Address 52 Finding Clients by File Import 52 Making a New Scanner 53 Making and Managing Lists 53 About Apple Remote Desktop Computer Lists 54 Creating an Apple Remote Desktop Computer List 54 Deleting Apple Remote Desktop Lists 54 Creating a Smart Computer List 55 Editing a Smart Computer List 55 Creating a List of Computers of from Existing Computer Lists 56 Importing and Exporting Computer Lists 56 Transferring Computer Lists from Apple Remote Desktop 3 to a New Administrator Computer 57 Transferring Remote Desktop 2 Computer Lists to a New Remote Desktop 3 Administrator Computer 57 Transferring Old v1.2 Computer Lists to a New Administrator Computer Chapter 5 59 Understanding and Controlling Access Privileges 59 Apple Remote Desktop Administrator Access 61 Setting Apple Remote Desktop Administrator Access Authorization and Privileges Using Local Accounts 62 Apple Remote Desktop Administrator Access Using Directory Services 62 Creating Administrator Access Groups 65 Enabling Directory Services Group Authorization 65 Apple Remote Desktop Guest Access 66 Apple Remote Desktop Nonadministrator Access 67 Virtual Network Computing AccessContents 5 68 Command-Line SSH Access 68 Managing Client Administration Settings and Privileges 69 Getting an Administration Settings Report 69 Changing Client Administrator Privileges Chapter 6 71 Setting Up the Network and Maintaining Security 71 Setting Up the Network 72 Using Apple Remote Desktop with Computers in an AirPort Wireless Network 73 Getting the Best Performance 73 Maintaining Security 75 Remote Desktop Authentication and Data Transport Encryption 75 Encrypting Observe and Control Network Data 76 Encrypting Network Data During Copy Items and Install Packages Tasks Chapter 7 77 Interacting with Users 78 Controlling 78 Controlling Apple Remote Desktop Clients 79 Control Window Options 80 Switching the Control Window Between Full Size And Fit-To-Window 80 Switching Between Control and Observe Modes 80 Sharing Control with a User 81 Hiding a User’s Screen While Controlling 81 Capturing the Control Window to a File 81 Switching Control Session Between Full Screen and In a Window 82 Sharing Clipboards for Copy and Paste 82 Controlling VNC Servers 83 Setting up a Non–Mac OS X VNC Server 84 VNC Control Options 85 Configuring an Apple Remote Desktop Client to be Controlled by a VNC Viewer 85 Observing 87 Changing Observe Settings While Observing 88 Changing Screen Titles While Observing 88 Viewing a User’s Account Picture While Observing 88 Viewing a Computer’s System Status While at the Observe Window 90 Shortcuts in the Multiple Screen Observe Window 90 Observing a Single Computer 91 Observing Multiple Computers 91 Observing a Computer in Dashboard 92 Sending Messages 92 Sending One-Way Messages 92 Interactive Chat 93 Viewing Attention Requests 93 Sharing Screens6 Contents 93 Sharing a Screen with Client Computers 94 Monitoring a Screen Sharing Tasks 94 Interacting with Your Apple Remote Desktop Administrator 94 Requesting Administrator Attention 95 Canceling an Attention Request 95 Changing Your Observed Client Icon Chapter 8 96 Administering Client Computers 96 Keeping Track of Task Progress and History 97 Enabling a Task Notification Script 98 Getting Active Task Status 98 Using the Task Feedback Display 98 Stopping a Currently Running Task 99 Getting Completed Task History 99 Saving a Task for Later Use 100 Creating and Using Task Templates 101 Editing a Saved Task 101 Installing Software Using Apple Remote Desktop 101 Installing by Package and Metapackage 103 Installing Software on Offline Computers 104 Installing by Using the Copy Items Command 104 Using Installers from Other Companies 105 Upgrading Software 106 Copying Files 107 Copy Options 108 Copying from Administrator to Clients 109 Copying Using Drag and Drop 110 Restoring Items from a Master Copy 111 Creating Reports 111 Collecting Report Data 112 Using a Task Server for Report Data Collection 113 Report Database Recommendations and Bandwidth Usage 114 Auditing Client Usage Information 116 Finding Files, Folders, and Applications 118 Comparing Software 119 Auditing Hardware 124 Testing Network Responsiveness 125 Exporting Report Information 126 Using Report Windows to Work with Computers 127 Maintaining Systems 127 Deleting Items 128 Emptying the Trash 128 Setting the Startup DiskContents 7 129 Renaming Computers 129 Synchronizing Computer Time 130 Setting Computer Audio Volume 131 Repairing File Permissions 131 Adding Items to the Dock 132 Changing Energy Saver Preferences 133 Changing Sharing Preferences for Remote Login 133 Setting Printer Preferences 135 Managing Computers 135 Opening Files and Folders 136 Opening Applications 137 Quitting Applications Without Logging Out the User 137 Putting a Computer to Sleep 138 Waking Up a Computer 138 Locking a Computer Screen 139 Displaying a Custom Picture on a Locked Screen 139 Unlocking a Computer Screen 140 Disabling a Computer Screen 140 Logging In a User at the Login Window 141 Logging Out the Current User 141 Restarting a Computer 142 Shutting Down a Computer 143 UNIX Shell Commands 143 Send UNIX Command Templates 145 Executing a Single UNIX Command 145 Executing Scripts Using Send UNIX Command 147 Built-in Command-Line Tools 152 Automating Functions 152 Setting the Client’s Data Reporting Policy 153 Creating a Template Data Reporting Policy 154 Designating the Task Server and Setting the Report Data Collection Location 155 Scheduled Tasks 156 Using AppleScript with Remote Desktop 159 Using Automator with Remote Desktop Appendix A 161 Icon and Port Reference 161 Client Status Icons 161 Apple Remote Desktop Status Icons 162 List Menu Icons 162 Task Status Icons 163 System Status Icons (Basic) 163 System Status Icons (Detailed) 164 TCP and UDP Port Reference8 Contents Appendix B 165 Report Field Definitions Reference 165 System Overview Report 167 Storage Report 169 USB Devices Report 169 FireWire Devices Report 169 Memory Report 169 PCI Cards Report 170 Network Interfaces Report 172 Network Test Report 172 Administration Settings Report 173 Application Usage Report 173 User History Report Appendix C 174 AppleScript Remote Desktop Suite 174 Classes and Commands for the Remote Desktop Application. Appendix D 180 PostgreSQL Schema Sample Index 182 9 Preface About This Book What Is Apple Remote Desktop? Apple Remote Desktop is easy-to-use, powerful, open standards-based, desktop management software for all your networked Macs. IT professionals can remotely control and configure systems, install software, offer interactive online help to end users, and assemble detailed software and hardware reports for an entire Mac network. You can use Apple Remote Desktop to:  Manage client computers and maintain, update, and distribute software  Collect more than 200 system-information attributes for any Mac on your network  Store the results in an SQL database and view the information using any of several hardware or software reports  Control and manage multiple computer systems simultaneously, making shutdown, restart, and sending UNIX commands fast and easy  Provide help and remote assistance to users when they encounter problems  Interact with users by sending text messages, observing and controlling users’ screens, and sharing their screens with other client users You can use Apple Remote Desktop to manage your client systems. IT administrators use Remote Desktop in education and business to simplify and empower the management of their organizations computer assets. For system administrators, Apple Remote Desktop can be used to administer large numbers of servers, like a virtual Keyboard-Video-Mouse (KVM) sharing unit. In computer administration environments, it’s the ideal solution for managing remote systems, reducing administration costs, and increasing productivity. Apple Remote Desktop can also be used by educators to facilitate instruction in computer labs or one-on-one learning initiatives. Used in a classroom, Apple Remote Desktop enhances the learning experience and allows teachers to monitor and control students’ computers.10 Preface About This Book Using This Guide The Apple Remote Desktop Administrator’s Guide contains chapters to help you use Remote Desktop. It contains overviews and explanations about Apple Remote Desktop’s features and commands. It also explains how to install and configure Apple Remote Desktop on clients, how to administer client computers, and how to use Remote Desktop to interact with computer users. This guide is provided on the Apple Remote Desktop installation disc and on the Apple Remote Desktop support website as a fully searchable, bookmarked PDF file. You can use Apple’s Preview application or Adobe (Acrobat) Reader to browse the contents of this guide as well as search for specific terms, features, or tasks. Remote Desktop Help Remote Desktop Help is available using Help Viewer. To open Remote Desktop Help, choose Help > Remote Desktop Help. The help files contain the same information found in this guide, and are useful when trying to accomplish a task when this guide is unavailable. Additionally, the Remote Desktop Help contains new information, corrections, and latebreaking information about Apple Remote Desktop. The most up-to-date information is available through Remote Desktop Help before it’s available on the web as an updated PDF file. Notation Conventions This guide and Remote Desktop Help contain step-by-step procedures to help you use Remote Desktop’s commands effectively. In many tasks shown in this manual and in Remote Desktop Help, you need to choose menu commands, which look like this: Choose Edit > Clear. The first term after Choose is the name of a menu in the Remote Desktop menu bar. The next term (or terms) are the items you choose from that menu.Preface About This Book 11 Terminal Command Conventions Commands or command parameters that you might type, along with other text that normally appears in a Terminal window, are shown in this font. For example: You can use the doit command to get things done. When a command is shown on a line by itself as you might type it in a Terminal window, it follows a dollar sign that represents the shell prompt. For example: $ doit To use this command, type “doit” without the dollar sign at the command prompt in a Terminal window, then press the Return key. Where to Find More Information About Apple Remote Desktop For additional information related to Apple Remote Desktop, try these resources. You’ll find more information in the Apple Remote Desktop Read Me file and on the Apple Remote Desktop website: www.apple.com/remotedesktop/ You can find the most recent edition of the Apple Remote Desktop Administrator’s Guide at:  the Apple Server Division Documentation page www.apple.com/server/documentation/  the Remote Desktop section of Apple.com, and www.apple.com/remotedesktop/  the Help Menu in the Remote Desktop application Notation Indicates monospaced font A command or other Terminal text $ A shell prompt [text_in_brackets] An optional parameter (one|other) Alternative parameters (type one or the other) underlined A parameter you must replace with a value [...] A parameter that may be repeated A displayed value that depends on your configuration or settings12 Preface About This Book The Apple Remote Desktop Support website provides a database of technical articles about product issues, use, and implementation: www.apple.com/support/remotedesktop/ To provide feedback about Apple Remote Desktop, visit the feedback page: www.apple.com/feedback/remotedesktop.html For details about how to join the Apple Remote Desktop Mailing list, visit: lists.apple.com/mailman/listinfo/remote-desktop/ To share information and learn from others in online discussions, visit the Apple Remote Desktop Discussions Forum: discussions.info.apple.com/appleremotedesktop/ For more information about PostgreSQL go to: www.postgresql.org For more information about using Apple products for IT professionals go to: apple.com/itpro/1 13 1 Using Apple Remote Desktop Apple Remote Desktop helps you keep Macintosh computers and the software running on them up to date and trouble free. And it lets you interact directly with Macintosh users to provide instructional and troubleshooting support. This chapter describes the main aspects of Apple Remote Desktop’s administration and user interaction capabilities and tells you where to find complete instructions for using them. Administering Computers Apple Remote Desktop lets you perform a wide range of client hardware and software administrative activities remotely, from an administrator computer (a computer on which administrator software resides):  Keep users’ software up to date by using Apple Remote Desktop to deploy software and related files to client computers.  Create reports that inventory the characteristics of client computer software and hardware.  Use Apple Remote Desktop’s remote administration capabilities to perform housekeeping tasks for client computers.14 Chapter 1 Using Apple Remote Desktop You can administer client computers individually, but most Apple Remote Desktop features can be used to manage multiple computers at the same time. For example, you may want to install or update the same applications on all the computers in a particular department. Or you may want to share your computer screen to demonstrate a task to a group of users, such as students in a training room. To manage multiple computers with a single action, you define Apple Remote Desktop computer lists. A computer list is a group of computers that you want to administer similarly. Computer lists let you group and organize computers for administration. Setting up computer lists is easy; you simply scan the network or import the identity of computers from files. A particular computer can belong to more than one list, giving you a lot of flexibility for multicomputer management. A computer can be categorized by its type (laptop, desktop), its physical location (building 3, 4th floor), its use (marketing, engineering, computing), and so forth. Once you’ve set up computer lists, you can perform most of the computer administration activities described next for groups of client computers. Marketing department Engineering departmentChapter 1 Using Apple Remote Desktop 15 Deploying Software Apple Remote Desktop lets you distribute software and related files to client computers from your Apple Remote Desktop administrator computer or from a computer running Mac OS X Server. Distributing Installer Packages You can distribute and automatically install packages in .pkg and .mpkg formats. Apple Remote Desktop lets you install software and software updates on one or more client computers without user interaction or interruption, or even if no user is logged in. After installation, Apple Remote Desktop erases the installer files. If the computers need to be restarted, as they do following an operating system update, you can restart them from Apple Remote Desktop. Xserve cluster node Marketing department Engineering department Deploy configuration files Deploy drag-and-drop application folders Deploy install packages (.pkg or .mpkg) Network install images NetBoot images Deploy UNIX shell scripts Set startup partition Administrator computer Mac OS X Server16 Chapter 1 Using Apple Remote Desktop For example, you can use Apple Software Update to download an iCal update or an operating system update to a test computer. If the update works as expected and introduces no compatibility issues, copy the installer package to the administrator computer to distribute to computers that need upgrading. Note that this approach conserves Internet bandwidth, because only one copy of the package needs to be downloaded. You can also use Apple Remote Desktop to deploy new versions of computational software to Xserve computers in a cluster node. You can use the PackageMaker tool (included on the Apple Remote Desktop installation CD and with Apple’s developer tools) to create your own installer packages, such as when you want to:  Distribute school project materials or business forms and templates  Automate the installation of multiple installer packages  Deploy custom applications Before performing remote installations, you can send an Apple Remote Desktop text message to notify users, perhaps letting them know that you’ll be using Apple Remote Desktop to lock their screens at a particular time before you start the installation. Using Network Install Images You can also distribute and install software, including the Mac OS X operating system, by using Network Install images. On Mac OS X Server, use the Network Image Utility to create a Network Install image. You can create the image by cloning a system that’s already installed and set up, or by using an installation disc or an image downloaded using Apple Software Update. If you choose to auto-install, you won’t have to interact with each computer. On the Apple Remote Desktop administrator computer, set the startup disk of remote client systems to point to the Network Install image, and then remotely reboot the clients to initiate installation. Before initiating installations that require computers to be restarted afterwards, send an Apple Remote Desktop text message to client users to notify them of a pending installation. For example, tell users you’ll log them off at 5:00 p.m. to install an operating system update. Using NetBoot Images Another kind of system image you can create using Mac OS X Server is a NetBoot image. Like a Network Install image, a client computer uses NetBoot images to start up. Unlike a Network Install image, the boot software is not installed on the client system. Instead, it resides on a remote server. It is recommended you use a NetBoot image that has Apple Remote Desktop installed and configured. Otherwise, administering the computer using Apple Remote Desktop after starting up from NetBoot is impossible.Chapter 1 Using Apple Remote Desktop 17 Client computers that boot from a NetBoot image get a fresh system environment every time they start up. For this reason, using NetBoot images is useful when a particular computer is shared by several users who require different work environments or refreshed work environments, or when you want to start a new experiment or use a different computing environment in a cluster node. You can use Apple Remote Desktop to set the startup disks of client systems to point to the NetBoot image, and then restart the systems remotely using Apple Remote Desktop. Users can also choose a NetBoot image for startup by using the Startup Disk pane of System Preferences. With just a few clicks you can reconfigure all the computers in a lab or cluster without having to manually restart and configure each computer individually. Distributing Preference Files Managed computers often require a standard set of preferences for each instance of an application. Use Apple Remote Desktop to distribute preference files when you need to replace or update a application preferences. For example, you can copy a standardized preference file to the currently logged in user’s Library/Preferences folder. Using UNIX Shell Scripts You can use Apple Remote Desktop to distribute and run UNIX shell scripts on client computers. For example, a script can mount an AFP server volume, from which it downloads a disk image to client computers. The script might also download an installer package and then perform a command-line installation. On an Xserve in a cluster node, you could also run a script that mounts an Xserve RAID disk designed for high throughput and then downloads large data sets for processing. You can also use Apple Remote Desktop to distribute AppleScript files that automate PDF workflows, or job instructions for computational clusters. Distributing Drag-and-Drop Applications You can distribute and install self-contained (drag-and-drop) applications by copying them to one or more client computers. Use this approach, for example, to distribute application updates. Verifying Installations To check whether an installation has been completed successfully, use Apple Remote Desktop’s remote control capabilities. For example, you can start an application remotely, or search for particular files. You can also use the File Search report to verify that all files for an application are installed correctly.18 Chapter 1 Using Apple Remote Desktop Taking Inventory Apple Remote Desktop lets you capture data describing the attributes of client computers, then generate reports based on the data. You specify how often you want to capture data, the data you want to capture, and the computers you want to profile. You can collect data just before generating a report if you need up-to-the-minute information. Or you can schedule data to be collected by Apple Remote Desktop at regular intervals and stored in its built-in SQL (Structured Query Language) database for use on an as-needed basis. You can also specify where you want the database to reside—on the local administrator computer, or on a server where the Apple Remote Desktop administrator software is installed and always running, so data can be captured on an ongoing basis. Using the collected data, Apple Remote Desktop generates reports tailored to your specifications. Xserve cluster node Marketing department Engineering department Administrator computer Mac OS X Server ARD SQL database ARD SQL database SQL toolsChapter 1 Using Apple Remote Desktop 19 File Search Report Use the File Search report to search client systems for specific files and folders and to audit installed applications. This report can help you find out how many copies of a particular application are in use so you don’t violate license agreements. Spotlight File Search Use the Spotlight Search report to search Tiger client systems for specific files and folders. The information in the report is updated as files matching your search change on the client systems. Software Version Report Use the Software Version report to make sure that all users have the latest application versions appropriate for their systems. Software Difference Report Use the Software Difference report to detect application versions that are out of date, nonstandard, or unacceptable for some other reason. Or, you can learn whether a user has installed an application that shouldn’t be installed. System Overview Report The System Overview report makes visible a wide variety of client computer characteristics. Using this report, you can review information about a client’s AirPort setup, computer and display characteristics, devices, network settings, system preferences, printer lists, and key software attributes. There are numerous uses for this report, such as identifying problems or verifying system configurations before installing new software, or determining how many devices of a particular type (such as scanners) are in a particular lab. Hardware Reports Several reports provide details about particular hardware used by client computers— storage, FireWire devices, USB devices, network interfaces, memory, and PCI cards. Use these reports to determine, for example, which computers need more memory, which computer has the fastest processor speed, and how much free space is left on a particular disk. Administration Settings Report Use the Administration Settings report to determine which Apple Remote Desktop administrator privileges are enabled or disabled for you in the Sharing pane of System Preferences on individual client computers. User History Report Use the User History report to show you who has logged in to a client, how they logged in, and for how long.20 Chapter 1 Using Apple Remote Desktop Application Usage Report Use the Application Usage report to find out which applications have been running on your client computers and who ran those applications. Network Test Report A Network Test report helps you measure and troubleshoot the communication between your administrator computer and your client computers. The Network Interfaces report might also help troubleshooting network hardware issues. Use this report to help identify reasons for network communication problems that could affect Apple Remote Desktop. For example, if you’re unable to copy items to particular client computers from the administrator computer, you may find you have a bad connection to the computers. Using this information can help you isolate the problem to a particular cable or hub. Generating Your Own Reports Because the Apple Remote Desktop database is in standard SQL format, you can also use your favorite SQL scripts to query, sort, and analyze the collected data. In addition, you can export data from the database into a file so you can import it for viewing in a different program, such as a spreadsheet application.Chapter 1 Using Apple Remote Desktop 21 Housekeeping Apple Remote Desktop provides several ways to remotely control client computers for housekeeping activities, which you can conduct using one or more Apple Remote Desktop windows. Managing Power State Use Apple Remote Desktop to control the power state of client computers. For example, you may need to have all computers turned off during maintenance of a power generation unit or during a holiday shutdown. You can send an Apple Remote Desktop text message reminding users to shut down their computers at a particular time. Any computers still running when you need to start maintenance can be detected and shut down remotely with Apple Remote Desktop. Xserve cluster node Marketing department Engineering department Administrator computer Execute UNIX shell script Restart/ shutdown/sleep Remote screen control Empty Trash Set startup partition Send text notification Mac OS X Server NetBoot images22 Chapter 1 Using Apple Remote Desktop Locking Computer Screens You can lock the screens of client computers for specified durations when you don’t want the computers to be used. For example, you may need to perform network maintenance and want to make sure computers don’t use the network for a few hours. You can display custom pictures or text messages on locked computer screens to let users know when the computers are available again. Reclaiming Disk Space Periodically empty the Trash on client computers to conserve disk space. Automating Periodic Maintenance Use AppleScript and UNIX shell scripts to automate periodic maintenance, such as checking permissions or deleting log files. Controlling Screens Use Apple Remote Desktop’s remote screen control to perform activities on the desktop of Xserve computers, or use graphical applications on them. Apple Remote Desktop replaces the need for KVM (keyboard-video-mouse) switches for accessing Xserve computers without a monitor attached. You can also remotely control a user’s computer to help determine reasons for slow performance or other problems. Changing Startup Disks Change the startup disk of a client computer to perform diagnostic or troubleshooting activities. For example, start up a computer using a server-based NetBoot image that’s been set up for troubleshooting. When you’re finished, reset the startup disk to the original boot volume. Managing Shared Computers On computers that are shared among users, check for files that need to be deleted, close applications, log users off, or perform other activities needed to prepare computers for the next users. Supporting Users Apple Remote Desktop lets you interact with users from your administrator computer in these ways:  Provide help: respond to users who need help by using Apple Remote Desktop to receive user requests and to remotely diagnose and fix problems.  Interact: conduct instructional interactions with students in a school or corporate training environment—from controlling or observing student screens to sharing your screen with all your students in order to perform a demonstration.Chapter 1 Using Apple Remote Desktop 23 Providing Help Desk Support When a user is having trouble, Apple Remote Desktop provides several ways to interact with the user and his or her computer to diagnose and fix the problem. Requesting Help A user can discreetly notify you of a problem by sending a request for help using an Apple Remote Desktop text message. Users initiate requests using the commands in the menu that appears when they click the Apple Remote Desktop icon in the menu bar. A notification on the administrator computer alerts you to the message, and you can use several techniques to obtain more information and troubleshoot the problem. Chatting with the User Conduct two-way Apple Remote Desktop text communication with the user to obtain more information. Screen Monitoring Use Apple Remote Desktop to observe the user’s screen if you need more details to understand the problem. Marketing department Engineering department Copy items Administrator computer Control, observe, and share screens Use text chat24 Chapter 1 Using Apple Remote Desktop Screen Controlling Use Apple Remote Desktop to control the user’s screen in order to diagnose and fix the problem. You may have unlimited control, or a user can grant you temporary guest access so you can control the computer only during troubleshooting. There are two levels of control available. You can take complete control of the user’s computer, or you can share control of the keyboard and mouse with the user. Screen Sharing If the problem is caused by incorrect actions by the user, share your screen with the user as you demonstrate the correct way to perform the action. Using Reports Use hardware and software reports as diagnostic tools to determine whether the client computer setup is part of the problem. For example, if a user can’t save his or her work, the storage report can help you determine whether it’s a disk space issue. Deploying New Software or Files If software or configuration settings are part of the problem, use Apple Remote Desktop to copy new configuration files, installer packages, or other items to client computers.Chapter 1 Using Apple Remote Desktop 25 Interacting with Students Apple Remote Desktop helps instructors teach more efficiently by letting them interact with student computers individually or as a group. Using Text Messages Send Apple Remote Desktop text messages to communicate with students. For example, notify them that a classroom activity will start soon or that they have ten minutes to finish an examination. Monitoring Student Computers View student computer screens on your computer, so you can monitor student activities or assess how well they’re able to perform a particular task. You can also monitor the applications running on any student’s computer. Sharing Screens Display your screen or a student’s screen on other student computers for training and demonstration purposes. Controlling Screens Show students how to perform tasks by controlling their screens from your computer, opening applications and using files as required. Classroom Administrator computer Observe and share one or multiple screens One-to-one help desk support Broadcast text messages Lock screens Distribute items electronically Open applications or files Control screen Log out students26 Chapter 1 Using Apple Remote Desktop Locking Screens Lock student screens to prevent students from using their computer when you want them to focus on other activities. Terminating Computer Use Remotely log students out or shut down their computers at the end of a class or school day. Distributing and Collecting Files Distribute handouts electronically, at a time that won’t disrupt class activities or when they’re needed for the next class activity, and collect homework files. Automating Website Access Open a webpage on all student computers. Drag a URL from Safari to your desktop, then copy it to student computers and open it in Safari. You can also copy files and open them in the appropriate applications on student computers. Providing One-to-One Assistance Provide help when a student needs it, conducting private and discreet computer-tocomputer interactions. Finding More Information You’ll find detailed instructions for performing the tasks highlighted in this chapter— and more—throughout this manual. To learn more about See information for Starting on page Remote Dekstop interface Window and icon functions page 28 Computer lists Creating computer lists page 49 Apple Remote Desktop administration Administrator privileges Administrator computers page 59 Controlling screens Controlling page 78 Observing screens Observing page 85 Deploying software Installing software Upgrading software page 101 Distributing files Copying files page 106 Taking inventory Data collection options Auditing software Auditing hardware Network responsiveness Customizing reports Exporting report data page 111 Client use reporting User login accounting Application usage page 114Chapter 1 Using Apple Remote Desktop 27 Additional information can be obtained at several Apple websites:  For information about NetBoot and Network Install, download the system imaging administration guide at: www.apple.com/server/documentation  You can find PackageMaker’s documentation at Apple’s Developer Connection: http://developer.apple.com/documentation/DeveloperTools/Conceptual/ SoftwareDistribution/index.html? Housekeeping tasks Deleting items Emptying the Trash Setting startup volumes Renaming computers Sleeping and waking Locking screens Logging users out Restart and shutdown page 127 Automating tasks Configuring data gathering Scheduling tasks Using UNIX shell scripts page 152 To learn more about See information for Starting on page2 28 2 Getting to Know Remote Desktop Remote Desktop is the administrator application for Apple Remote Desktop. Its attractive interface is powerful, yet simple to use. Remote Desktop’s interface is customizable, allowing you to get the information you want quickly, the way you want it. This chapter contains screenshots and short descriptions of Remote Desktop’s interface, as well as detailed instructions for customizing the appearance and preferences of the application. You will learn about:  “Remote Desktop Human Interface Guide” on page 28  “Configuring Remote Desktop” on page 36  “Interface Tips and Shortcuts” on page 37 Remote Desktop Human Interface Guide The following sections give basic information about the human interface of Remote Desktop, Apple Remote Desktop’s administrator application.  “Remote Desktop Main Window” on page 29  “Task Dialogs” on page 31  “Control and Observe Window” on page 32  “Multiple-Client Observe Window” on page 33  “Report Window” on page 34  “Changing Report Layout” on page 35Chapter 2 Getting to Know Remote Desktop 29 Remote Desktop Main Window The main window of Remote Desktop has a customizable toolbar, groups of lists, tasks, and scanners on the left, and the main window area to the right. “List Menu Icons” on page 162 contains icons seen in the list menu of the main window. A All Computers list: The All Computers list is a list of all client computers that you plan to administer. It includes all the clients you have authenticated to, as well as the client computers that you plan to authenticate to. Computers need to be in the All Computers list before you can command or administer them. If you have a 10-client license, the All Computers list can contain only 10 computers. B Apple Remote Desktop computer lists: A list of computers you create to group computers in ways that are convenient for you. Any list is a subset of the client computers in the All Computers list. If you add a computer directly to a computer list, it is added automatically to the All Computers list as well. C Smart computer lists: A smart computer list is a list of computers which is a subset of the client computers in the All Computers list that meet a predetermined criteria. Smart Computer lists update themselves based on your criteria compared to the contents of the All Computers list. D Group folders: Groups are tools to help you organize all your possible lists, tasks, and scanners. Groups look like folders, and can be collapsed to hide the group contents. E Saved tasks: Saved tasks are listed in the left portion of the main window. They have the icon of the type of task and have a user-changeable name. A B C D E F G I H K L J30 Chapter 2 Getting to Know Remote Desktop F Scanner: Scanners find clients to add to the All Computers list. You can make new scanners and customize them for your needs. See “Making a New Scanner” on page 52. G Task server list: This lists tasks delegated to the Task Server, rather than run those run directly from the application. When all the target computers have come online and participated in the task, the task is labeled as complete. H Active tasks list: This list shows all tasks that are currently running or scheduled and uncompleted. I Task history list: The task history list shows a list of most recently run tasks, as defined in the Remote Desktop preferences. You can inspect each task by double-clicking it. Once a task is completed (whether successfully or not) it is moved to the Task History list. J Task status icon: These icons represent the current state of a task. See “Task Status Icons” on page 162. K Client status icon: Icon representing the current state of a client computer. See “Client Status Icons” on page 161. L Customizable toolbar: The toolbar can be fully customized with icons of your most-used Apple Remote Desktop features.Chapter 2 Getting to Know Remote Desktop 31 Task Dialogs When you click a task, a dialog appears to let you set task parameters or confirm the task. A Task type header: This header area shows you the kind of task represented. B Saved task name: When you save a task, you name it for your own use. C Task configuration area: This area is different for every task. It’s where you set operating parameters for the task to be performed. D Participating computers: This area shows you the computers that will be affected by the task. You can add or remove computers in this area without changing computer list membership. E Schedule task button: When you click this button in a task dialog, you can set a time to perform the task as well as repeat the task. See “Scheduled Tasks” on page 155 for more information. F Save task button: When you click this button in a task dialog, you can name and save the task as configured. Saved tasks appear in the left side of Remote Desktop’s main window. G Task templates: This control allows you to save current task configuration settings, or apply previously saved settings to the current task. These templates are stored on a per-task basis. For example, the Send UNIX Commands template pop-up has an extensive list of built-in templates, while other tasks may have none. A B G C D E F32 Chapter 2 Getting to Know Remote Desktop Control and Observe Window This window is the same for both controlling and observing a single client. The only difference is the state of the Observe or Control toggle button. When it’s selected, you have control over the remote client. A Observe or control toggle: When this button is selected, you have control over the remote client. B Share mouse control: When this button is selected, you share mouse control with the user. C Fit screen in window: When this button is selected, the remote client is scaled to the Control window size. D Lock computer screen for control: When this button is selected, the remote client screen shows a lock, and your view allows you to view the client desktop normally. E Capture screen to file: When this button is clicked, the remote client screen is saved to a local file at the selected image quality. F Fit screen to full display: When this button is selected, your display doesn’t show your computer desktop, only that of the remote computer, at full possible resolution. G Get clipboard from client: When this button is clicked, the contents of the remote client Clipboard are transferred to the local Clipboard. A B C D E F G H J IChapter 2 Getting to Know Remote Desktop 33 Multiple-Client Observe Window When you observe many clients at the same time, they all appear in the same window. If you have more computers than will fit in the window, they are divided across several pages. H Send clipboard to the client: When clicked, the remote client Clipboard receives the contents of the local Clipboard. I Image Quality: Adjusts the screen color depth from black and white to millions of colors. J Desktop of Controlled Computer: Resize this window from the lower right corner. A Page Delay: Adjusts the number of seconds before automatically advancing to the next page of screens. B Computers Per Page: Adjusts the number of client screens visible on each page. C Image Quality: Adjusts the screen color depth from black and white to millions of colors. D Display Computer Information: Shows the computer information area, which contains desktop titles, account pictures, and status icons. E Computer title selector: Changes the titles displayed underneath the client screens (you can choose the computer name, IP address, or hostname). F Account picture: Shows the login icon of the currently logged in user. H A B C I G E I D F34 Chapter 2 Getting to Know Remote Desktop Report Window Reports serve as valuable shortcuts when you’re copying files and organizing computer lists. G Computer status: Shows basic computer status beneath each client screen. H Cycle through pages: Manually advances to the next page of screens. I View Options: Reveals the view option controls. J Observed computers: Contains the scaled desktops of the observed client computers. A Report category: Most reports have subcategories to help you find the information you want. In the report window, you switch between the subcategories using these tabs. B Save report to file: Saves the report to a plain text file. C Print: Formats and prints the report window. D Open selected: Opens the item selected in the report. The item opens on the client computer. C B A C B D E FChapter 2 Getting to Know Remote Desktop 35 Changing Report Layout You can customize report layouts for your own purposes. By default, reports include a column for each information type you selected before running the report, in the order presented in the report dialog. The columns in the report are initially sorted by computer name. You can resize or rearrange the columns of a report, as well as sort the rows by column. Additionally, in the File Search report, you can choose what information is displayed about a found item. By default, the item name, kind, parent path, actual size, and modification date are displayed. To change what information is displayed: 1 In the File Search report window, select or deselect each report column as desired. 2 After making your selections, click Generate Report as usual. When the report window appears, you can rearrange the columns or sort by a different column. E Delete selected: Deletes the item selected in the report from the remote computer. F Copy to this computer: Copies selected items to the administrator computer. Report column If checked, will show Name The item name Parent path The path to the folder that the item is in Full path The full file path Extension The file extension indicating the file type (.app, .zip, .jpg) Date modified The last date and time the file was changed and saved Date created The date and time the file was created Actual size Actual file size, in kilobytes or megabytes Size on disk Amount of disk space used by the file, in kilobytes Kind File, folder, or application Invisible A checkmark indicating whether it is visible in the Finder Version number If an application, the version reported Version string If an application, the version reported Owner The item owner’s short name Group The item’s group name Permissions The item’s UNIX permissions (for example, -rw-r--r--) Locked A checkmark indicating whether it is a locked file36 Chapter 2 Getting to Know Remote Desktop Configuring Remote Desktop You can configure the Remote Desktop administrator application to meet your work needs. Remote Desktop has an interface that is both flexible and functional. Customizing the Remote Desktop Toolbar The Remote Desktop application has a fully customizable toolbar, which provides a quick way to perform tasks. To perform a task, just click the appropriate icon in the toolbar. To show or hide the toolbar, click the toolbar button in the upper-right corner of the application window. You can add, remove, or rearrange the task icons in the toolbar to suit your needs. To customize the application toolbar: 1 Choose Window > Customize Toolbar. 2 Drag your favorite toolbar items or the default set of items to the toolbar. To remove an item, drag it from the toolbar. To rearrange items, drag them into the order you prefer. 3 Choose whether to display toolbar items as text, icons, or both. Selecting “Use Small Size” shrinks the items in the toolbar. Setting Preferences for the Remote Desktop Administrator Application In Remote Desktop preferences, you can select options that affect how the administrator application interacts with client computers. To open the Preferences window:  Choose Remote Desktop > Preferences. In the General pane, you can set:  What double-clicking a client computer does (Get Info, Control, Observe, Text Chat)  Whether to show the client idle time  What warnings may appear when quitting the application  A new serial number  A new Remote Desktop application password In the Control & Observe pane, you can set:  Whether a remote screen is shown in a window or a full screen  Whether control of the mouse and keyboard is shared with the client computer when the client is controlled  Whether a remote screen is shown at its actual size in a window or if it shrinks to fit the window In the Task Server pane, you can set:  Whether Remote desktop is using another computer as a Task Server, or whether this copy of Remote Desktop is being used as a Task ServerChapter 2 Getting to Know Remote Desktop 37  Whether other Apple Remote Desktop administrators can access your local Task Server  Whether clients collect user and application tracking data  A saved template for scheduling client reporting policies In the Labels pane, you can set:  Label colors and text for labeling computers In the Tasks pane, you can set:  Whether to automatically change focus to the active task  Whether to execute a notification script on task completion  Limits on task history list contents and time until removed In the Security pane, you can set:  Whether to accept messages from client users  Whether to allow control of the computer while Remote Desktop is active  The default encryption preference for control and observe sessions  The default encryption preference for Copy Items and Install Packages tasks  Which features of Remote Desktop are available to nonadministrator users See “Apple Remote Desktop Nonadministrator Access” on page 66. Interface Tips and Shortcuts There are a number of features of the Remote Desktop interface which make it particularly flexible and powerful. The following lists a few built-in shortcuts to features which can make using Remote Desktop more productive. Computers can be selected from any window Any computer in any window—report windows, task windows, computer lists, observe windows—can be a target for some task. For example, if you are observing 10 computer screens and need to send a text message to one, select the screen with a single click and then choose Interact > Send Text Message. Likewise, if you get a software report on 50 computers and notice that one of the computers is missing some vital piece of software, you can drop that software onto the selected computer within the report window. Treating all windows as possible computer selection lists for tasks may save you lots of time switching between the Remote Desktop window and other windows as you accomplish your work.38 Chapter 2 Getting to Know Remote Desktop Drag and drop works on configuration dialogs Configuration dialogs accept dragged items. Computer lists in the dialogs accept dragged computers. The Copy Items dialog accepts dragged files to copy, without having to browse the file system for them. Save yourself time and effort by dragging available items to dialogs rather than browsing for them. Making lists from reports or other lists You may need to make a list based on the outcome of some report, but you don’t know which computers will need to be included. After getting a report and sorting on the desired column, you can select the computers and make a new list from the selection. If you double-click the list icon, you open another window containing the computers in the list. This is useful for comparing lists, or for using the new window as a source from which to drag computers to other lists. Saved Tasks and Task Templates save you time You may spend a lot of time coming up with the perfect software search to find exactly what you need. You shouldn’t recreate that search every time you need it. Save your tasks, and duplicate them. With a little editing, you can have a number of similar saved tasks for specific uses. Alternatively, you can use task templates to save settings across task dialogs, applying the same settings through various tasks.3 39 3 Installing Apple Remote Desktop To use Apple Remote Desktop, install the administration software on the administrator computer first, and then install and enable the client software on the computers you want to manage. You’ll need your install disc, the serial number, and either the printed Welcome instructions, or these instructions. This chapter describes how to install Apple Remote Desktop for system administration and user interaction and gives complete setup instructions. You can learn about:  “System Requirements for Apple Remote Desktop” on page 39  “Installing the Remote Desktop Administrator Software” on page 40  “Setting Up an Apple Remote Desktop Client Computer for the First Time” on page 41  “Upgrading the Remote Desktop Administrator Software” on page 41  “Upgrading the Client Software” on page 42  “Creating a Custom Client Installer” on page 44  “Considerations for Managed Clients” on page 46  “Removing or Disabling Apple Remote Desktop” on page 46 System Requirements for Apple Remote Desktop Administrator and client computers:  Mac OS X or Mac OS X Server version 10.3.9 or later (Mac OS X version 10.4 or later is required for some features).  Mac OS Extended (HFS+) formatted hard disk.  For observing and controlling other platforms: a system running VNC-compatible server software. NetBoot and Network Install (optional)  Mac OS X Server version 10.3 or 10.4 with NetBoot and Network Install services enabled40 Chapter 3 Installing Apple Remote Desktop Network Requirements  Ethernet (recommended), AirPort, FireWire, or other network connection See “Setting Up the Network” on page 71 for more information. Installing the Remote Desktop Administrator Software To set up Apple Remote Desktop on administrator computers, you install the software on the computer you plan to use to administer remote computers. Then, you open the application setup assistant, and add to the main list of computers. To install Apple Remote Desktop on an administrator computer: 1 Insert the Apple Remote Desktop installation disc. 2 Double-click the Remote Desktop installer package and follow the onscreen instructions. The Remote Desktop application will be installed in the Applications folder. 3 Launch Remote Desktop (in the Applications folder). The Remote Desktop Setup Assistant appears. 4 Enter the serial number. The serial number can be found on the Apple Remote Desktop Welcome document that came with your software. Optionally, enter a registration name and organization. 5 Click Continue. 6 Enter a Remote Desktop application password and verify it. The Remote Desktop application password is used to encrypt names and passwords of client computers for Apple Remote Desktop. You can store this password in your keychain for convenience, or you can require that the password be entered each time you open Remote Desktop. 7 If you have another unlimited-licensed copy of Apple Remote Desktop acting as a Task Server (a dedicated computer running Remote Desktop for report data collection and delegated install tasks), enter the server address and click Continue. 8 Set the default data collection scope and time for newly administered computers. These settings will be stored as the default upload schedule, which can be applied to computers when you add them for administration. For more detailed information, see “Setting the Client’s Data Reporting Policy” on page 152. 9 Click Done. The main application window appears.Chapter 3 Installing Apple Remote Desktop 41 10 Configure some client computers for administration, find them in a scanner, and add them to a computer list. See:  “Setting Up an Apple Remote Desktop Client Computer for the First Time” on page 41  “Finding and Adding Clients to Apple Remote Desktop Computer Lists” on page 49 Setting Up an Apple Remote Desktop Client Computer for the First Time The following section contains information on setting up Apple Remote Desktop 3 on client computers. Since Apple Remote Desktop v1.2 was included with Mac OS X v10.3 computers and Apple Remote Desktop v2.2 was installed with Mac OS X v10.4 computers, all Apple Remote Desktop 3 client installations are upgrade installations, even if you are setting up clients for the first time. See “Upgrading the Client Software” on page 42 for more information. If the Apple Remote Desktop client software was removed from the computer, you can install a fresh copy of the most recent client software by installing Apple Remote Desktop manually. See “Method #2—Manual Installation” on page 43 for more information. If you’re setting up Mac OS X Server for the first time using Server Setup Assistant, you can enable Apple Remote Desktop as one of the initial services. This allows you to administer a server immediately after server software installation by providing Remote Desktop with the user name and password of the default system administrator. Upgrading the Remote Desktop Administrator Software Upgrading Remote Desktop is just like installing it for the first time. The only difference is that the final button in the installer reads “Upgrade” rather than “Install.” The installer upgrades existing software to its latest version, imports previously created lists, and restarts the underlying processes after completion. See “Installing the Remote Desktop Administrator Software” on page 40, for detailed instructions. If you are upgrading from version 1.2 and changing administrator computers, you’ll need to transfer your existing computer lists. See “Transferring Old v1.2 Computer Lists to a New Administrator Computer” on page 57. Be sure to transfer your lists from Apple Remote Desktop v1.2 to the new computer before upgrading to Apple Remote Desktop 3. If you upgrade from version 1.2 to version 3 on the same administrator computer, this list migration is done for you.42 Chapter 3 Installing Apple Remote Desktop Upgrading the Client Software This section contains information on installing Apple Remote Desktop 3 on client computers. Since Apple Remote Desktop client software was automatically included on the clients running Mac OS X v10.3 and v10.4, all Apple Remote Desktop 3 installations are upgrade installations, even if you are setting up clients for the first time. You can only upgrade Apple Remote Desktop v1.x and v2.x computers if they meet the minimum system requirements (see “System Requirements for Apple Remote Desktop” on page 39). Please note that there is no supported “downgrade” to any previous version, and if you upgrade the client computers to version 3, you will not be able to administer them with earlier versions of Remote Desktop. There are two methods to upgrade the client computer’s software. Method #1—Remote Upgrade Installation This method works best with existing clients already configured using a previous version of Apple Remote Desktop. If used with existing administered clients, use Remote Desktop to identify those clients running a previous version. You may then upgrade them to the latest version. The main benefit of this upgrade method is the ease of installation and the retention of previous client settings, if any. This method only works for Apple Remote Desktop 1.2 clients and later. Earlier versions of Apple Remote Desktop like 1.0 must be upgraded to version 1.2 using Mac OS X’s Software Update, or they must be updated manually. See “Method #2—Manual Installation” on page 43 for more information. To upgrade existing client software remotely using Apple Remote Desktop: 1 Enable the existing version of Apple Remote Desktop on the client computers. 2 Configure the clients for administration. See “Setting Apple Remote Desktop Administrator Access Authorization and Privileges Using Local Accounts” on page 61. 3 If the client computers are not in an existing Remote Desktop computer list, find the client computers using an Apple Remote Desktop scanner. See “Finding and Adding Clients to Apple Remote Desktop Computer Lists” on page 49 for more information. 4 Select the client computers to be upgraded. 5 Choose Manage > Upgrade Client Software. 6 Click Upgrade.Chapter 3 Installing Apple Remote Desktop 43 Method #2—Manual Installation This method works best if you have never enabled Apple Remote Desktop on your clients and have an existing software distribution infrastructure. This method also allows for the greatest power and configuration flexibility. Also, if you don’t want Apple Remote Desktop to upgrade your clients using the Upgrade Client Software feature, you can perform a manual upgrade. The custom installer not only installs the needed software but also prepares and configures the client computer for administration and can be configured to add or edit user names and passwords for Apple Remote Desktop authentication. To manually upgrade the client software: 1 Use Remote Desktop to create a client software installer package. For detailed instructions, see “Creating a Custom Client Installer” on page 44. 2 Copy and install the package on the client computers. You need the name and password of a user with administrator privileges on the computer to install the package. There are several ways to do this. For example, you can:  Distribute the package by removable media, such as a CD.  Copy the installer to the clients over the network using file sharing.  Copy the installer to the clients using command-line tools like scp (if ssh is enabled), and use Apple’s command-line installation tool, “installer,” to install the package remotely. This process is described in detail in “Upgrading Apple Remote Desktop Clients Using SSH” on page 43.  Add the custom installer package to a Network Install image, using System Image Utility to automatically include the software and your custom settings when clients install the operating system using Mac OS X Server 10.4’s NetBoot and Network Install features. Upgrading Apple Remote Desktop Clients Using SSH You may not be able to or want to use Remote Desktop to upgrade existing clients to Apple Remote Desktop 3. If the clients have SSH enabled (called Remote Login in System Preferences), and are available on the network, you can still upgrade the client computers. You still need to use Remote Desktop to create a custom installer package. You also need the user name and password of a user with system administrator privileges on the client computer. Warning: Custom install packages that create user names contain sensitive password data. Take care to store such custom installers securely.44 Chapter 3 Installing Apple Remote Desktop To upgrade existing client software using SSH: 1 Create the custom client installer package. For detailed instructions, see “Creating a Custom Client Installer” on page 44. 2 Open the Terminal application (located in /Applications/Utilities/). 3 Copy the installer package to the client computer by typing: $ scp -r @: For other options, see the scp man page. 4 Log in to the client computer by typing: $ ssh @ For other options, see the ssh man page. 5 On the client computer, install the package by typing: $ sudo installer -pkg -target / For other options, see installer man page. Creating a Custom Client Installer To install the Apple Remote Desktop client software on computers, you use the administrator application, Remote Desktop, to create a custom client installer. The custom client installer not only installs the Apple Remote Desktop system software, but can create user names and passwords on the client computer with their Apple Remote Desktop privileges already assigned. You’ll use an assistant to create a custom client installer package. Any values set in the custom installer will apply to all the computers that receive the installation. While creating a custom installer, you will have a chance to create new Apple Remote Desktop administrator user names with passwords, and automatically set Apple Remote Desktop access privileges and preferences. To create the client installer: 1 Open Remote Desktop. 2 Choose File > Create Client Installer. The Custom Installer Setup Assistant appears. 3 Choose to create a custom installer and click Continue. If you choose not to create a custom installer, you can create a basic installer that sets no preferences on the client computer. Warning: Custom installer packages that create user names contain sensitive password data. Take care to store and transmit such custom installers securely.Chapter 3 Installing Apple Remote Desktop 45 4 Click Continue to begin creating a custom installer. 5 Choose whether to start Remote Desktop sharing at system startup. This changes the setting found in the Sharing pane of System Preferences. 6 Choose whether to hide or show the Apple Remote Desktop menu bar icon. 7 Click Continue. 8 Choose whether to create a new user for Apple Remote Desktop login. Click Continue. A new user account can be created to grant Apple Remote Desktop administrator privileges. Creating a new user account does not overwrite existing user accounts or change existing user passwords. If you choose not to create a new user account, skip to step 10 after clicking Continue. 9 Add a new user by clicking Add and filling in the appropriate information. Click OK after adding each user, and click Continue when you’re ready to go on. 10 Choose whether to assign Apple Remote Desktop administrator access privileges to Directory Services groups. If you choose to do so, select “Enable directory-based administration.” See “Apple Remote Desktop Administrator Access Using Directory Services” on page 62 for more information on using this method to grant Apple Remote Desktop administrator access. 11 Choose whether to assign Apple Remote Desktop administrator access privileges to specific users. Click Continue. If you choose not to assign administrator access privileges, skip to step 14. 12 Click Add to designate a user to receive Apple Remote Desktop access privileges. 13 Provide the user’s short name and set the privileges as desired. See “Apple Remote Desktop Administrator Access” on page 59 for more information. Click OK after each user, and click Continue when you’re ready to go on. 14 Choose whether to allow temporary guest control by requesting permission on the client computers. See “Considerations for Managed Clients” on page 46 for more information. 15 Choose whether to allow non–Apple VNC viewers to control the client computers, and click Continue. See “Virtual Network Computing Access” on page 67 for more information. 16 If desired, select and enter information in any or all of the four System Data fields. This information appears in Apple Remote Desktop System Overview reports. For example, you can enter an inventory number for the computer, a serial number, or a user’s name and telephone number.46 Chapter 3 Installing Apple Remote Desktop 17 Click Continue. 18 Select a location for the installer. 19 Click Continue to create the installer. An installer metapackage (.mpkg file) is created in the designated location. 20 Click Done. Considerations for Managed Clients If you plan on restricting what applications can open on a managed client, you’ll need to make sure that Apple Remote Desktop’s processes are allowed to run. A managed client is a client computer whose environment is governed by Mac OS X Server’s Workgroup Manager. The following options need to be enabled in Workgroup Manager’s client and group application preference settings:  “Allow approved applications to launch non-approved applications”  “Allow UNIX tools to run” Removing or Disabling Apple Remote Desktop Apple Remote Desktop’s client components are bundled as part of Mac OS X and Mac OS X Server. You may choose to remove or disable parts of it to fit your own personal computing needs. The following section describes how to uninstall or disable key Apple Remote Desktop components. Uninstalling the Administrator Software To remove the administrator software completely, you must remove the application, the encrypted list of computer user names and passwords, and the client information database. To remove the administrator software: 1 Drag the Remote Desktop application to the Trash. 2 Empty the Trash. 3 Delete the Apple Remote Desktop database from /var/db/RemoteManagement/ using the following commands in the Terminal application: $ sudo rm -rf /var/db/RemoteManagement 4 Delete the Remote Desktop preferences files using the following commands in the Terminal application. $ sudo rm /Library/Preferences/com.apple.RemoteDesktop.plist $ sudo rm /Library/Preferences/com.apple.RemoteManagement.plist $ rm ~/Library/Preferences/com.apple.RemoteDesktop.plistChapter 3 Installing Apple Remote Desktop 47 5 Delete the Remote Desktop documentation using the following commands in the Terminal application. sudo rm -r /Library/Documentation/Applications/RemoteDesktop 6 Delete the Apple Remote Desktop support files from /Library/Application Support/ using the following commands in the Terminal application: $ rm -rf ~/Library/Application\ Support/Remote\ Desktop/ $ sudo rm -rf /Library/Application\ Support/Apple\ Remote\ Desktop/ 7 Delete the Apple Remote Desktop installation receipts from /Library/Receipts/ using the following commands in the Terminal application: $ rm -r /Library/Receipts/RemoteDesktopAdmin* $ rm -r /Library/Receipts/RemoteDesktopRMDB* 8 Delete the Apple Remote Desktop Dashboard Widget (after closing every instance of the Widget) using the following commands in the Terminal application: $ sudo rm -r /Library/Widgets/Remote\ Desktop/ Disabling the Client Software You may want to temporarily disable Apple Remote Desktop on a client without removing the software. To disable the client software on a client computer: 1 On the client computer, open System Preferences and click Sharing. If necessary, enter the user name and password of a user with administrator privileges on that computer. 2 Deselect Apple Remote Desktop in the Sharing pane. 3 Quit System Preferences. Apple Remote Desktop is now disabled and the underlying software is deactivated. Alternately, you can disable only the administrator privileges by doing the following: a Click Access Privileges. b Deselect each user account that you enabled for Apple Remote Desktop administration. c Click OK. d Quit System Preferences. Warning: Because Apple Remote Desktop is part of the default Mac OS X 10.3 and 10.4 installation, do not remove the Apple Remote Desktop client components.48 Chapter 3 Installing Apple Remote Desktop Uninstalling the Client Software from Client Computers To remove Apple Remote Desktop client software from Mac OS X clients, you need to remove a number of software components from each client system. To uninstall client software: 1 Open Terminal (located in /Applications/Utilities). 2 Delete the client pieces from /System/Library/ using the following commands in the Terminal application: $ sudo rm -rf /System/Library/CoreServices/Menu\ Extras/RemoteDesktop.menu $ sudo rm -rf /System/Library/CoreServices/RemoteManagement/ $ sudo rm -rf /System/Library/PreferencePanes/ARDPref.prefPane $ sudo rm -rf /System/Library/StartupItems/RemoteDesktopAgent/ 3 Delete the client preferences from /Library/Preferences/ using the following command in the Terminal application: $ sudo rm /Library/Preferences/com.apple.ARDAgent.plist $ sudo rm /Library/Preferences/com.apple.RemoteManagement.plist 4 Delete the client installation receipts from /Library/Receipts/ using the following command in the Terminal application: $ sudo rm -r /Library/Receipts/RemoteDesktopClient* $ sudo rm -rf /var/db/RemoteManagement/ Warning: It is not recommended that you uninstall the client software. Disabling the client software is sufficient to stop Apple Remote Desktop system activity. See “Disabling the Client Software” on page 47 for instructions.4 49 4 Organizing Client Computers Into Computer Lists Apple Remote Desktop uses lists of client computers to logically organize the client computers under your control. Connecting to client computers on the network and adding them to your list is necessary to administer them. This chapter describes finding clients and organizing them into lists for Apple Remote Desktop administration and user interaction. You can learn about:  “Finding and Adding Clients to Apple Remote Desktop Computer Lists” on page 49  “Making and Managing Lists” on page 53  “Importing and Exporting Computer Lists” on page 56 Finding and Adding Clients to Apple Remote Desktop Computer Lists Before you can audit, control, or maintain any client, you need to add it to an Apple Remote Desktop computer list. To find computers that aren’t on the local subnet, your local network’s routers and firewalls must be properly configured to pass network “pings,” and TCP/UDP packets on ports 3283 and 5900. Remote Desktop has four different methods for discovering possible clients: searching the local networks, searching a range of IP addresses, using a specific IP address or domain name, and importing a list of IP addresses. Once you have found a potential client, you see the following default information: Search column Description (none) Displays a small icon indicating whether the computer is already in the Master List. (none) Displays a small icon showing what kind of access the client is capable of. See “Client Status Icons” on page 161. Name The name given to the computer in the Sharing pane of System Preferences. IP Address The computer’s IP address, if any.50 Chapter 4 Organizing Client Computers Into Computer Lists If you want to change the default display list for the scanner, you can select Edit > View Options and choose any of the other available options (which include Computer Info Fields, Ethernet ID, Label, or others). To add a computer to a computer list, you first authenticate to the computer. Authenticated computers are found in the All Computers list in the Remote Desktop window. You can add a computer to the All Computers list without authenticating, but you will be unable to administer the client until you provide a valid user name and password. Finding Clients by Searching the Local Network When you select a local network scanner, Remote Desktop sends a subnet broadcast to computers in the same subnets as the administrator computer. All possible clients on the local subnets appear in a list on the right side of the Remote Desktop window. To search for clients on the local network: 1 Select a scanner at the left of the Remote Desktop window. 2 Select Local Network. All responding clients are listed in the Remote Desktop window. 3 Select the desired computers. 4 Drag the selected computers to the All Computers list. 5 Authenticate by providing a user name and password for an Apple Remote Desktop administrator. The computer is now in your All Computers list. Finding Clients by Searching a Network Range To locate computers by network range, you provide a beginning and ending IP address to scan, and Apple Remote Desktop queries each IP address in that range in sequence, asking if the computer is a client computer. This method works best when searching for clients outside the local subnet, but on the local area network. Alternatively, you can use a text file that contains IP address ranges (in this format “192.168.0.1-192.168.3.20”), and use text file import to find clients. See “Finding Clients by File Import” on page 52. DNS Name The computer’s DNS name, found by reverse lookup, if any. ARD Version Apple Remote Desktop client software version. Network Interface Which interface the client responded through. Search column DescriptionChapter 4 Organizing Client Computers Into Computer Lists 51 To search a range of network addresses: 1 Select a scanner at the left of the Remote Desktop window. 2 Select Network Range. 3 Enter the beginning and ending IP address. 4 Click the Refresh button. All responding clients are listed in the Remote Desktop window. 5 Select the desired computers. 6 Drag the selected computers to the All Computers list. 7 Authenticate by providing a user name and password for an Apple Remote Desktop administrator. The computer is now in your All Computers list. Finding Clients by Network Address If you know the exact IP address or fully qualified domain name of a computer, you can use that IP address or domain name to add the computer to your All Computers list. To add a specific address immediately to the All Computers list: 1 Choose File > Add By Address. 2 Enter the IP address or fully qualified domain name. 3 Enter the user name and password. 4 Choose whether to verify the name and password before adding it to the All Computers list. 5 Click Add. Alternatively you use the scanner to try an address or domain name and check availability before attempting to add it to the All Computers list. To search for a specific address: 1 Select a scanner at the left of the Remote Desktop window. 2 Select Network Address. 3 Enter the IP address or fully qualified domain name in the Address field. 4 Click the Refresh button. If the client responds successfully, it is listed in the Remote Desktop window. 5 Select the desired computers. 6 Drag the selected computers to the All Computers list. 7 Authenticate by providing a user name and password for an Apple Remote Desktop administrator. The computer is now in your All Computers list.52 Chapter 4 Organizing Client Computers Into Computer Lists Finding Clients by File Import You can import a list of computers into Apple Remote Desktop by importing a file listing the computers’ IP addresses. The list can be in any file format (text, spreadsheet, word processor) and must contain either IP addresses or fully qualified domain names (such as foo.example.com). File import also allows you to add ranges of IP addresses by expressing the range in the following format: xxx.xxx.xxx.xxx-yyy.yyy.yyy.yyy. For example, a text file with the line “192.168.0.2-192.168.2.200” would add all IP addresses in that address range. To import a list of computers from a file: 1 Select a scanner at the left of the Remote Desktop window. 2 Select File Import. 3 Browse for the file by clicking the Open File button, or drag a file into the window. Alternatively, you can enter the file’s pathname in the File field. All responding clients are listed in the Remote Desktop window. 4 Select the desired computers. 5 Drag the selected computers to the All Computers list. 6 Authenticate by providing a user name and password for an Apple Remote Desktop administrator. The computer is now in your All Computers list. Making a New Scanner You may want several scanners in order to search for specific address ranges or to do other types of searches. You can make and save your own scanner so you can quickly do the search at any time. You can rename scanners to make them easy to identify. To make a custom search list: 1 Choose File > New Scanner. 2 Rename the newly created scanner. 3 Select the scanner icon. 4 Choose a search type from the pop-up menu to the right.Chapter 4 Organizing Client Computers Into Computer Lists 53 5 Customize the search by entering the specific parameters for the search (such as an IP address range, or file location). You can find out how to customize the search in the following sections:  “Finding Clients by Searching the Local Network” on page 50  “Finding Clients by Searching a Network Range” on page 50  “Finding Clients by Network Address” on page 51  “Finding Clients by File Import” on page 52 6 Click the Refresh button. All responding clients are listed in the Remote Desktop window. Select your scanner icon and click the Refresh button whenever you want to run the search. Making and Managing Lists You use lists to organize and perform management tasks on client computers. You can make groups of lists, and rearrange the lists by dragging them up and down the left side of the main window. Apple Remote Desktop has several different kinds of lists. The following section describes the kinds of lists, and explains how to create lists and use them for client management. About Apple Remote Desktop Computer Lists Apple Remote Desktop displays computers in lists in the main section of the Remote Desktop window. The default computer list is called the All Computers list. This is a full list of all possible clients that you have located and authenticated to. You can create other lists to group the computers on your network in any way you wish. Computer lists have the following capabilities:  You can create as many lists as you want.  The All Computers list can have up to the number of computers your license allows.  Computers can appear in more than one list.  Lists can be made in any grouping you can imagine: geographic, functional, hardware configuration, even color.  Click a list name and keep the mouse over the list name, you can edit the list name.  If you double-click the list icon, you open another window containing the computers in the list.54 Chapter 4 Organizing Client Computers Into Computer Lists Creating an Apple Remote Desktop Computer List You can make more specific, targeted lists of computers from your All Computers list. The easiest way to make a new list is to use computers already in the All Computers list. You can also create blank lists and add computers to them later. To create an Apple Remote Desktop computer list: 1 Select the All Computers list icon in the main Remote Desktop window. 2 Select the computers you want to add to the new list. 3 Choose File > New List From Selection. 4 Name the computer list. Alternatively, you can choose File > New List to create a blank list and drag computers from the All Computers list, or from the scanner search results, to the blank list. Deleting Apple Remote Desktop Lists You can delete Apple Remote Desktop computer lists and scanner lists that you created. You cannot delete the All Computers list, Task Server list, or Task History list. To delete a list: m Select the list and press the Delete key. Creating a Smart Computer List You can create a computer list which automatically populates based on custom criteria. Once you create a smart list, any computer added to the All Computers list (or other specified list) which matches the criteria will automatically be added to the smart list. You can match any or all of the following criteria:  Name  IP Address  DNS Name  Label  Apple Remote Desktop version  Startup Volume  Installed RAM  CPU Information  Machine Model  Mac OS version  Computer is in List In order to use a smart list which populates from any list except the All Computers list, you need to add the “Computer is in List” criterion and specify the source list.Chapter 4 Organizing Client Computers Into Computer Lists 55 To create a smart computer list: 1 Choose File > New Smart List. 2 Name the smart computer list. 3 Choose “any” or “all” criteria to match. 4 Select the attribute to select by, using the pop-up windows and text entry field. 5 Add any other criteria with the Add (+) button. 6 Click OK. The new smart list appears in Remote Desktop’s main window. Editing a Smart Computer List You may want to edit the smart lists you have created. The editing window is the same as the one used to create the smart list. The options available are the same as those listed in “Creating a Smart Computer List” on page 54. To edit a smart computer list: 1 Select the smart list in Remote Desktop’s main window. 2 Choose File > Edit Smart List. 3 Change the smart computer list as desired. Creating a List of Computers of from Existing Computer Lists You may want a list which combines the results of several different lists and smart lists. You can create aggregate lists by using the “Computer is in List” option. The list created will have the computers from the source lists, but not indicate which source list they came from. To create an list of computer lists: 1 Create the lists which will serve as the sources of the smart list. See “Creating an Apple Remote Desktop Computer List” on page 54 or “Creating a Smart Computer List” on page 54 for more information. 2 Create the Smart List which will draw its computers from the previously created lists. “Creating a Smart Computer List” on page 54 for more information. 3 In the Smart List creation dialog, choose to match all of the stated conditions. 4 For the first condition, select “Computer is in List.” 5 Select a source list from the pop-up menu. 6 Add another condition by clicking the Add (+) button. 7 Repeat steps 4-6, adding Computer Lists for all of the source lists.56 Chapter 4 Organizing Client Computers Into Computer Lists 8 Add other conditions and criteria as desired. 9 Create the final Smart List by clicking OK. The new Smart List appears in Remote Desktop’s main window. Importing and Exporting Computer Lists When setting up Apple Remote Desktop 3, you may not necessarily use the same computer you used for the previous version of Apple Remote Desktop. Rather than create new lists of client computers, you can transfer existing lists between computers, with benefits and limitations depending on the transfer circumstance. The following sections will help you import or export your computer lists.  “Transferring Computer Lists from Apple Remote Desktop 3 to a New Administrator Computer” on page 56  “Transferring Remote Desktop 2 Computer Lists to a New Remote Desktop 3 Administrator Computer” on page 57  “Transferring Old v1.2 Computer Lists to a New Administrator Computer” on page 57 Transferring Computer Lists from Apple Remote Desktop 3 to a New Administrator Computer You may want to move your existing computer lists to the new administrator computer running Apple Remote Desktop 3. Lists transferred in this way retain their client computers as well as the original name of the list. You can only use these instructions to move computer lists between administrator computers which run Apple Remote Desktop 3. When you import or export a computer list, the user name and password used for Apple Remote Desktop authentication are not exported. Once you’ve imported the computer list, you will still need to authenticate to the computers. To transfer the computer lists: 1 In the main Remote Desktop window, select the list you want to move. 2 Choose File > Export List. 3 Select a name and a file location for the exported list. The default file name is the list name. Changing the file name, however, does not change the list name. 4 Click Save. A .plist file is created in the desired location. The XML-formatted .plist file is a plain text file that can be inspected with Apple’s Property List Editor or a text editor. 5 Copy the exported file to the desired administrator computer. 6 On the new administrator computer, launch Remote Desktop. 7 Choose File > Import List.Chapter 4 Organizing Client Computers Into Computer Lists 57 8 Select the exported list, and click Open. The list now appears in Remote Desktop’s main window. Transferring Remote Desktop 2 Computer Lists to a New Remote Desktop 3 Administrator Computer If you are installing Apple Remote Desktop 3 on a computer different from the version 2.x administrator computer, you may want to move your existing computer lists to the new administrator computer running Apple Remote Desktop 3. When you import or export a computer list, the user name and password used for Apple Remote Desktop authentication are not exported. Once you’ve imported the computer list, you will still need to authenticate to the computers. To transfer the computer lists: 1 In the main Remote Desktop window, select the list you want to move. 2 Make sure Remote Desktop lists the computer’s name and IP address. 3 Choose File > Export Window. 4 Select a name and a file location for the exported list, and click Save. The default file name is the window’s title. 5 Copy the exported file to the desired administrator computer. 6 On the new administrator computer, launch Remote Desktop. 7 Using the Scanner, add the clients by File Import. See “Finding Clients by File Import” on page 52, for detailed instructions. The list now appears in Remote Desktop’s main window. 8 Select the computers in the list. 9 Choose File > New List From Selection. The new list now appears in Remote Desktop’s main window. Transferring Old v1.2 Computer Lists to a New Administrator Computer If you are installing Apple Remote Desktop 3 on a computer other than an older administrator computer using Apple Remote Desktop 1.2, you need to move your existing computer lists to the new administrator computer before installing version 3. These instructions only apply when moving Apple Remote Desktop 1.2 computer lists to a new computer. Throughout these instructions, the computer with the original lists is the “source computer.” The computer that will have Apple Remote Desktop 3 installed is the “target computer.”58 Chapter 4 Organizing Client Computers Into Computer Lists To transfer the computer lists: 1 Open Keychain Access (located in /Applications/Utilities) on the source computer. 2 Choose File > New Keychain. 3 Name the new keychain, and click Create. 4 Enter a password for the new keychain. This is a temporary password that you will use to retrieve the information in the keychain. Do not use your login password or other sensitive password. 5 If necessary, click Show Keychains to show the administrator keychain. 6 Select the source computer’s main keychain. If the keychain is locked, unlock it and authenticate. 7 Select only the Apple Remote Desktop entries in the keychain. 8 Drag the Apple Remote Desktop entries to the newly created keychain. 9 Provide the source computer keychain password for each entry. 10 Quit Keychain Access on the source computer. 11 Copy the newly created keychain from the source computer (~/Library/Keychains/ ) to the same location on the target computer. You can copy the keychain over the network, or use a removable storage drive. 12 On the target computer, open Keychain Access in the Finder. 13 Choose File > Add Keychain. 14 Select the keychain that was copied from the source computer, and click Open. 15 If necessary, click Show Keychains to show the keychains. 16 Unlock the newly imported keychain, using the password designated for that keychain. 17 Select the Apple Remote Desktop entries. 18 Drag the Apple Remote Desktop entries to the main keychain on the target computer. Provide the temporary keychain password for each entry. 19 Quit Keychain Access on the source computer. When you open Apple Remote Desktop on the new computer, you will notice that the computer lists from the old computer are available.5 59 5 Understanding and Controlling Access Privileges There are several different ways to access and authenticate to Apple Remote Desktop clients. Some depend on Apple Remote Desktop settings, and others depend on other client settings, or third-party administration tools. This chapter explains the various access types, their configuration, and their uses. You can learn about:  “Apple Remote Desktop Administrator Access” on page 59  “Apple Remote Desktop Administrator Access Using Directory Services” on page 62  “Apple Remote Desktop Guest Access” on page 65  “Apple Remote Desktop Nonadministrator Access” on page 66  “Virtual Network Computing Access” on page 67  “Command-Line SSH Access” on page 68  “Managing Client Administration Settings and Privileges” on page 68 Apple Remote Desktop Administrator Access Access privileges allow an Apple Remote Desktop administrator to add computers to a list and then interact with them. If no access privileges are allowed on a client computer, that computer cannot be used with Apple Remote Desktop. Access privileges are defined in the Apple Remote Desktop section of the Sharing pane of the client computers’ System Preferences. The recommended access privileges for a client computer depend on how it’s used.  If the computer is used in a public area, such as a computer lab, you may want to allow administrators full access privileges.  If the computer is used by one person, you may not want to give administrators full access privileges. Also, you may want a user who administers his or her own computer to take responsibility for creating passwords and setting the access privileges for the computer60 Chapter 5 Understanding and Controlling Access Privileges The following table shows the settings in the Apple Remote Desktop settings in the Sharing Preference pane and the features of Remote Desktop that they correspond to. For example, if you want a certain administrator to be rename computer file sharing names, you will need to grant that user that privilege by selecting “Change Settings”. checkbox in the Apple Remote Desktop settings in the Sharing Preference pane on the client computer. Select To allow administrators to Select any other privileges. (If you select only this box, the administrator can see the client computer in the Computer Status window and include it in Network Test reports.) Generate reports Create hardware and software reports using the Report menu; use Set Reporting Policy and Spotlight Search. Open and quit applications Use these Manage menu commands: Open Application, Open Items, Send UNIX Command and Log Out Current User. Change settings Use these Manage menu commands: Rename Computer, Send UNIX Command and Set Startup Disk. Delete and replace items Use these Manage menu commands: Copy Items, Install Packages, Send UNIX Command and Empty Trash. Also delete items from report windows. This item must be enabled in order to use the Upgrade Client Software feature. Send text messages Use these Interact menu commands: Send Message and Chat. Restart and shut down Use these Manage menu commands: Sleep, Wake Up, Restart, Send UNIX Command, and Shut Down. This item must be enabled in order to use the Upgrade Client Software feature. Copy items Use these Manage menu and Server menu commands: Copy Items, Send UNIX Command and Install Packages. This item must be enabled in order to use the Upgrade Client Software and Change Client Settings features. Control Use these Interact menu commands: Control, Share Screen, Lock and Unlock Screen. This item must be enabled in order to use the Upgrade Client Software and Change Client Settings features.Chapter 5 Understanding and Controlling Access Privileges 61 Setting Apple Remote Desktop Administrator Access Authorization and Privileges Using Local Accounts To prepare a client for administration, you activate the existing version of Apple Remote Desktop on the client computer and set Apple Remote Desktop administrator access privileges by using the Sharing pane of the computer’s System Preferences. You set access privileges separately for each user account on the computer. Follow the steps in this section to set access privileges on each client computer. Note: You can skip this step if you create a custom installer that automatically enables your desired client settings. To make changes on a client computer, you must have the name and password of a user with administrator privileges on the computer. To set administrator privileges on a computer: 1 On the client computer, open System Preferences and click Sharing. If the preference pane is locked, click the lock and then enter the user name and password of a user with administrator privileges on that computer. 2 Select Apple Remote Desktop in the Sharing service pane. 3 Click Access Privileges. 4 Select each user that you want enabled for Apple Remote Desktop administration authentication. 5 Select a listed user whose access privileges you want to set, and then make the changes you want to the access privileges. Your changes take effect immediately. Hint: Holding down the Option key while clicking the user’s checkbox will automatically select all the following checkboxes for access. See “Apple Remote Desktop Administrator Access” on page 59 for more information. 6 Repeat for additional users whose access privileges you want to set. 7 If desired, enter information in any or all of the four Computer Information fields. This information appears in Apple Remote Desktop System Overview reports and optionally in the computer list views. For example, you can enter an inventory number for the computer, a serial number, or a user’s name and telephone number. 8 Click OK. 9 To activate the Apple Remote Desktop client, make sure to select the Apple Remote Desktop checkbox, or select Apple Remote Desktop and click Start.62 Chapter 5 Understanding and Controlling Access Privileges Apple Remote Desktop Administrator Access Using Directory Services You can also grant Apple Remote Desktop administrator access without enabling any local users at all by enabling group-based authorization if the client computers are bound to a directory service. When you use specially named groups from your Directory Services master domain, you don’t have to add users and passwords to the client computers for Apple Remote Desktop access and privileges. When Directory Services authorization is enabled on a client, the user name and password you supply when you authenticate to the computer are checked in the directory. If the name belongs to one of the Apple Remote Desktop access groups, you are granted the access privileges assigned to the group. Creating Administrator Access Groups In order to use Directory Services authorization to determine access privileges, you need to create groups and assign them privileges. There are two ways of doing this: Method #1 You can create groups and assign them privileges through the mcx_setting attribute on any of the following records: any computer record, any computer list record, or the guest computer record. To create an administrator access group: 1 Create groups as usual. If you are using Mac OS X Server, you use Workgroup Manager to make them. 2 After you have created groups, you edit either the computer record of the computer to be administered, its computer list record, or the guest computer record. 3 Use a text editor, or the Apple Developer tool named Property List Editor to build the mcx_setting attribute XML. The XML contains some administrator privilege key designations (ard_admin, ard_reports, etc.), and the groups that you want to possess those privileges. The following privilege keys have these corresponding Remote Desktop management privileges:Chapter 5 Understanding and Controlling Access Privileges 63 In the XML, you name a privilege key and make the value the name of the group or groups you want to possess the privilege. Use the sample XML below to make your management/key designation XML. 4 When you have created the snippet of XML, you enter this whole snippet into a computer record or computer list record. If you are using Workgroup Manager, you enable the preference to “Show All Records Tab and Inspector” and use the Inspector to copy the entire snippet of XML the value which corresponds to the “MCXSettings” attribute name. Management Privilege ard_admin ard_reports ard_manage ard_interact Generate reports X X X Open and quit applications X X Change settings X X Copy items X X Delete and replace items X X Send messages X X X Restart and shut down X X Control X X Observe X X Show being observed X X64 Chapter 5 Understanding and Controlling Access Privileges For more information on using Workgroup Manager, and Open Directory, see their documentation at: www.apple.com/server/documentation The following is the sample XML format you need to use to assign management privileges via MCX keys. It assigns the above “ard_interact” privileges to the groups named “some_group” and “staff.” It also assigns the “ard_manage” privileges to the group named “staff,” the “ard_admin” privileges to the group “my_admin_group,” and leaves no group with the “ard_reports” privilege set. Here’s the XML: mcx_application_data com.apple.remotedesktop Forced mcx_preference_settings ard_interact some_group staff ard_manage staff ard_admin my_admin_group ard_reports This example attribute defines four privileges, although any of them may be left out.Chapter 5 Understanding and Controlling Access Privileges 65 Method #2 You can create groups with special names that correspond to the privilege keys above: ard_admin, ard_reports, ard_manage, and ard_interact. The corresponding privileges are automatically assigned to these specially named groups. If you have already created these groups for use with Apple Remote Desktop 2, they will continue to work as expected with Apple Remote Desktop 3. Enabling Directory Services Group Authorization In order to enable group-based authorization for Apple Remote Desktop access, you create the appropriate groups in your Directory Services master directory domain. To complete this task, you need to be the Directory Services administrator and have access to your organization’s users and groups server. To enable Apple Remote Desktop authorization by group: 1 Use one of the methods in the section “Creating Administrator Access Groups” to create groups with Apple Remote Desktop access privileges assigned to them. 2 Add users to the groups. 3 Make sure the client computers to be administered are bound to your directory system. 4 Set the clients to use directory authorization by using the Change Client Settings feature or make a custom installer. 5 Choose to enable directory-based administration on the clients using Directory Access found in /Applications/Utilities/. Apple Remote Desktop Guest Access You can configure an Apple Remote Desktop client to give temporary, one-time access to an Apple Remote Desktop administrator who does not have a user name or password for the client computer. Each time the Apple Remote Desktop administrator would like to control the client computer, he or she must request permission from the remote client’s user. Warning: Granting access to control a screen is the most powerful feature in Apple Remote Desktop, and can be equivalent to unrestricted access.66 Chapter 5 Understanding and Controlling Access Privileges To allow guest access: 1 On the client computer, open System Preferences and click Sharing. If prompted, enter the user name and password of a user with administrator privileges on that computer. 2 Select Apple Remote Desktop in the Sharing pane. 3 Click Access Privileges. 4 Select “Guests may request permission to control screen.” 5 Click OK. Apple Remote Desktop Nonadministrator Access Remote Desktop can operate in what is referred to as “user mode.” User mode is activated when a nonadministrator user opens Remote Desktop to administer Apple Remote Desktop client computers. The administrator of the computer with Remote Desktop installed can choose which features and tasks are available to nonadministrator users. Limiting Features in the Administrator Application User mode is a great way to delegate administrative tasks, or give users only the features of Remote Desktop that they really use. For example, you might not allow nonadministrators to copy or delete files, but you may want them to be able to observe client screens and send messages to client users. You can choose to allow nonadministrators to:  Observe, control, and share screens  Lock and unlock screens  Send text messages and chat  Sleep and wake client computers  Log out users  Restart and shut down computers  Open or quit files and applications  Rename computers  Generate reports and software searches  Copy items, delete items, and empty the Trash  Create Apple Remote Desktop custom client installers  Upgrade clients and change client settings  Install packages  Set the client computer’s startup volume  Set the client’s data reporting policy  Send UNIX commandsChapter 5 Understanding and Controlling Access Privileges 67 Each of these features can be enabled or disabled independently of each other, or you can enable all of Remote Desktop’s features for nonadministrator users. To enable User Mode: 1 Make sure you are logged in as an administrator user. 2 Open Remote Desktop. 3 Choose Remote Desktop > Preferences. 4 Click the Security button. 5 Enable or disable features, as desired. 6 Close the Preference’s window. Virtual Network Computing Access You can use Apple Remote Desktop to access a Virtual Network Computing (VNC) server and view and interact with the server’s screen. VNC access is determined by the VNC server software. To access a VNC server, it is only necessary to know the IP address or fully qualified domain name and the password designated in the VNC server software. This password does not necessarily correspond to any other password on the system, and is determined by the VNC configuration. VNC access is similar to Apple Remote Desktop’s Control command. It allows you to use your keyboard and mouse to control a VNC server across a network. It doesn’t give any other Apple Remote Desktop administrator privileges except those of the currently logged-in user. Non-Apple VNC viewers can control Apple Remote Desktop clients if the client allows it. Allowing a non-Apple VNC viewer access to an Apple Remote Desktop client is less secure than using Apple Remote Desktop to control the client. The VNC protocol implemented in third-party VNC viewers may not encrypt keystrokes sent over the network, so sensitive information can be intercepted. Warning: Granting VNC access to control a screen is the most powerful feature in Apple Remote Desktop, and can be equivalent to unrestricted access.68 Chapter 5 Understanding and Controlling Access Privileges To allow VNC access: 1 On the client computer, open System Preferences and click Sharing. If prompted, enter the user name and password of a user with administrator privileges on that computer. 2 Select Apple Remote Desktop in the Sharing pane. 3 Click Access Privileges. 4 Select “VNC viewers may control screen with password.” 5 Enter a VNC password. Command-Line SSH Access Command-line SSH access is not granted or managed using Remote Desktop. This type of access is managed in the Sharing pane of System Preferences (called “Remote Login”) and is separate from Apple Remote Desktop access types. When you log in to a client remotely using SSH, you have the user privileges assigned to the user name and password. These may or may not include computer administrator privileges. You can use SSH to access a client using a user account created for Apple Remote Desktop, but you are limited to performing whatever tasks were allowed to that user when the account was created. Conversely, only the users specified in the Apple Remote Desktop access privileges can access a computer using Apple Remote Desktop. Apple Remote Desktop privileges are completely separate and distinct from local computer administrator UNIX privileges. Managing Client Administration Settings and Privileges Regular audits of administration settings can help maintain a secure Remote Desktop administration environment. Using the various administrator options given with Apple Remote Desktop administrator privileges, you can create specialized logins for certain tasks, limiting potentially disruptive power of certain sub-administrators. The following section gives detailed instructions for checking the administrator privilege settings of client computers, and changing those settings. Warning: Do not use the same password as any local user or Apple Remote Desktop login.Chapter 5 Understanding and Controlling Access Privileges 69 Getting an Administration Settings Report You can query active Apple Remote Desktop clients for a report on what commands they are accepting from your administrator authentication. The report is a list of the Apple Remote Desktop administrator access types each with an “On” or “Off” to indicate whether that access type is available to you. To get an administration settings report: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Report > Administration Settings. 4 Click Get Report. Changing Client Administrator Privileges Once the client computers are able to be administered, you can change the administrator access privileges for multiple computers simultaneously, using the Change Client Settings command. If you are using Directory Services to designate administrator privileges, you don’t need to change the settings on the clients. To make changes on a client, you must have the name and password of a user with administrator privileges on the computer. Additionally, you must already have the Control privilege. Note: You do not have to make a selection on every page of the assistant. You can click Continue to move to the next set of settings. To change administrator privileges on each computer: 1 Select a computer list. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Change Client Settings. The client assistant appears. Click Continue. 4 Choose whether to start Remote Desktop sharing at system startup. This changes the setting found in the Sharing pane of System Preferences. 5 Choose whether to hide or show the Apple Remote Desktop menu bar icon. 6 Click Continue. 7 Choose whether to create a new user for Apple Remote Desktop login. Click Continue. New users can be used to grant Apple Remote Desktop administrator privileges. Creating a new user does not overwrite existing users or change existing user passwords. If you choose not to create a new user, skip to step 9 after clicking Continue.70 Chapter 5 Understanding and Controlling Access Privileges 8 Add a new user by clicking Add and filling in the appropriate information. Click OK after adding each user, and click Continue when you’re ready to go on. 9 Choose whether to assign Apple Remote Desktop administrator access privileges to Directory Services groups. If you choose to do so, select “Enable directory-based administration.” See “Apple Remote Desktop Administrator Access Using Directory Services” on page 62 for more information on using this method to grant Apple Remote Desktop administrator access. 10 Choose whether to assign Apple Remote Desktop administrator access privileges to specific users. Click Continue. If you choose not to assign administrator access privileges, skip to step 13. 11 Click Add to designate a user to receive Apple Remote Desktop access privileges. 12 Provide the user’s short name and assign the privileges as desired. See “Apple Remote Desktop Administrator Access” on page 59 for more information. Click OK after each user, and click Continue when you’re ready to go on. 13 Choose whether to allow temporary guest control by requesting permission on the client computers. 14 Choose whether to allow non-Apple VNC viewers to control the client computers, and click Continue. See “Virtual Network Computing Access” on page 67 for more information. 15 If desired, select and enter information in any or all of the four System Data fields. This information appears in Apple Remote Desktop System Overview reports. For example, you can enter an inventory number for the computer, a serial number, or a user’s name and telephone number. 16 Click Continue to review the clients’ settings. 17 Choose whether to execute the change using the application or a dedicated task server. 18 Click Change to change the clients’ settings The client configuration assistant contacts all of the selected computers and changes their administration settings.6 71 6 Setting Up the Network and Maintaining Security This chapter describes the main aspects of setting up your network for use with Apple Remote Desktop system administration, as well as best-practice tips for your network. Additionally, it contains information about Apple Remote Desktop security features, and detailed instructions for enabling them. You can learn about:  “Setting Up the Network” on page 71  “Using Apple Remote Desktop with Computers in an AirPort Wireless Network” on page 72  “Getting the Best Performance” on page 73  “Maintaining Security” on page 73 Setting Up the Network Your network configuration determines Apple Remote Desktop’s performance and usability. AirPort and AirPort Extreme networks offer slower performance than almost any Ethernet network. Therefore, file copying, client monitoring, and reporting are slower over AirPort and AirPort Extreme connections. Network routers and firewalls also shape, direct, or block network traffic; these things can have an effect on Apple Remote Desktop’s reliability and efficiency. Here are a few guidelines to keep in mind when setting up Apple Remote Desktop on your network:  The more AirPort clients connected to a base station, the lower the bandwidth for each computer. AirPort Base Stations are not considered “switched networks.”  Local Hostname (name using Apple’s Bonjour technology, that looks like: name.local) browsing does not extend beyond the local subnet. Local Hostnames do not resolve across routers like domain names do.  Networks with switches have fewer collisions and packet errors than networks with hubs. This means greater reliability and speed. Consider using switches instead of hubs.72 Chapter 6 Setting Up the Network and Maintaining Security  Organize computers you’re administering using Apple Remote Desktop into small groups, and close the Remote Desktop administrator application when not in use. This helps reduce the number of status queries, thus reducing network traffic.  If a client has a slow network type, consider running it in a list separate from the faster clients. A single slow client can slow down network operations.  If network traffic passes through firewalls, make sure you have a large Maximum Transmission Unit (MTU) setting (1200 or greater). Too small an MTU setting can result in black screens when sharing or sending screens.  If you are using a wide-area network (WAN), or metropolitan area network (MAN), make sure that the defrag bit is turned off in your router so packets don’t get chunked up. This can result in black screens when sharing or sending screens.  Network Address Translation (NAT) networks (such as those that use the Mac OS X Internet Sharing feature) can pose configuration and access difficulties. If you want to use Remote Desktop from behind a NAT router to access computers beyond the NAT router, you need to set TCP and UDP port forwarding for ports 3283 and 5900 to your administrator computer. Similarly, if you wish to access a single client computer that is behind a NAT router, you need to set the router to forward TCP and UDP ports 3283 and 5900 to the client computer you wish to access. Using Apple Remote Desktop with Computers in an AirPort Wireless Network Using Apple Remote Desktop to observe or control client computers connected using AirPort wireless technology can sometimes result in impaired performance or cause communication errors to appear in the Computer Status window. To get the best performance from Apple Remote Desktop with computers in an AirPort wireless network:  Make sure that all AirPort Base Stations and all Apple Remote Desktop client computers have the latest versions of Apple Remote Desktop software, AirPort software, and Mac OS X software installed.  Limit the number of clients that connect to an AirPort Base Station. AirPort clients on a base station receive all network communication packets sent to any one client on that base station. Although clients ignore packets that aren’t addressed to them, CPU resources are used to identify and discard the packet.  Scale the Control and Observe window. Apple Remote Desktop has server-side scaling that will allow for less traffic across the network as you scale the window to smaller sizes.  Try not to use tasks that multicast traffic such as Share Screen and File Copy. File Copy tries to initiate a series of individual copies if there is a significant number of multicast networking errors.Chapter 6 Setting Up the Network and Maintaining Security 73  Wireless networks also are not suited for multicast traffic. However Apple Remote Desktop’s multi-observe feature is different because it doesn’t use multicast traffic.  Display shared screens in black and white rather than in color.  Configure your AirPort Base Station with a station density of High and increase the multicast rate to 11 Mbps using AirPort Admin Utility. Using the base station density and multicast rate settings limits the range of each AirPort Base Station’s network, requiring client computers to be fewer than 50 meters from a base station. Getting the Best Performance To get the best performance when using the Share Screen, Observe, and Control commands:  Use the fastest network possible. This means favoring Ethernet over AirPort, 1000Base-T over 100Base-T, and 100Base-T over 10Base-T.  If you’re using AirPort, adjust the multicast speed higher.  Don’t mix network speeds if possible.  Reduce the use of animation on remote computers. For example, you can simplify Dock preference settings by turning off animation, automatic hiding and showing, and magnification effects.  View the client’s screen in a smaller window when using the “fit to window” option.  View the client’s screen with fewer colors.  Use a solid color for the desktop of the screen you’re sharing.  Share screens only on local networks. If you share a screen with a computer connected across a router, screen updates happen more slowly.  Set the Control and Observe image quality to the lowest acceptable for the given circumstance. Maintaining Security Remote Desktop can be a powerful tool for teaching, demonstrating, and performing maintenance tasks. For convenience, the administrator name and password used to access Remote Desktop can be stored in a keychain or can be required to be typed each time you open the application. However, the administrator name and password for each client computer are stored in the administrator’s preferences and are strongly encrypted.74 Chapter 6 Setting Up the Network and Maintaining Security Administrator Application Security  Make use of user mode to limit what nonadministrator users can do with Remote Desktop. See “Apple Remote Desktop Nonadministrator Access” on page 66.  If you leave the Remote Desktop password in your keychain, be sure to lock your keychain when you are not at your administrator computer.  Consider limiting user accounts to prevent the use of Remote Desktop. Either in a Managed Client for Mac OS X (MCX) environment, or using the Accounts pane in System Preferences, you can make sure only the users you designate can use Remote Desktop.  Check to see if the administrator computer is currently being observed or controlled before launching Remote Desktop (and stop it if it is). Remote Desktop prevents users from controlling a client with a copy of Remote Desktop already running on it at connection time, but does not disconnect existing observe or control sessions to the administrator computer when being launched. Although this functionality is helpful if you want to interact with a remote LAN which is behind a NAT gateway, it is possible to exploit this feature to get secretly get information about the administrator, administrator’s computer, and its associated client computers. User Privileges and Permissions Security  To disable or limit an administrator’s access to an Apple Remote Desktop client, open System Preferences on the client computer and make changes to settings in the Remote Desktop pane in the Sharing pane of System Preferences. The changes take effect after the current Apple Remote Desktop session with the client computer ends.  Remember that Apple Remote Desktop keeps working on client computers as long as the session remains open, even if the password used to administer the computer is changed.  Don’t use a user name for an Apple Remote Desktop access name and password. Make “dummy” accounts specifically for Apple Remote Desktop password access and limit their GUI and remote login privileges. Password Access Security  Never give the Remote Desktop password to anyone.  Never give the administrator name or password to anyone.  Use cryptographically sound passwords (no words found in a dictionary; eight characters or more, including letters, numbers and punctuation with no repeating patterns).  Regularly test your password files against dictionary attack to find weak passwords.Chapter 6 Setting Up the Network and Maintaining Security 75  Quit the Remote Desktop application when you have finished using it. If you have not stored the Remote Desktop password in your keychain, the application prompts you to enter the administrator name and password when you open it again. Physical Access Security  If you have stored the Remote Desktop password in your keychain, make sure the keychain is secured and the application isn’t running while you are away from the Remote Desktop window.  If you want to leave the Remote Desktop application open but need to be away from the computer, use a password-protected screen saver and select a hot corner so you can instantly activate the screen saver. Remote Desktop Authentication and Data Transport Encryption Authentication to Apple Remote Desktop clients uses an authentication method based on a Diffie-Hellman Key agreement protocol that creates a shared 128-bit key. This shared key is used to encrypt both the name and password using the Advanced Encryption Standard (AES). The Diffie-Hellman key agreement protocol used in Remote Desktop 3 is very similar to the one used in personal file sharing, with both of them using a 512-bit prime for the shared key calculation. With Remote Desktop 3, keystrokes and mouse events are encrypted when you control Mac OS X client computers. Additionally, all tasks except Control and Observe screen data, and files copied via Copy Items and Install Packages are encrypted for transit (though you may choose to encrypt these as well by changing your application preferences). This information is encrypted using the Advanced Encryption Standard (AES) with the 128-bit shared key that was derived during authentication. Encrypting Observe and Control Network Data Although Remote Desktop sends authentication information, keystrokes, and management commands encrypted by default, you may want additional security. You can choose to encrypt all Observe and Control traffic, at a certain performance cost. Encryption is done using an SSH tunnel between the participating computers. In order to use encryption for Observe and Control tasks, the target computers must have SSH enabled (“Remote Login” in the computer’s Sharing Preference pane). Additionally, firewalls between the participating computers must be configured to pass traffic on TCP port 22 (SSH well known port). If the you are trying to control a VNC server which is not Remote Desktop, it will not support Remote Desktop keystroke encryption. If you try to control that VNC server, you will get a warning that the keystrokes aren’t encrypted which you will have to acknowledge before you can control the VNC server. If you chose to encrypt all network data, then you will not be able to control the VNC server because Remote Desktop is not able to open the necessary SSH tunnel to the VNC server. 76 Chapter 6 Setting Up the Network and Maintaining Security To enable Observe and Control transport encryption: 1 Choose Remote Desktop > Preferences. 2 Click the Security button. 3 In the “Controlling computers” section, select “Encrypt all network data.” Encrypting Network Data During Copy Items and Install Packages Tasks Remote Desktop can send files for Copy Items and Install Packages via encrypted transport. This option is not enabled by default, and you must either enable it explicitly for each copy task, or in a global setting in Remote Desktop’s preferences. Even installer package files can be intercepted if not encrypted. To encrypt individual file copying and package installation tasks: m In the Copy Items task or Install Packages task configuration window, select “Encrypt network data.” To set a default encryption preference for file copies: 1 In the Remote Desktop Preferences window, select the Security pane. 2 Check “Encrypt transfers when using Copy Items,” or “Encrypt transfers when using Install Packages” as desired. Alternatively, you could encrypt a file archive before copying it. The encrypted archive could be intercepted, but it would be unreadable.7 77 7 Interacting with Users Apple Remote Desktop is a powerful tool for interacting with computer users across a network. You can interact by controlling or observing remote screens, text messaging with remote users, or sharing your screen with others. This chapter describes Remote Desktop’s user interaction capabilities and gives complete instructions for using them. You can learn about:  “Controlling” on page 78  “Observing” on page 85  “Sending Messages” on page 92  “Sharing Screens” on page 93  “Interacting with Your Apple Remote Desktop Administrator” on page 9478 Chapter 7 Interacting with Users Controlling Apple Remote Desktop allows you to control remote computers as if you were sitting in front of them. You can only control the keyboard and mouse of any one computer at a time. There are two kinds of remote computers that Apple Remote Desktop can control: Apple Remote Desktop clients and Virtual Network Computing (VNC) servers. Controlling Apple Remote Desktop Clients Apple Remote Desktop client computers can be controlled by any administrator computer that has the Control permission set. See “Apple Remote Desktop Administrator Access” on page 59 for more information about Apple Remote Desktop permissions. While you control an Apple Remote Desktop client computer, some keyboard shortcut commands are not sent to the remote computer, but they affect the administrator computer. These include:  Change Active Application (Command-Tab and Command-Shift-Tab)  Show or Hide Dock (Command-Option-D)  Log Out User (Command-Shift-Q)  Take Screen Shot (Command-Shift-3, -4)  Force Quit (Command-Option-Escape)Chapter 7 Interacting with Users 79 Also, special keys including the sound volume, screen brightness, and Media Eject keys do not affect the client computer. These instructions assume the that observed computer has Apple Remote Desktop installed and configured properly (see “Setting Up an Apple Remote Desktop Client Computer for the First Time” on page 41) and that the computer has been added to an Apple Remote Desktop computer list (see “Finding and Adding Clients to Apple Remote Desktop Computer Lists” on page 49). To control an Apple Remote Desktop client: 1 Select a computer list in the Remote Desktop window. 2 Select one computer from the list. 3 Choose Interact > Control. 4 To customize the control window and session, see “Control Window Options” on page 79. 5 Use your mouse and keyboard to perform actions on the controlled computer. If your Remote Desktop preferences are set to share keyboard and mouse control, the remote computer’s keyboard and mouse are active and affect the computer just as the administrator computer’s keyboard and mouse do. If your preferences aren’t set to share control, the remote computer’s keyboard and mouse do not function while the administrator computer is in control. Control Window Options When controlling a client, the control window contains several buttons in the window title bar which you can use to customize your remote control experience. There are toggle buttons that switch your control session between two different states, and there are action buttons that perform a single task. In addition to the buttons, there is a slider for image quality. The toggle buttons are:  Control mode or Observe mode  Share mouse control with user  Fit screen in window  Lock computer screen while you control  Fit screen to full display The action buttons are:  Capture screen to a file  Get the remote clipboard contents  Send clipboard contents to the remote clipboard80 Chapter 7 Interacting with Users Switching the Control Window Between Full Size And Fit-To-Window When controlling a client, you can see the client window at full size, or scaled to fit the control window. Viewing the client window at full size will show the client screen at its real pixel resolution. If the controlled computer’s screen is larger than your control window, the screen show scroll bars at the edge of the window. To switch in-a-window control between full size and fit-to-window modes: 1 Control a client computer. 2 Click the Fit Screen In Window button in the control window toolbar. Switching Between Control and Observe Modes Each control session can be switched to a single-client observe session, in which the controlled computer no longer takes mouse and keyboard input from the administrator computer. This allows you to easily give control over to a user at the client computer keyboard, or place the screen under observation without accidentally affecting the client computer. See “Observing a Single Computer” on page 90 for more information on Apple Remote Desktop observe mode. To switch between control and observe modes: 1 Control a client computer. 2 Click the Control/Observe toggle button in the control window toolbar. Sharing Control with a User You can either take complete mouse and keyboard control or share control with an Apple Remote Desktop client user. This allows you to have more control over the client interaction as well as prevents possible client side interference. This button has no effect while controlling VNC servers. See “Controlling VNC Servers” on page 82 for more information. To switch between complete control and shared mouse modes: 1 Control a client computer. 2 Click the “Share mouse and keyboard control” button in the control window toolbar.Chapter 7 Interacting with Users 81 Hiding a User’s Screen While Controlling Sometimes you may want to control a client computer with a user at the client computer, but you don’t want the user to see what you’re doing. In such a case, you can disable the client computer’s screen while preserving your own view of the client computer. This is a special control mode referred to as “curtain mode.” You can change what’s “behind the curtain” and reveal it when the mode is toggled back to the standard control mode. To switch between standard control and curtain modes: 1 Control a client computer. 2 Click the “Lock computer screen while you control” button in the control window toolbar. Capturing the Control Window to a File You can take a picture of the remote screen, and save it to a file. The file is saved to the administrator computer, and is the same resolution and color depth as the controlled screen in the window. To screen capture a controlled client’s screen: 1 Control a client computer. 2 Click the “Capture screen to a file” button in the control window toolbar. 3 Name the new file. 4 Click Save. Switching Control Session Between Full Screen and In a Window You can control a computer either in a window, or using the entire administrator computer screen. The “Fit screen to full display” toggle button changes between these two modes. In full screen mode, the client computer screen is scaled up to completely fill the administrator screen. In addition to the client screen, there are a number of Apple Remote Desktop controls still visible overlaying the client screen. In in-a-window mode, you can switch between fitting the client screen in the window or showing it actual size, possibly scrolling around the window to see the entire client screen. See “Switching the Control Window Between Full Size And Fit-To-Window” on page 80 for more information. To switch between full screen and in-a-window modes: 1 Control a client computer. 2 Click the “Fit screen to full display” button in the control window toolbar.82 Chapter 7 Interacting with Users Sharing Clipboards for Copy and Paste You can transfer data between the Clipboards of the administrator and client computer. For example, you may want to copy some text from a file on the administrator computer and paste it into a document open on the client computer. Similarly, you could copy a link from the client computer’s web browser and paste it into the web browser on the administrator computer. The keyboard shortcuts for Copy, Cut, and Paste are always passed through to the client computer. To share clipboard content with the client: 1 Control a client computer. 2 Click the “Get the remote clipboard contents” button in the control window toolbar to get the client’s Clipboard content. 3 Click the “Send clipboard contents to the remote clipboard” button in the control window toolbar to send content to the client’s Clipboard. Controlling VNC Servers Virtual Network Computing (VNC) is remote control software. It allows a user at one computer (using a “viewer”) to view the desktop and control the keyboard and mouse of another computer (using a VNC “server”) connected over the network. For the purposes of these instructions, VNC-enabled computers are referred to as “VNC clients.” VNC servers and viewers are available for a variety of computing platforms. Remote Desktop is a VNC viewer and can therefore control any computer on the network (whether that computer is running Mac OS X, Linux, or Windows) that is:  Running the VNC server software  In an Apple Remote Desktop computer list If the you are trying to control a VNC server which is not Remote Desktop, it will not support Remote Desktop keystroke encryption. If you try to control that VNC server, you will get a warning that the keystrokes aren’t encrypted which you will have to acknowledge before you can control the VNC server. If you chose to encrypt all network data, then you will not be able to control the VNC server because Remote Desktop is not able to open the necessary SSH tunnel to the VNC server. For more information, see “Encrypting Observe and Control Network Data” on page 75. These instructions assume the observed computer has been added to an Apple Remote Desktop computer list (see “Finding and Adding Clients to Apple Remote Desktop Computer Lists” on page 49). When adding a VNC server to an Apple Remote Desktop computer list, you only need to provide the VNC password, with no user name. To control a VNC client computer: 1 Select a computer list in the Remote Desktop window.Chapter 7 Interacting with Users 83 2 Select one computer from the list. 3 Choose Interact > Control. If the controlled computer’s screen is larger than your control window, the screen scrolls as the pointer approaches the edge of the window. 4 To customize the control window and session, see “Control Window Options” on page 79. 5 Use your mouse and keyboard to perform actions on the controlled computer. Regardless of your Apple Remote Desktop preferences, controlled VNC servers share keyboard and mouse control. The remote computer’s keyboard and mouse are active and affect the computer just as the administrator computer’s keyboard and mouse do. Setting up a Non–Mac OS X VNC Server This section contains very basic, high-level steps for setting up a non–Mac OS X client to be viewed with Remote Desktop. This section cannot give detailed instructions, since the client operating system, VNC software, and firewall will be different. The basic steps are: 1 Install VNC Server software on the client computer (for example, a PC, or a Linux computer). 2 Assign a VNC password on the client computer. 3 Make sure the client’s firewall has the VNC port open (TCP 5900). 4 Make sure “Encrypt all network data” is not selected in the Security section of the Remote Desktop Preferences. 5 Add the computer to the Remote Desktop’s All Computers list using the client’s IP address. 6 Put the client computer’s VNC password in the Remote Desktop authentication box. There is no user name for a VNC server, just a password. Apple Remote Desktop Control and the PC’s Ctrl-Alt-Del If you use Remote Desktop to administer a PC that’s running VNC, you may be wondering how to send the Ctrl-Alt-Del command (Control-Alternate-Delete) from a Mac to the PC. Though Mac and PC key mappings differ, you can use an alternate key combination to send the command.  For full-size (desktop) keyboards, use Control-Option-Forward Delete.  For abbreviated keyboards (on portable computers), use Function-Control-OptionCommand-Delete.84 Chapter 7 Interacting with Users VNC Control Options After you have added a VNC server to a computer list (or when you are first adding it), you can set a custom port for VNC communication, and you can designate a display to control. To set a custom port on an existing computer list member: 1 Select a computer list in the Remote Desktop window. 2 Select a VNC Server computer in the Remote Desktop window. 3 Choose File > Get Info. 4 Click Edit in the Info window. 5 At the end of the IP Address or fully qualified domain name, add a colon followed by the desired port. For example, if you want to connect to a VNC server (vncserver.example.com) that is listening on TCP port 15900, you would enter: vncserver.example.com:15900 6 Click Done. To set a custom VNC port when adding a computer by address: 1 Choose File > Add By Address. 2 Enter the IP address or fully qualified domain name. 3 At the end of the IP Address or fully qualified domain name, add a colon followed by the desired port. For example, if you want to connect to a VNC server (vncserver.example.com) that is listening on TCP port 15900, you would enter: vncserver.example.com:15900 4 Enter the user name and password. 5 Click Add. To designate a display to control: 1 Add a custom port number, as described above. 2 Use the display number for the last number in the custom port designation (display designations start at 0 for the default primary display). For example, f you want to control the default display on a VNC server (vncserver.example.com) that is listening on TCP port 5900, you would enter: vncserver.example.com:5900 If you want to control the second display, you would enter: vncserver.example.com:5901Chapter 7 Interacting with Users 85 If you want to control the third display, you would enter: vncserver.example.com:5902 Configuring an Apple Remote Desktop Client to be Controlled by a VNC Viewer When configured to do so, an Apple Remote Desktop client can be controlled with a non–Apple VNC viewer. Allowing a non–Apple VNC viewer access to an Apple Remote Desktop client is less secure than using Remote Desktop to control the client. The non–Apple VNC software expects the password to be stored in a cryptographically unsecured form and location. To configure a client to accept VNC connections: 1 On the client computer, open System Preferences. 2 Click Sharing, select Apple Remote Desktop, then click Access Privileges. 3 Select “VNC viewers may control screen with the password.” 4 Enter a VNC password. 5 Click OK. Observing You may not want to control a computer, but merely monitor what is on its screen. Observing a remote computer is similar to controlling one, except your mouse movements and keyboard input are not sent to the remote computer. Apple Remote Desktop client computers can be observed on any administrator computer that has the “Observe” permission set. See “Apple Remote Desktop Administrator Access” on page 59 for more information about Apple Remote Desktop permissions. Warning: Do not use the same password as any user or Apple Remote Desktop administrator. The password may not be secure.86 Chapter 7 Interacting with Users Remote Desktop allows you to observe multiple clients on the same screen, cycling through the list of observed computers. This allows you to monitor many screens without having to select each one individually. Dealing With Many Client Screens When observing a single client, you can see the client window at full size, or scaled it to fit the observe window. To switch between the full size and fitting to the window, click the Fit to Window button, just as you would in a control window. If you’re observing more clients than you’ve chosen to fit on one screen, you can cycle through multiple pages by clicking the Previous or Next button. Cycle Pages: Use these buttons to manually switch to the previous or next page of screens. Getting More Information on Observed Clients There is a computer information area beneath each of the observed desktops. It’s automatically disabled when the administrator is viewing more computers than the computer information area is able to show effectively (a threshhold of about 220 pixels across). This could happen if:  the initial selection of computers is too great for the window sizeChapter 7 Interacting with Users 87  the observe window is resized, shrinking the information beneath the threshold  the setting for the number of viewed machines is changed The computer information area is reenabled when the sizes are returned to more than the image size threshhold. Changing Observe Settings While Observing While you are observing multiple computers, you can adjust the Apple Remote Desktop observe settings using the controls at the top of the observe window. These settings will be visible after clicking View Options in the toolbar. To change your observe settings:  Page Delay: Adjust the number of seconds before automatically advancing to the next page of screens.  Computers per page: Adjust the number of client screens visible on each page.  Image Quality: Adjust the screen color depth from black and white to millions of colors.  Titles: Change the titles of the displayed screens in the computer information area.  Account Picture: Add the currently logged-in user’s account picture under each observed desktop. See “Viewing a User’s Account Picture While Observing” on page 88 for more information.  Computer Status: Add a status overview icon underneath the observed desktop. See “Viewing a Computer’s System Status While at the Observe Window” on page 88 for more information.88 Chapter 7 Interacting with Users Changing Screen Titles While Observing While you are observing multiple computers, you can change the title underneath the desktops shown in the observe window. The main title can be the:  Name (the computer sharing name)  IP Address  Host Name To change your observe window titles: 1 Click View Options in the observe window’s toolbar. 2 Select Display Computer Information. 3 From the Title pop-up menu, select the desired title. 4 Click Done. Viewing a User’s Account Picture While Observing Remote Desktop can display the user’s account picture and a user-created status underneath the observed desktop. The user’s account picture is their system login icon, so it might be either a picture taken from an iSight camera, or a custom image selected in the Accounts pane of System Preferences. To view a user’s account picture: 1 Click View Options in the observe window’s toolbar. 2 Select Display Computer Information. 3 Select Account Picture. 4 Click Done. Viewing a Computer’s System Status While at the Observe Window Remote Desktop can display certain system status information underneath the observed desktop. This information gives you a basic assessment of the following service statistics:  CPU Usage  Disk Usage  Free MemoryChapter 7 Interacting with Users 89 There are two levels of detail for system statistics. The top level is a single icon (a red, yellow, or green icon). You show the second level of detail by placing the mouse pointer over the high-level status icon. The icon changes to an “i” and you can click the “i” to get more information. Clicking the icon exposes per-service status icons: Icon Indicates or One or more service statistic is red. This takes precedence over any yellow or green indicator. or One or more service statistic is yellow This takes precedence over any green indicator. Service is operating within established parameters. No service informaiton available. Service Icon Status CPU Usage Usage is at 60% or less Usage is between 60% to 85% Usage is at 85% or higher No status information is available DIsk Usage Usage is at 90% or less Usage is between 90% and 95% Usage is at 95% or higher No status information is available Free Memory Less than 80% used Between 80% and 95% used90 Chapter 7 Interacting with Users To show system status in the observe window: 1 Click View Options in the observe window’s toolbar. 2 Select Display Computer Information. 3 Select Computer Status. 4 Click Done. Shortcuts in the Multiple Screen Observe Window You can access several Apple Remote Desktop commands using icons in the observe window. You can customize the observe window with the commands that are most useful to you. For example, you may want to access the Copy Items command, the Text Chat command, and the Lock Screen command, using the buttons in the observe window toolbar. You perform Remote Desktop tasks on any computer by selecting its screen and choosing a task from the Remote Desktop menus or the observe window toolbar. Regardless of your toolbar customizations, you’ll be able to advance through pages manually, change the titling of the observed screens, change the number of client screens per page, change the number of seconds before paging, or change the color depth of the observed screens. Observing a Single Computer When you observe a single computer, the observed screen appears in a window on your administrator computer. If a screen saver is active when you observe the screen, the screen saver remains in effect. The observe window contains a “Share mouse control” button to switch to controlling the screen. To observe a single computer: 1 Select a computer list in the Remote Desktop window. 2 Select a computer in the Remote Desktop window. 3 Choose Interact > Observe. If the observed computer’s screen is larger than the observe window, the screen will scroll as the pointer approaches the edge of the window. 4 To customize the single-client observe window and session, see “Control Window Options” on page 79. The observe window’s options are the same as those of the control window. Over 95% used No status information available Service Icon StatusChapter 7 Interacting with Users 91 Observing Multiple Computers When you observe multiple client computers, each client screen is scaled down, so that several computers can be viewed at the same time. You can set the number of client screens that appear at any one time. See “Setting Preferences for the Remote Desktop Administrator Application” on page 36 for more information. If a client has a screen saver running when you start observing, the screen saver remains in effect. The screens will cycle through the entire list of selected computers, a few at a time, switching every 30 seconds, altered by the speed setting. To observe multiple computers: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Interact > Observe. The remote computer screens appear in a window. Observing a Computer in Dashboard If you are using Mac OS X version 10.4 or later, you can use the Dashboard widget to observe one client computer. The computer must be in your All Computers list and be authenticated with permission to Observe. Apple Remote Desktop does not have to be launched to use the widget. To observe using Dashboard: 1 Add the computer to your All Computers list. See “Finding and Adding Clients to Apple Remote Desktop Computer Lists” on page 49 for detailed information. 2 Activate Dashboard, and click the widget’s icon to run it. 3 Click the widget’s “Info” button to flip the widget over. 4 Supply a hostname or IP address, login name, and password or simply select the computer you want to observe (if it’s listed). 5 Click Done.92 Chapter 7 Interacting with Users Sending Messages Apple Remote Desktop allows you to communicate with users of Apple Remote Desktop client computers using text messaging. You can use text messages to give instructions or announcements, to collaborate remotely, or troubleshoot with users. There are two types of text messaging: one-way messages and two-way interactive chat. Text messages and chat are available only to Apple Remote Desktop client computers; they are not available to VNC client computers. Sending One-Way Messages You can use a one-way text message to send announcements or information to users client computers. The announcements appear in front of open application windows and can be dismissed by the user. To send a one-way text message: 1 Select a computer list in the Remote Desktop window. 2 Select one computer from the list. 3 Choose Interact > Send Message. 4 Enter your message. 5 Click Send. The text message appears on the screen of all the selected computers. Interactive Chat You can start an interactive text chat with the user of an Apple Remote Desktop client computer. This allows instant feedback from users, so you can collaborate or troubleshoot. To begin an interactive chat: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Interact > Chat. 4 Enter your message, one line at a time. The message appears real-time on the user’s screen as you type.Chapter 7 Interacting with Users 93 5 Press the Return key to complete and send each line. Viewing Attention Requests After a client user sends an attention request, the Apple Remote Desktop administrator can read the attention request text. To view attention requests: 1 Choose Window > Messages From Users. 2 Select the message you want to view. 3 Click Display to view the request’s message. Sharing Screens Apple Remote Desktop allows you to show your screen (or the screen of a client computer in your list) to any or all Apple Remote Desktop client computers in the same computer list. You can, for example, show a presentation to a classroom of computers from a single computer. Sharing a Screen with Client Computers You can share a client computer’s screen, or the administrator’s screen, with any number of clients. The client screen displays what is on the shared screen, but cannot control it in any way. To share a computer’s screen: 1 Select a computer list in the Remote Desktop window. 2 Select on or more computers in the selected computer list. These computers include the target computers and the source computer. 3 Choose Interact > Share Screen. 4 Select the screen to be shared. If you want to share the Apple Remote Desktop administrator screen, select “Share your screen.” If you want to share a client screen, select “Share a different screen,” and drag a computer from an Apple Remote Desktop computer list to the dialog. 5 Click Share Screen. The selected computer shows the shared computer screen. If the target computer’s screen resolution is lower than the shared computer’s, only the top left part of the shared screen (up to the lowest screen resolution) is seen on the target screen.94 Chapter 7 Interacting with Users Monitoring a Screen Sharing Tasks You may want to keep track of the screen sharing tasks you have begun. You can get information on all active screen sharing tasks, and can sort the tasks by time started, source screen, or target computers. To view current active screen sharing tasks: m Choose Window > Active Share Screen Tasks. Interacting with Your Apple Remote Desktop Administrator Users of Apple Remote Desktop client computers can initiate contact with a Remote Desktop administrator. Clients can ask for attention from the administrator, or cancel that attention request. Additionally, users of Apple Remote Desktop client computers can set an identifying icon for a Remote Desktop administrator to view. The Remote Desktop administrator can choose whether to view the icon or not. Requesting Administrator Attention At times, Apple Remote Desktop client computer users need to get the attention of the Apple Remote Desktop administrator. If an Apple Remote Desktop administrator is currently monitoring the client computer, the client user can send an attention request. To request administrator attention: 1 Click the Apple Remote Desktop status icon and choose Message to Administrator. The attention request window appears. 2 If the network has more than one Apple Remote Desktop administrator available, choose an administrator from the “Send message to” pop-up menu. 3 Enter the message. 4 Click Send. The attention request icon appears on the administrator’s screen.Chapter 7 Interacting with Users 95 Canceling an Attention Request If a user no longer needs the Apple Remote Desktop administrator’s attention, he or she can cancel the attention request after it has been sent. To cancel an attention request: 1 Click the Apple Remote Desktop status icon and choose Message to Administrator. 2 Click the Apple Remote Desktop status icon in the menu bar and choose Cancel Message. Changing Your Observed Client Icon By default, the icon that the Remote Desktop administrator sees while observing is the login icon for the currently logged-in user. If you had an iSight camera active when setting up your computer, you may have taken a picture of yourself for your user icon. You can change this icon, and it will change on the administrator’s observation screen. To change your login icon: 1 Prepare the picture you want to use. You could use a graphic file, or take a picture using an iSight camera. 2 Open System Preferences. The System Preferences application launches. 3 Select the Accounts pane. 4 Select your account, and choose the Picture button. 5 Replace your current account picture with the new picture. 6 Close System Preferences.8 96 8 Administering Client Computers Apple Remote Desktop gives you powerful administrative control. You can manually or automatically get detailed information about every computer, install software, and maintain systems from a single administrator computer. This chapter describes Remote Desktop’s capabilities and gives complete instructions for using them. You can learn about:  “Keeping Track of Task Progress and History” on page 96  “Installing Software Using Apple Remote Desktop” on page 101  “Upgrading Software” on page 105  “Copying Files” on page 106  “Creating Reports” on page 111  “Maintaining Systems” on page 127  “Managing Computers” on page 135  “UNIX Shell Commands” on page 143  “Automating Functions” on page 152 Keeping Track of Task Progress and History The task history area is on the left side of the Remote Desktop window (see “Remote Desktop Main Window” on page 29) with all computer lists and scanners. Every time you execute a task (generating a report, copying a file, restarting a computer), the task name, affected computers, task result, and time you execute it is stored in the Task History window (accessible via Window > Task History). The Task History list, in the main Remote Desktop window, shows the task name and result. You can collapse the Task History list to reduce its size. You can select a task in the Task History list to see some information about it, and double-click it to view a more detailed description of the task, as well as the computers involved with it. Tasks in progress appear in the Active Tasks list, where you can stop and restart them.Chapter 8 Administering Client Computers 97 Remote Desktop keeps track of three kinds of task progress: active, Task Server, and completed. Active tasks are those which are currently being processed by the client computers, and the client computers have not all reported back to the administrator console. Some tasks are so short that they only briefly appear in the list of current tasks; other tasks may take a long time and remain there long enough to return to the task and view the progress as it happens. The Active Tasks list is located in the left side of the Remote Desktop window, and has a disclosure triangle to expand or hide the list. Task Server tasks are those which have been assigned to the task server (either the one running on the administrator’s computer, or a remote one) which have not yet completed for all the task participants. Completed tasks are those which have received a task status for all participating client computers. The task description and computer list then moves to the task history list. The task history list is located in the left side of the Remote Desktop window, and has a disclosure triangle for expanding or hiding the list. In addition to the task status and notification features of Remote Desktop, you can set a task notification shell script to run when any task has completed. This script is for all tasks, but it can be as complex as your needs require. Enabling a Task Notification Script When a task completes, Remote Desktop can run a script that you create. This script is for all completed tasks, and it must be a shell script. There is a default notification script provided, which you can customize for your needs. The script must be a shell script, but you can use various other scripting environments like AppleScripts with the osascript command. To enable a task notification script: 1 Make sure you are logged in as an administrator user. 2 Open Remote Desktop. 3 Choose Remote Desktop > Preferences. 4 Click the Tasks button. 5 Select “Enable task notification script.” 6 Choose the location of the script. The default notification script is located at /Library/Application Support/Apple/Remote Desktop/Notify. 7 Close the Preferences window.98 Chapter 8 Administering Client Computers Getting Active Task Status When you get a task’s current status, you see the progress of the task, the computers involved, and their feedback to the administrator computer. To get status on a currently running task: 1 Select the Active Tasks list. 2 Select the desired task in the Remote Desktop window. The task status and computers involved are shown in the Remote Desktop window. You can make sure the main window always shows the currently running task in the main work area by setting a preference. Otherwise, the main window will continue to show the last selected computer list. To automatically show task status in the main window: 1 Make sure you are logged in as an administrator user. 2 Open Remote Desktop. 3 Choose Remote Desktop > Preferences. 4 Click the Tasks button. 5 Select “Always change focus to active task.” 6 Close the Preference’s window. Using the Task Feedback Display You can use the task feedback display to:  Retry a task on selected computers  Cancel a task in progress Tasks in progress appear in the Active Tasks list, where you can stop them, or run them again. To use the task feedback window: 1 Select the task in the task history list or active task list. 2 Change the task as desired: a Click the retry button to perform the task again. b Click the stop button to cancel the active task. Stopping a Currently Running Task If a task is in progress and Remote Desktop is still waiting for feedback from the client computers, you can stop the task. You use the Active Tasks list to stop the command in progress.Chapter 8 Administering Client Computers 99 To stop a currently running task: 1 Select the Active Tasks list. 2 Select the desired task in the Remote Desktop window. The task status and computers involved are shown in the Remote Desktop window. 3 Click the Stop button in the top-right of the main window. Getting Completed Task History After a task has received feedback from all the involved client computers, or they have experienced a communication time-out, the task is moved to the Task History list. The Task History list is located in the left side of the Remote Desktop window, and has a disclosure triangle to expand or hide the list. This list stays populated as long you’ve set in the Remote Desktop preferences. The Task History list can also be viewed in a separate window with the tasks sorted by date. To get status on a completed task: 1 Open the Task History list using the disclosure triangle. 2 Select the desired task in the Remote Desktop window. The final task status and computers involved are shown in the Remote Desktop window. or m Select Window > Task History. The final task status and computers involved are shown in a separate window. Saving a Task for Later Use You may want to save a task for later, repeated use. If you find yourself repeating certain tasks, you can save those tasks and the information about which computers go with them. Observe and Control tasks cannot be saved. Saved tasks appear in a list on the left side of the Remote Desktop main window. To save a task for later use: 1 Open the task you want to save. For example, if you want to save a Copy Items task, select Manage > Copy Items. 2 Configure the task as desired. 3 Before executing the task, click Save. 4 Name the saved task. The task appears in a list on the left side of the Remote Desktop main window.100 Chapter 8 Administering Client Computers Creating and Using Task Templates In each task configuration dialog, you can save a task’s settings to a template to reuse for future tasks of that same type. For example, if you always use certain copy options for a Copy Items task, you can save those settings as a template, and have them apply to any newly created Copy Items task. Once a task template is saved, you can select any one of the saved templates from the Templates pop-up menu. Selecting a template automatically configures the dialog box according to the saved template. If you want to perform a task similar to an existing template, you start with that template using the Template pop-up menu, then you customize the resulting task configuration dialog after applying the template. For example, if you always want to use the same Copy Items options, but you want vary the group of computers you apply it to, you create a task template by configuring the copy options dialog without selecting target computers and then saving it via the Templates pop-up menu. Then whenever you make a new Copy Items task with target computers selected, you can apply the saved settings by selecting those settings from out of the Templates pop-up menu and add your own settings afterward. You are free to make as many templates as you want either from existing templates or from scratch. Once saved, a template can be made the task’s default, with all new instances of the task opening with the default template settings. You can also edit the task template list from the Template pop-up list, removing a template, or making it the task default. There are existing, built-in templates for the Send UNIX Command task which can not be removed, see “Send UNIX Command Templates” on page 143 for more information. Note: Templates are only stored for their own task type. For example, Copy Items saved templates are not available for use with Rename Computer tasks, etc. To create a task template: 1 Open a task configuration window. You can use existing saved tasks, or a newly created task. 2 Configure the task as desired. 3 Click the Template pop-up menu, and select Save as Template. 4 Name the template, and click OK. To apply a task template: 1 Open a task configuration window. You can use existing saved tasks, or a newly created task. 2 Click the Template pop-up menu, and select the template you want. The settings in the template are now applied to the dialog window. 3 If desired, customize the task further.Chapter 8 Administering Client Computers 101 Editing a Saved Task You may want to change a previously saved task, changing whether what the task does or changing the target computers. To edit a saved task: 1 Double-click the saved task you want to edit. Alternatively, you could use Control-click or right-click and choose Edit Task from contextual menu. 2 In the task description window, change the task parameters. You can alter task preferences, and change the computer list. Remove computers by selecting them and pressing the Delete key; add computers by dragging them from a list to the task. After a task is completed, the task name, result, and time you last ran it are stored for review. The task feedback window gives a detailed account of the task, and reports success or failure for each participating client computer. To view the task feedback window: m Select the task in the Task History list. Installing Software Using Apple Remote Desktop There are several methods you can use to install software with Apple Remote Desktop. The following section describes how to install software using installer packages and metapackages, using the copy command in Remote Desktop, using installers made by other software companies, or using NetBoot or Network Install. Installing by Package and Metapackage You can install new software automatically and without user intervention by copying installer packages (.pkg or .mpkg files) to one or more remote clients. Apple Remote Desktop copies the package to the computers you choose, runs the installer with no visible window or user interaction required, and then erases the installer files on completion. Warning: Distributing copyrighted software without the appropriate license agreement is a violation of copyright law.102 Chapter 8 Administering Client Computers You can choose to initiate the installation of a package from the designated Task Server rather from a Remote Desktop task. This allows you to install packages on to computers that may not be connected to the network (with a status of “Offline”) when you run the task. The Task Server monitors the network for the next time the offline client comes online again. Then the Task Server performs the installation. For more information about designating a Task Server, see “Using a Task Server for Report Data Collection” on page 112 and “Designating the Task Server and Setting the Report Data Collection Location” on page 154. For detailed instructions about installing via the Task Server, see “Installing Software on Offline Computers” on page 103. You can install multiple packages in succession. When you execute installation of multiple packages, Remote Desktop copies over all the selected packages and then installs them. It also detects whether a restart is required and will give you a visual cue. You can tell the task to restart the computers upon completion, or restart the computers manually later. It is not possible to stop the installation of a package. Once the installation starts, it will complete (assuming no errors occur on the client). However, you can click the Stop button to stop remaining packages from being copied over and therefore halt the install. Alternatively, an administrator can use the PackageMaker application (available on the Apple Remote Desktop CD or with the Apple Developer Tools) to create a metapackage that contains several installers to be run in sequence. In addition to creating metapackages, you can also use PackageMaker to create packages for custom software that your organization may have developed. More information about making and using packages and metapackages is available on the Apple Developer Connection website: developer.apple.com To copy and install software using a .pkg file: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Install Packages. 4 Select a .pkg or .mpkg file to install. Alternatively, you can drag an installer package on to the package list window. 5 Select whether to restart the target computers after installation. 6 Select the option to run the task from “This application.” This option is preferable when installing on computers that are all currently online. If you want to install the software via a Task Server, see “Installing Software on Offline Computers” on page 103.Chapter 8 Administering Client Computers 103 7 Select other installation parameters, as desired. For more information on the available options, see “Copy Options” on page 107. Note: Client computers are not restarted automatically after an installation is complete unless explicitly selected in the task command. 8 Click Install. During installation, a progress bar appears in the task header in the main window. No progress bars appear on the client computer. The copied package is deleted from the client computer if an error occurs during installation. However, a failed installation may leave behind other files created by the installer. Installing Software on Offline Computers Using Apple Remote Desktop, you can install software on a computer that is not currently connected to the network (with a status of “Offline”). The installation does not occur when initially ordered, but when the offline computer next becomes available. The installation itself is handled by a designated Task Server. The Task Server will continue to monitor the network for the next time the offline client comes online again. For more detailed information about setting up and using a Task Server, see “Designating the Task Server and Setting the Report Data Collection Location” on page 154. To install software on offline clients: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. Any or all may be offline. 3 Choose Manage > Install Packages. 4 Select a .pkg or .mpkg file to install. Alternatively, you can drag an installer package into the Packages list. 5 Choose whether to run the task from the Task Server designated by Remote Desktop’s preferences. To set up or alter the Task Server, see “Using a Task Server for Report Data Collection” on page 112 and “Designating the Task Server and Setting the Report Data Collection Location” on page 154. 6 Select other installation parameters, as desired. For more information on the available options, see “Copy Options” on page 107 and “Installing by Package and Metapackage” on page 101. 7 Click Install.104 Chapter 8 Administering Client Computers Installing by Using the Copy Items Command Many applications can be installed simply by copying the application or its folder to the client computer. Consult the application’s documentation to verify that you can simply copy the application to the hard disk to install it. To install software by copying: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Copy Items. 4 Add software to the “Items to copy” list. For more information, see “Copying Files” on page 106. Repeat this step until all the software you want to copy is in the list. 5 Select a destination. There are several preset locations available in the “Place items in” pop-up menu, including the Applications folder. If you do not see the location you want, you can specify a full pathname. 6 Select your copy options. See “Copy Options” on page 107 for more information on the available options. 7 Click Copy. The software is copied to the indicated location. If the copy operation is unsuccessful, an error message appears in the task feedback window. Using Installers from Other Companies The Install Packages command only works with installers that use the .pkg or .mpkg file format, and some applications can’t be installed by simply copying the application to the hard disk. To install software using installers with different file formats, you use a combination of tasks. To install software with third-party installers: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Copy Items. 4 Add the software installer to the “Items to copy” list. For more information, see “Copying Files” on page 106. 5 Select a copy destination. 6 Select After Copying Open Items. 7 Click Copy.Chapter 8 Administering Client Computers 105 The software is copied to the indicated destination. If the copy is operation unsuccessful, an error message appears in the task feedback window. 8 Select a computer that received the copy of the installer. 9 Choose Interact > Control. 10 Control the screen of the selected computer and complete the installation process interactively. Upgrading Software Upgrading software is similar to installing software. However, the method of upgrading software depends on the original method of installation. As a general rule, upgrades should not be done while users have their applications open. Make sure the software to be upgraded is not running. Upgrading consists of three main tasks:  Finding out if a piece needs to be updated  Removing the old version  Installing the new version To upgrade software on client computers: 1 Run a Software Version report to determine what version of the software client computers have. See “Generating a Software Version Report” on page 118 to learn how to run the report. 2 Remove the old version of the software. If the software was originally installed using a package or metapackage, it should be removed automatically when you install the new version. If the software was originally installed using the Copy Items command, you can delete the old version, or simply replace the old version with the new version when you install the new version. If the software was originally installed using another company’s installer application, you may need to use an uninstaller before installing the new version. Consult the software’s manual for instructions on removing its software. If an uninstaller application is necessary, you can copy it to each of the client computers and run it remotely. Warning: Distributing copyrighted software without the appropriate license agreement is a violation of copyright law.106 Chapter 8 Administering Client Computers 3 Use the appropriate installation method to install the new version of the software. For more information, see:  “Installing by Package and Metapackage” on page 101  “Installing by Using the Copy Items Command” on page 104  “Using Installers from Other Companies” on page 104 Copying Files Apple Remote Desktop makes it easy to copy items (other than the system software) on one or more client computers. Copying files works fastest with a small number of files. For example, ten files that are 10 KB each generally take longer than one file that is 100 KB. Consider copying a single file archive (like a .zip or .sit file) to remote computers for faster copying. Remember that Mac OS X applications are bundles of many smaller files. Although the application you want to copy looks like a single file in the Finder, it may contain hundreds, or even thousands of smaller files. If a client computer is asleep when you attempt to copy items, Remote Desktop tries to wake the client. If it can’t wake the client and the copy does not proceed, you should use Remote Desktop to wake the target computer, and then attempt the copy again.Chapter 8 Administering Client Computers 107 If you choose to copy out to many client computers simultaneously, Remote Desktop uses network multicasts to send the files. If there is a significant number of multicast networking errors, Remote Desktop tries to copy individually to each client computer. Copy Options Each time you copy an item to a remote computer, you have the chance to customize the operation to allow fine-grained control of the location and file owner of the copied file, the network bandwidth used, and what to do in case of failure or duplicate files. Copy Destination Locations There are several preset destinations available in the “Place Items In” destination popup menu, including the Applications folder. If you do not see the destination you want, you can specify a full pathname. Owner and Group for Copied File By default, the copied files inherit the owner and group of the enclosing destination folder. For additional flexibility, you have several options for handing file ownership. You can:  Preserve current owner  Set the owner to the current console user  Specify user and group Encryption You can encrypt the copy transport stream to protect the data sent across the network. By selecting the “Encrypt network data” option, you exchange performance for security. This option is also available in the Install Packages dialog. Copy Failure Handling By default, if a single computer fails to get the copied file, the copy operation continues to all participating computers. However, there may be times when you want a copy operation to stop if one of the copies fails. You can choose to cancel the entire copy operation if one participating computer reports a failure. This option is also available in the Install Packages dialog. Network Bandwidth Limits File copies are done at the maximum sustainable rate for the network. This allows Apple Remote Desktop to use all the resources at its disposal to quickly and efficiently finish the copy. Depending on what else is being done on the network, you may want to explicitly limit the copy data transfer rate. You can set an approximate maximum data rate in kilobytes per second for file copies. This option is also available in the Install Packages dialog.108 Chapter 8 Administering Client Computers More Options When the Item Already Exists If an item with the same name as the item you selected to copy already exists at the destination, you have several options for handing the name conflict. You can:  replace the existing item  replace the existing item if the existing item is older  rename the existing item  rename the item being copied  always ask which of the above options you want to use Post-Copy Action You can choose to open a copied item immediately after it’s copied. If you select this option, the file will open with the parent application that created it. Copying from Administrator to Clients Using Apple Remote Desktop, you can copy items to any number of client computers simultaneously. To copy items to clients: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the Remote Desktop window (or any window). 3 Choose Manage > Copy Items. 4 Add software to the “Items to copy” list. Click the Add button to browse local hard disks for items to copy, or drag files and folders to the list. If you want to remove an item from the list, select the item and click Remove. Repeat this step until all the software you want to copy is in the list. 5 Select your copy options. See “Copy Options” on page 107 for more information on the available options. 6 If you want to schedule this event for another time, or set it to repeat, click the Schedule button. See “Scheduled Tasks” on page 155 for more information about scheduling events. 7 Click Copy. The software is copied to the indicated destination. If the copy is unsuccessful, an error message appears in the task feedback window.Chapter 8 Administering Client Computers 109 Copying Using Drag and Drop Using Apple Remote Desktop, you can copy items by dragging them between Finder windows on your administrator computer, the Remote Desktop window, and control windows. For example, you can drag an item from a Finder window to a selected computer in the Remote Desktop window. You can use this feature to collect needed files from remote computers or distribute files between remote computers. Copying from the Finder to a Client You can copy files, applications, or folders from the administrator’s Finder windows to remote computers. You can also drag items directly on to a control window. To copy items from the Finder to a client: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers or select the desired Control window. 3 Switch to the Finder. 4 Locate the item you want to copy in the Finder. 5 Drag the item you want to copy from the Finder to the selected clients in the Remote Desktop window or control window. Copying onto a Control window puts the file wherever you drop it. 6 Select your copy options. See “Copy Options” on page 107 for more information on the available options for copy tasks. 7 Click Copy. Copying from a Client to the Finder Using Apple Remote Desktop, you can copy files, applications, or folders from a remote computer to the administrator’s computer. The process requires that you find the file you want to copy, using a report or locating them in a control window. Note: Copied items retain their original owners and permissions. To copy items from a client to the administrator’s computer: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose a file search report to find the item. See “Finding Files, Folders, and Applications” on page 116 for more information. 4 Select the item you want to copy in the report window. 5 Drag the item you want to copy from the report window to the administrator’s Finder, or click the Copy To This Computer button in the menu bar of the report window.110 Chapter 8 Administering Client Computers Alternatively, you can drag items from a control window to the administrator computer’s desktop. Restoring Items from a Master Copy Your client computers can restore non-system software from a master copy. This is helpful if you want to make sure each client computer has the same software. You can automate the software restore process by using the instructions in “Automating Functions” on page 152. You may want to start by creating a disk image that contains the Mac OS X applications and items you want to copy. Alternatively, you can copy files from any local disk, such as a hard disk, CD, disk partition, or other disk. The Copy Items command does not copy system software that is hidden (that is, not visible in the Finder). It can copy the Applications folder, Library folder, and Users folder, as well as any folders at the root of the hard disk that were created by the computer’s administrator user. Important: You cannot use the Copy Items feature to copy Mac OS X system software to client computers To restore files using the Copy Items command: 1 Make a master copy of the volume that has the files to be restored. You can use any volume, such as a spare hard disk, a CD, or a mounted disk image (.dmg) file. 2 Mount the master copy volume on the administrator computer. Master copy volumes must be local volumes, not mounted from over a network. 3 Open Remote Desktop. 4 Select a computer list in the Remote Desktop window. 5 Select one or more computers in the selected computer list. 6 Choose Manage > Copy Items. 7 Add the master copy volume to the Copy Items list. 8 Select your copy options. See “Copy Options” on page 107 for more information on the available options for copy tasks. 9 If you want to schedule this event for another time or set it to repeat, click the Schedule button. See “Scheduled Tasks” on page 155 for more information about scheduling events. 10 Click Copy.Chapter 8 Administering Client Computers 111 Creating Reports Apple Remote Desktop allows you to query client computers for many kinds of information, from installed software to network speed and reliability. Creating reports gives you valuable information about the client computers. Reports also help when you’re copying files and organizing computer lists. Collecting Report Data There are three search strategies that Apple Remote Desktop uses when searching for report information: new data, cached data, and Spotlight data. With a new data search, the Remote Desktop application queries a client directly, and waits for the client computer to respond with the desired information. A new data search gets the most recent information, but takes longer since the client computer has to gather all the data and send it over the network to the waiting administrator computer. New data reports are also generated by clients whose reporting policy is set to send data only in response to a report query. See “Setting the Client’s Data Reporting Policy” on page 152. The next source of information is a cached data search. With a cached data search, the application queries Apple Remote Desktop’s internal database of collected system information (such as hardware information and system settings), file information (including installed applications and versions, and software names), or both. You determine how often the data is collected, and what type of data is stored. See “Setting the Client’s Data Reporting Policy” on page 152.112 Chapter 8 Administering Client Computers The database, which is a PostgreSQL database located at /var/db/RemoteManagement/ RMDB/ can be accessed using other tools besides Remote Desktop. To find out more about the database schema, see “PostgreSQL Schema Sample” on page 180. The last kind of new data search is a Spotlight search. This is not a static report on saved data in a database, but it’s an interactive search of the client computers. A Spotlight search can only be done on client computers running Mac OS X 10.4 or later. Spotlight searches a comprehensive, constantly updated index that sees all the metadata inside supported files—the “what, when and who” of every piece of information saved on your Mac—including the kind of content, the author, edit history, format, size, and many more details. Spotlight searches are “live” meaning that the window reflects changes in the found files even after the command is executed. Using a Task Server for Report Data Collection You can use a computer other than the administrator computer to collect your report data, if you have another unlimited-managed computer license for Apple Remote Desktop. Using a server that is always running and has the benefits of uninterrupted power and steady uptime, you can dedicate those computing resources to report data collection. Such a server is referred to as a Task Server. To use a Task Server, you need:  a computer that will be running when the clients are set to upload their report data  an unlimited license for the Remote Desktop server  a separate unlimited license for the administrator computer To set up a Task Server, you need to: 1 Install Remote Desktop on the server. See “Installing the Remote Desktop Administrator Software” on page 40. 2 Configure the server to be the Task Server. You do this via the server settings in the Remote Desktop preferences. See “Designating the Task Server and Setting the Report Data Collection Location” on page 154 3 Install Remote Desktop on the administrator computer. See “Installing the Remote Desktop Administrator Software” on page 40. 4 Configure Remote Desktop on the administrator computer to use the Task Server as its source for report data. You do this using the server settings in the Remote Desktop preferences. See “Designating the Task Server and Setting the Report Data Collection Location” on page 154. 5 Set the client reporting policy to tell clients to send report information to the Task Server.Chapter 8 Administering Client Computers 113 You do this using the Get Info window of any client computer or the client’s own Apple Remote Desktop preferences. See “Setting the Client’s Data Reporting Policy” on page 152 and “Creating a Template Data Reporting Policy” on page 153. Report Database Recommendations and Bandwidth Usage You can have a single Apple Remote Desktop data collection database for any number of clients. However, avoid having all the clients upload their report information at the same time. As the number of clients grows, the network usage from the clients as they upload their report data could come in bursts over a short period of time overwhelming the network buffer on the Task Server. In such a case, you will probably give yourself your own denial-of-service attack. Increasing the number of Task Server computers can divide the network and computing load among several computers for better performance and better network citizenship. However, since there is no way to aggregate report data across several collectors and display it on one administrator computer, you would need multiple administrators to balance your network load in this manner. If you use a single database for a large number of clients, it is recommended that you stagger the generation of report caches over the time between which you want to run reports. For example, if you normally run a report every week, then set 1/7th of your clients to rebuild caches on day one, another 1/7th for the next day and so on. Additionally, they should stagger the cache rebuild over the course of the day as well. It is recommended that you keep in a given list the minimum number of computers necessary for your purposes. When a list is selected, the clients in the list send status updates at a minimum of every 20 seconds. If you have a large number of clients in a list (for example, 1000), this makes about 50 updates a second. Creating more lists doesn’t create more resource overhead for Remote Desktop, and can allow you to quickly and easily administer the clients you want with a minimum wait. Depending on your network and list sizes, you may find that smaller lists may result in more productive and reliable administration. What Bandwidth Does the Default System Overview Report Use on a LAN? The average System Overview Report cache is about 20 KB. While reporting, the admin and clients will always try to use all available bandwidth (most IP-based client/server applications work this way). Therefore, on a 10Mbit/sec. network, the report data collection for a single client may use 100% of the bandwidth for a period of 0.016 seconds. Assuming a list of 1000 computers, all trying to report at the same time, this may use 100% of the bandwidth for 16 seconds. Naturally, faster networks will perform better, and networks with a slow bottleneck like a DSL or modem line perform worse.114 Chapter 8 Administering Client Computers System Report Size The file system data which is uploaded to the report database (labeled “File Search data” in the Scheduling sheet of the Task Server preference pane) contains a significant amount of data. For a client with 10 GB of files on the hard disk, the report data uploaded can easily reach 5 MB in size. With hundreds or thousands of clients, this amount can add up quickly and might tax network resources. In addition, by choosing to upload user accounting data and application usage data, you are further increasing the size of the uploaded data for any one client. Since you may not want to store all the possible information for a given client computer, you can customize which type of data is collected, as desired. Auditing Client Usage Information With Apple Remote Desktop, you can get detailed information about who has been using the client computers and how. There are two reports that help you audit information about how the clients are being used:  the User History report  the Application Usage report Generating a User History Report The User History report is used to track who has logged in to a computer, when they logged in and out, and how they accessed the computer. The client stores 30 days of accumulated data, so the requested time can’t be more than the last 30 days. The report shows the following information:  computer name  user’s short name  access type (login window, tty, SSH)  login time  logout time  remote login host (originating host to the login session: localhost, or some remote computer) Note: Multiple users logged in via Fast User Switching can lead to confusing or conflicting reports. When a second or third user logs in to a computer, there is no way of knowing which user is the active user. Session length may not reflect actual usage, and login and logout times overlap. User History report information is collected by default if you are installing Remote Desktop for the first time. If you have upgraded an older version of Remote Desktop, you need to enable its collection explicitly in the clients’ reporting policy. See “Setting the Client’s Data Reporting Policy” on page 152 for instructions.Chapter 8 Administering Client Computers 115 To generate a User History report: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Report > User History. 4 Select the time frame for the user history information. 5 Click Generate Report. The newly generated report window appears. Generating an Application Usage Report The Application Usage report shows which applications have been running on a given client, their launch and quit time, and who launched them. The client stores 30 days of accumulated data, so the requested time can’t be more than the last 30 days. The following fields are shown by default in the report:  Computer name  Name of application  Launch date  Total running time  Time as frontmost application  User name of process owner  Current state of application Application Usage report information is collected by default if you are installing Remote Desktop for the first time. If you have upgraded an older version of Remote Desktop, you need to enable its collection explicitly in the clients’ reporting policy. See “Setting the Client’s Data Reporting Policy” on page 152 for instructions. To generate an Application Usage report: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Report > Application Usage. 4 Select the time frame for application usage. 5 Click Generate Report. The newly generated report window appears.116 Chapter 8 Administering Client Computers Finding Files, Folders, and Applications Apple Remote Desktop allows you to search the contents of client computer hard disks for specific files, folders, or applications. Additionally, it can compare the results of such searches to the items on the administrator computer. These searches can compare software versions, fonts, applications, or installed packages. Using Spotlight to Find Items You can use Spotlight to find items on client computers. A Spotlight search can be done only on client computers running Mac OS X v10.4 or later. Spotlight searches are “live,” meaning that the window reflects changes in the found files even after the command is executed. Spotlight searches cannot be used for offline client computers. The Spotlight Search window is similar to the Spotlight Search window found locally on a Mac OS X v10.4 computer. It supports many of the same features and queries as Spotlight on a local computer. For more information on running a Spotlight search, see Spotlight Help. To search for software items using Spotlight: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Interact > Spotlight Search. 4 Choose the desired search parameters and enter a search term. The results are updated immediately in the window.Chapter 8 Administering Client Computers 117 The results of the search are listed in the pane at the bottom of the window. Note: The “Home” Spotlight search location means the Home folder of the currently logged in user. Generating a File Search Report The File Search report allows you to find up to a total of 32,000 items on selected computers. The items can be files, folders, or applications, but they can only be items accessible (or visible) in the Finder. The search parameters include:  Name  Parent path  Full path  Extension  Date created  Date modified  Size on disk  Kind  Version number  Version string  Owner  Group  Lock status The search parameters for Apple Remote Desktop are slightly different from those used by the Finder’s Find command. For example, Apple Remote Desktop does not search by visibility or by label. The report display can be customized as well. See “Changing Report Layout” on page 35 for more information. To search for software items: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Report > File Search. 4 Choose the desired search parameter from the pop-up menu and enter a search term. 5 If you want to customize the report display, do so now. For more information about the report display, see “Changing Report Layout” on page 35 for more information. 6 To search using new data, check Rebuild Data For Report; to search using saved data only, uncheck Rebuild Data For Report.118 Chapter 8 Administering Client Computers 7 Click Search. The newly generated report window appears. Comparing Software Apple Remote Desktop has several specialized reports for comparing software on client computers with software on the administrator computer. These reports can’t be run comparing two client computers. One computer in the comparison must be the administrator computer. Generating a Software Version Report The Software Version report compares application versions on client computers with application versions on the administrator computer. You can select up to 10 applications to compare. Command-line tools and unbundled Java (.jar) applications do not report their version. To generate a Software Version report: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Report > Software Version. 4 Select the software you want to compare, from the application list. You can select up to 10 applications. If the application you want doesn’t appear in the list, click the Add (+) button to browse for the application. 5 To search using new data, check Rebuild Data For Report. 6 Click Generate Report. The newly generated report window appears. Generating a Software Difference Report The Software Difference report compares the applications, fonts, and installed packages of the selected client computers with those on the administrator computer. The resulting report lists the items compared, their version, location, and whether or not they were found on the selected client computers. The Software Difference report can compare all executable Mac OS X and Classic applications. Unbundled Java (.jar) applications and command-line utilities are not included in the report. The report can compare all the fonts in the /System/Library/ Fonts/ and /Library/Fonts/, as well as the Fonts folder for the currently logged in user. Comparing installed packages returns a list of all package receipts in /Library/Receipts/. You can use this report to find out if your clients have the applications or fonts they need. Comparing differences in installed packages can help you troubleshoot software conflicts, and keep your client computers up to date.Chapter 8 Administering Client Computers 119 To generate a Software Difference report: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Report > Software Difference. 4 Select the software type you want to compare. Selecting Applications compares all executable applications. You can limit which folder on the administrator computer Remote Desktop uses to look for applications. Selecting Fonts compares all fonts in /Library/Fonts/, /System/Library/Fonts/, and user font directories. Selecting Installed Packages compares all package receipts in /Library/Receipts/. 5 To search using new data, select Rebuild data for report. 6 Click Generate Report. The newly generated report window appears. Auditing Hardware You can get a report about the hardware of any client computer. Hardware information can be accessed using a number of different reports. Although some basic hardware information can be found in the System Overview report, several more focused hardware reports provide more detailed information. To get a basic System Overview report: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Report > System Overview. 4 Select or deselect hardware items as desired. 5 To search using new data, select Rebuild data for report. 6 Click Get Report. The newly generated report window appears.120 Chapter 8 Administering Client Computers Getting Serial Numbers Although there is no specific serial number report for Apple Remote Desktop, the serial number of any client is in the Computer section of the System Overview Report. In addition to using Apple Remote Desktop to retrieve a computer’s serial number, you could use the command-line tool systemprofiler with Apple Remote Desktop’s Send UNIX Command feature. To generate a serial number report: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Report > System Overview. 4 Select Serial Number from the Computer section. 5 Select or deselect other items as desired. 6 To search using new data, check Rebuild Data For Report. 7 Click Get Report. The newly generated report window appears. Getting Storage Information The Storage report collects information about the client computer’s internal hard disks. It can get information about the hardware itself, the volumes on the disk, file system information, and journaling information for the disk. For a complete listing of Storage report options, see “Report Field Definitions Reference” on page 165. Basic information about hard disk volumes and size can also be found in the storage section of the System Overview report. To generate a Storage report: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Report > Storage. 4 Select the hard disk information desired. 5 To search using new data, select Rebuild Data For Report. 6 Click Get Report. The newly generated report window appears.Chapter 8 Administering Client Computers 121 Getting FireWire Device Information The FireWire Devices report gets information about FireWire devices connected to the client computer. It can get the following information from a device:  Manufacturer  Model  Device speed  Software version  Firmware revision For more information about FireWire Devices report options, see “Report Field Definitions Reference” on page 165. The number of attached FireWire devices can also be found in the Devices section of System Overview report. To generate a FireWire Devices report: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Report > FireWire Devices. 4 Select the FireWire information desired. 5 To search using new data, select Rebuild Data For Report. 6 Click Get Report. The newly generated report window appears. Getting USB Device Information The USB Devices report gets information on Universal Serial Bus devices (scanners, keyboards, mice, and so forth) connected to the client computer. It can get the following information from a device:  Product name and ID  Vendor name and ID  Device speed  Bus power amps For more information about the USB Devices report options, see “Report Field Definitions Reference” on page 165. Basic information about attached USB devices can also be found in the Devices section of the System Overview report.122 Chapter 8 Administering Client Computers To generate a USB Devices report: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Report > USB Devices. 4 Select the USB device information desired. 5 To search using new data, select Rebuild Data For Report. 6 Click Get Report. The newly generated report window appears. Getting Network Interface Information The Network Interfaces report gets information for all network interfaces, including inactive interfaces. It also gets detailed network, output, and Ethernet statistics from client computers. The Network Interfaces report can be used to find network errors or faulty network equipment, troubleshoot network performance, and query the network settings of the client computers. All detailed statistics are refreshed when the client restarts, and address information may change if your client uses DHCP to get a network address. For a complete listing of Network Interfaces report options, see “Report Field Definitions Reference” on page 165. Basic information about network settings can also be found in the Network and AirPort section of the System Overview report. To generate a Network Interfaces report: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Report > Network Interfaces. 4 Select the interface information desired. 5 To search using new data, select Rebuild Data For Report. 6 Click Generate Report. The newly generated report window appears.Chapter 8 Administering Client Computers 123 Getting Memory Information The Memory report gets specific information about the installed memory in a client computer. In addition to reporting how much memory the client has, it shows information about each memory module, including the module’s:  Slot identifier  Size, type, and speed Memory reports can be used for managing computer resources, hardware troubleshooting, or deciding which client computer can handle a memory-intensive application or task. For more information about the Memory report options, see “Report Field Definitions Reference” on page 165. Basic information about system memory can also be found in the Computer section of the System Overview report. To generate a Memory report: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Report > Memory. 4 Select the module information desired. 5 To search using new data, select Rebuild Data For Report. 6 Click Get Report. The newly generated report window appears. Getting PCI Card Information The PCI Cards report gets information about the PCI cards installed in a client computer. It shows information about each PCI card, including each card’s:  Slot name  Card name, type, memory, and revision  Vendor and device IDs  ROM revision For more information about the PCI Cards report options, see “Report Field Definitions Reference” on page 165. Basic information about a client’s PCI cards can also be found in the Computer section of the System Overview report.124 Chapter 8 Administering Client Computers To generate a PCI Cards report: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Report > PCI Cards. 4 Select the PCI card information desired. 5 To search using new data, select Rebuild Data For Report. 6 Click Get Report. The newly generated report window appears. Testing Network Responsiveness Apple Remote Desktop can test network responsiveness between your administrator computer and client computers. It sends network packets to the clients and reports the time taken to receive confirmation from the clients. You can choose how many network packets to send, how often they are sent, and how long the administrator computer waits for a reply before listing a packet as lost. To generate a Network Test report: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Report > Network Test. 4 Select the options you want. Choose the number of packets sent from the Packets pop-up menu (Total Packets to Send). Choose how often to send the send packets from the Interval pop-up menu (Interval Between Packets). Choose how long to wait before reporting a packet as lost from the Time Out pop-up menu (Packet Time Out). 5 Click Get Report. The newly generated report window appears. Evaluating the Network Test Report You can use the Network Test report to diagnose whether task failures in Apple Remote Desktop are due to network congestion or to some other factor. You may, for example, find that a Copy Items task is failing on a particular subnet, due to network congestion on that subnet.Chapter 8 Administering Client Computers 125 Here are some suggestions for evaluating your network performance based on this report:  The number of routers between your computer and another computer can affect the time the packets take to return. When you evaluate the times for a computer, you should compare them to the times for a computer in the same area of the network or with the same number of intervening routers.  If the maximum time for a packet to return from a computer is significantly greater than the time for other computers in the same area of the network, there may be a problem with the computer.  If a single computer has a large number of lost packets, there may be a problem with the network connection to that computer.  If several computers in the same area of the network have a large number of lost packets, there may be a network connection problem or a problem with an intervening router or bridge. Exporting Report Information You can export reports into a comma-delimited or tab-delimited text file. All the columns of information in the report window are included, and the report rows are exported in the order they’re sorted at the time of export. Exported reports can be put into a database, spreadsheet, or word processor for further analysis or organization, or be sent to another administrator. You could even use certain reports as input files for network scanners for Remote Desktop. Alternatively, you could access the report’s SQL database directly with your own SQL query tools or applications. Using standard SQL database queries you can get any or all information out of the report database for use with other applications or databases. To export a report: 1 Generate any report, and bring the report window to the front. 2 If desired, sort the report rows by selecting a new column to sort by. 3 If you do not want to export the entire report, select the rows to be exported. 4 Choose File > Export Window. 5 Name the file, and choose a location to save to. 6 Select a text encoding.  Western (Mac OS Roman): Best choice if the report information uses the Roman alphabet, and the exported document will be opened in an application or on an operating system that does not support Unicode text encoding (for example, some installations of Mac OS 9).  Unicode (UTF-8): Best choice if the exported file will be opened on Mac OS X and contains no Asian language characters (such as Chinese or Japanese).126 Chapter 8 Administering Client Computers  Unicode (UTF-16): Best choice if the report contains Asian language characters. 7 Select a field separator.  Tab: Inserts a Tab character between column values.  Comma: Inserts a comma between column values. 8 If you have selected only some rows of the report and want to export only the selected rows, select Export Selected Items Only. 9 Click Save. Using Report Windows to Work with Computers After you’ve created a report, you can use it to select computers and then do any of the following:  Create new computer lists. Select computers in the report window and select File > New List From Selection.  Generate other reports. Select any number of rows in a report window; then choose another report from the Report menu. The new report will be generated based on the computers in the selected rows.  Initiate any management task. Select any row in a report window; then choose a management task from the Manage menu. This has the same effect as selecting the computer in an Apple Remote Desktop computer list.  Interact with users. Select any row in a report window; then choose a task from the Interact menu. This has the same effect as selecting the computer in an Apple Remote Desktop computer list.  Delete a file from a computer. Select a file in any file or software report window and click the Delete button.  Copy an item to your computer. Select an item in any software report window and click Copy to This Computer.Chapter 8 Administering Client Computers 127 Maintaining Systems Apple Remote Desktop provides easy and powerful tools for maintaining client computers, including tasks such as deleting files, emptying the Trash, and setting computer startup options. Deleting Items If you delete a file from a client computer, it is moved to the client’s Trash. To delete an item from a client: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Report > File Search. 4 Find the software you want to delete, using the File Search report. For more information, see “Finding Files, Folders, and Applications” on page 116. 5 Select the item or items you want to delete in the File Search report window. 6 Click Delete Selected in the report window. 7 Click Delete.128 Chapter 8 Administering Client Computers Emptying the Trash Apple Remote Desktop allows you to empty the Trash on clients to free up disk space. To find out how much free disk space is on a computer, create a System Overview or Storage report using the Report menu. As a part of routine maintenance for client computers, you can free disk space by emptying the Trash. Emptying the Trash completely removes any items you’ve previously deleted on the client. You can use the System Overview report to see how much disk space you can recover by emptying the Trash. To empty the Trash: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Empty Trash. 4 Click Empty. Setting the Startup Disk Apple Remote Desktop can set the startup disk on any client computer. You can choose between a volume on a local hard disk or any available NetBoot volume. The startup disk must have a valid operating system installed on it. To set the startup volume on a local hard disk for multiple computers at once, the local volume name must be the same for all computers. Alternatively, you can set the startup disk to be a NetBoot volume provided by Mac OS X Server. This allows you to start up a number of clients from a NetBoot server. To set the startup disk: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Set Startup Disk. The list that appears shows the client’s local hard disk, a custom NetBoot server item, and a list of all available NetBoot and Network Install servers available on the local network subnet. 4 Choose the client’s local hard disk or a NetBoot server volume. 5 If you want to choose a specific local hard disk volume, select Hard Disk, click Edit, and enter the desired volume name. 6 If you want to choose a custom NetBoot server volume, enter the server IP address or fully qualified domain name, and the NetBoot volume name. 7 If desired, select Restart When Done.Chapter 8 Administering Client Computers 129 If you select Restart When Done, the client computer will restart after having its startup volume set. You need to have Restart privileges to use this option. 8 Click Set. Renaming Computers Apple Remote Desktop can set the name that a client computer uses for file sharing. You can rename multiple computers with the same name followed by a number (such as Computer1, Computer2, and so on). This is especially useful for differentiating client computers after a clean system installation. Note: The Rename Computer feature does not change the Local Hostname or the DNS name of a client computer. To rename a computer: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Rename Computers. 4 Enter the new computer name. 5 If desired, select “Append a unique number for each computer.” Selecting this option appends a unique number to the end of the computer name. For example, if you rename three computers “Computer,” the computers will be named “Computer1,” “Computer2,” and “Computer3.” 6 Click Rename. Synchronizing Computer Time Maintaining synchronized clocks across your clients is essential for management reliability. Synchronized times allow for more precise audits and allow you to accurately correlate events between clients on the network. In addition, many internet services rely on, or benefit from, clock times that are synchronized to a Network Time Protocol (NTP) server. Any scheduled event benefits from synchronized client time. All Mac OS X clients can be set to automatically synchronize their clocks with an NTP server. Mac OS X Server can be configured to act as an NTP server as well. In order to maintain synchronization across your clients, you should choose a single NTP server to synchronize to. Apple provides an NTP server at time.apple.com. Setting computer time requires the use of Apple Remote Desktop’s Send UNIX Command feature and its built-in command-line tool, systemsetup. See “Built-in Command-Line Tools” on page 147 for more information about the tool.130 Chapter 8 Administering Client Computers To synchronize client computer clocks: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Send UNIX Command. 4 Use the provided Templates for Send UNIX Command to set the time server (see “Send UNIX Command Templates” on page 143 for more information). a Select System Setup > Network Time from the Template pop-up menu. b Click Send. c Select System Setup > Network Time Server from the Template pop-up menu. Change the time server from time.apple.com to whichever time server you want, if desired. 5 Alternatively, manually enter the UNIX command. a Type or paste the following UNIX command: systemsetup -setusingnetworktime on -setnetworktimeserver b Set the user permissions for this command to be sent as the user “root.” 6 Click Send. Setting Computer Audio Volume You may want to standardize or otherwise configure the output volume of your computers. You could use this to silence a lab of computers all playing music, or turn up the volume on a single remote computer for a user’s benefit. You can also set the alert volume separately from the output volume and input volume. Additionally you can set “output muted.” Muting the volume causes the computer to remember what the previous volume level was and return to it when the sound is enabled again. Setting computer audio volume requires the use of Apple Remote Desktop’s Send UNIX Command feature, AppleScript, and the command-line tool osascript. See “UNIX Shell Commands” on page 143 for more information. See AppleScript’s StandardAdditions dictionary for information about using this tool. To set a computer’s audio volume: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Send UNIX Command. 4 Use the provided Templates for Send UNIX Command to set the computer volume (see “Send UNIX Command Templates” on page 143 for more information). a Select Miscellaneous > Volume On from the Template pop-up menu. b Set the desired volume level in the Send UNIX Task dialog.Chapter 8 Administering Client Computers 131 5 Alternatively, manually enter the UNIX command. a Type or paste the following UNIX command: osascript -e 'set volume output volume any_number_from_0-100' b or for Mac OS X v.10.3 clients enter or paste the following: osascript -e 'set volume any_number_from_0-7' 6 Click Send. Repairing File Permissions Sometimes a client’s system file permissions can be corrupted or changed from their expected values. In such a case, it may be necessary to manually repair the permissions on the client. Repairing permissions returns system and library files to their default settings. Repairing file permissions requires the use of Apple Remote Desktop’s Send UNIX Command feature, and the command-line tool diskutil. See “UNIX Shell Commands” on page 143 for more information. For information about using this tool, see diskutil’s man page. To repair a computer’s file permissions: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Send UNIX Command. 4 Type or paste the following UNIX command: diskutil repairPermissions / 5 Set the user permissions for this command to be sent as the user “root.” 6 Click Send. Adding Items to the Dock If you install software on your client computers by dragging and dropping, the file, folder, or application isn’t immediately added to the user’s Dock. The instructions provided here are a workaround for clients that are not part of a managed client environment. Note: Dock management is best done in a Mac OS X Server Workgroup Management environment. If you use Mac OS X Server to manage client settings and preferences, the correct place to change the Dock is within the management settings of Workgroup Manager. To add an application or other item to the Dock: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Send UNIX Command.132 Chapter 8 Administering Client Computers 4 Type or paste the following UNIX command (replace /Path_To_Application with your own path to the desired application, and be sure to include the application file extension, .app): defaults write com.apple.dock persistent-apps -array-add 'tiledatafile-data _CFURLString/Path_To_Application _CFURLStringType0 ';killall -HUP Dock Use “persistent-others” instead of “persistent-apps” if the item is anything other than an application. 5 Set the permissions for those of currently logged-in user. 6 Click Send. Changing Energy Saver Preferences You can get and change the settings found in the Energy Saver pane of System Preferences. You can change the computer sleep time, as well as other Energy Saver Options. You can set all the clients to have the same sleep time and even turn on the preference necessary for them to respond to the Apple Remote Desktop Wake command (“Wake for Ethernet network administrator access”). Changing the Energy Saver preferences requires the use of Apple Remote Desktop’s Send UNIX Command, and its built-in systemsetup command-line tool. See “Built-in Command-Line Tools” on page 147 for more detailed information about the systemsetup tool. To change the Energy Saver preferences: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Send UNIX Command. 4 Use the provided Templates for Send UNIX Command to set the energy saver preferences. a Select any one of the following Energy Saver items from the System Setup group:  Restart After Freeze  Restart After Power Failure  System Sleep Time  Display Sleep Time  Wake On Network Access  Wake On Modem Activity b Change the template values to the desired values, and click Send. 5 Alternatively, manually enter the UNIX command.Chapter 8 Administering Client Computers 133 a Type or paste the following UNIX command: systemsetup -setsleep minutes number_of_minutes_to_sleep -setwakeonmodem (on | off) -setwakeonnetworkaccess (on | off) -setrestartpowerfailure (on | off) -setrestartfreeze (on | off) b Set the permissions for this command to root. 6 Click Send. Changing Sharing Preferences for Remote Login Mac OS X’s Sharing System Preference pane allows you to enable or disable SSH login access to the computer. You can use Remote Desktop to change enable or disable a remote computer’s preference. Setting the remote login sharing preference requires the use of Apple Remote Desktop’s built-in command-line tool, systemsetup. See “Built-in Command-Line Tools” on page 147 for more detailed information about the tool. To change the Remote Login sharing preference: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Send UNIX Command. 4 Use the provided Templates for Send UNIX Command to set the Remote Login (SSH) setting (see “Send UNIX Command Templates” on page 143 for more information). a Select System Setup > Remote Login (SSH) from the Template pop-up menu. b Set the login for on or off. 5 Alternatively, manually enter the UNIX command. a Type or paste the following UNIX command: systemsetup -setremotelogin (on | off) b Set the permissions for this command to root. 6 Click Send. Setting Printer Preferences You can set the default printer for your client computers so that they all have the same default and configured printer. There are several ways to set up printer preferences for a client computer. If you have a computer whose printer setup is correct, you can use Remote Desktop to copy the necessary configuration files to the client computers. If you don’t have a configured computer available, you can use the command-line tools in Mac OS X to set the printer preference. Setting the printer preference via Remote Desktop involves using the Copy Items task. See “Copying from Administrator to Clients” on page 108 for more information.134 Chapter 8 Administering Client Computers To set up printer preferences using Copy Items: 1 Set up a client computer’s print preference using the Printer Setup Utility. 2 Use the Copy Items task to copy the following file and folder to all the target computers: /private/etc/cups/printers.conf /private/etc/cups/ppd/ Because these files are hidden in the Finder, you may have to use the Terminal or the Finder’s “Go to Folder” command to add them to the “Items to copy” list. 3 Choose a “Same relative location” as the copy destination. 4 Choose to replace existing items. 5 Click Copy. 6 Restart the client computers’ printer process by restarting the clients. If you are comfortable with the command-line, you can use Remote Desktop’s Send UNIX Command to configure all the client computer preferences at once. Setting printer preferences using Send UNIX Command requires the use of the built-in lpadmin command-line tool. For more information, see the lpadmin man page. To set up printer preferences using Send UNIX Command: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Send UNIX Command. 4 Type or paste the following UNIX command: lpadmin -p printer_name -E -v lpd://printer_and_queue_address -m printer_model_ppd_file -L “text_description_of_printer_location” 5 Set the user permissions for this command to “root.” 6 Click Send.Chapter 8 Administering Client Computers 135 Managing Computers Using Apple Remote Desktop, you can control multiple client computers simultaneously, issuing commands that are found in Mac OS X’s Apple menu (Log Out, Sleep, Restart, etc.), as well as other commands. Opening Files and Folders Apple Remote Desktop can open existing items (files, folders, and applications) on client computers. The item to open must be on the administrator computer, in addition to being on the client computers, and must have the same name, type, size, permissions, and file creation date as the item on the administrator computer. The Open Items command opens files in the application used to create them, if it exists on the client computer, or in the application assigned to open files with that file’s extension. Folders open in the Finder. Applications are opened, or brought to the front, if already open.136 Chapter 8 Administering Client Computers To open an item: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Open Items. 4 Click the Add (+) button and browse for the item on the administrator computer. Alternatively, drag the item from the administrator computer’s Finder to the Open Items dialog. 5 Click Open when the item is selected. The Open Items dialog shows the icon and name of the item to open. 6 Click Open. Opening Applications Apple Remote Desktop can open applications on client computers. The application to open must be on the administrator computer, in addition to being on client computers. If the application is already open, the Open Application command brings it to the front. You can open both Mac OS X and Classic applications with this command. The application on the administrator computer must have the same name, type, and permissions as the one to be opened on the client computer. To open an application: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Open Application. The Open Application dialog shows the applications installed and found in the Applications folder at the top level of the hard disk of the administrator’s computer. 4 Select the application or click the Add (+) button and browse to find the desired application on the administrator computer. Alternatively, drag the item from the administrator computer’s Finder to the Open Application dialog. The Open Application dialog shows the icon and name of the application to open. 5 Click Open.Chapter 8 Administering Client Computers 137 Quitting Applications Without Logging Out the User Apple Remote Desktop can quit running applications on client computers. You can quit both Mac OS X and Classic applications with this command. The administrator must be able to use the Send UNIX Command on the client computer. You can get more information on the killall command by seeing its man page. Note: Unsaved changes to documents on the client will be lost. To quit an open application: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Send UNIX Command. 4 Use the provided Templates for Send UNIX Command to quit an application (see “Send UNIX Command Templates” on page 143 for more information). a Select Miscellaneous > Quit Application from the Template pop-up menu. b Fill in the desired Application Name. 5 Alternatively, manually enter the UNIX command. a Type or paste the following UNIX command: killall “application_name” b Set the user permissions for this command to be sent as the user “root.” 6 Click Send. Putting a Computer to Sleep Apple Remote Desktop can put client computers to sleep. This has the same result as choosing the Sleep command on the client: the display sleeps, the hard disks spin down, and the computer’s central processor and network interface are put in a lowpower mode. Note: Although you can put computers to sleep which are on other network subnets besides your own, and via AirPort, you will not be able to wake them using Remote Desktop. To put a computer to sleep: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Sleep. 4 Click Sleep.138 Chapter 8 Administering Client Computers Waking Up a Computer Apple Remote Desktop can wake up computers that have gone to sleep or been put to sleep with Remote Desktop. To wake a computer using Remote Desktop, the computer’s networking hardware must support waking via network packet (wakeonlan), and the computer must have “Wake For Ethernet Network Administrator Access” enabled in the Wake Options of Energy Saver preferences. You cannot wake up computers connected to the network via AirPort or computers not located on your local subnet. Apple Remote Desktop uses a “wakeonlan” packet to wake sleeping client computers. The packet can only be delivered by way of a local broadcast address, so it only works on a local area network. Also, the network hardware still needs to be powered to receive and act on the packet. AirPort and other wireless network interfaces completely power down on sleep and therefore can’t receive or act on a wakeonlan packet. If you must wake computers on a different subnet, you may want to use a computer on that subnet as a type of sentry. It never sleeps, and runs another licensed copy of Remote Desktop, as well as allows itself to be controlled by your local copy of Remote Desktop. That way you can control the “sentry” computer and instruct it to wake client computers on its local subnet. To wake a computer: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers from the list that show a status as “Sleeping” or offline. 3 Choose Manage > Wake. 4 Click Wake. Locking a Computer Screen Apple Remote Desktop can lock a computer screen. When you lock a computer screen, no one can see the desktop or use the mouse and keyboard on that computer. By default, Apple Remote Desktop displays a picture of a padlock on locked screens, but you can display a custom picture. See “Displaying a Custom Picture on a Locked Screen” on page 139 for more information. You can continue to work with computers using Remote Desktop after you’ve locked their screens.Chapter 8 Administering Client Computers 139 To lock a computer screen: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Interact > Lock Screen. 4 Enter a message to be displayed on the locked screen, if desired. 5 Click Lock Screen. The client screen goes black, except for the administrator’s name, the default picture, and any message text. Displaying a Custom Picture on a Locked Screen You can display a picture of your choice on the client screen while it is locked by Apple Remote Desktop. When creating images, make sure the image size will fit on the client computer’s screen. For example, if you have clients with 800 x 600 screens, a picture that is 1024 x 768 will be scaled down to fit the screen. To create a custom locked screen picture: 1 Create a picture using a graphics program, such as AppleWorks. 2 Save the picture in PICT, TIFF, GIF, JPEG, or any other QuickTime-compatible static image format. QuickTime-compatible movies or QuickTime VR objects cannot be used. 3 Name the picture “Lock Screen Picture”. 4 Copy the “Lock Screen Picture” file to /Library/Preferences/ on the client computer. Unlocking a Computer Screen You must use Apple Remote Desktop to unlock any computer screen locked by Remote Desktop. When you unlock a computer screen, you restore the desktop and use of the mouse and keyboard on that computer. To unlock a computer screen: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers from the list that show a “Locked Screen” status. 3 Choose Interact > Unlock Screen. 4 Click Unlock Screen.140 Chapter 8 Administering Client Computers Disabling a Computer Screen Sometimes you may want to control a client computer with a user at the client computer, but you don’t want the user to see what you’re doing. In such a case, you can disable the client computers screen while preserving your own view of the client computer. This is a special control mode referred to as “curtain mode.” You can change what’s “behind the curtain” and reveal it when the mode is toggled back to the standard control mode. This feature only works with Mac OS X v.10.4 clients. To disable a computer screen while you work: 1 Control a client computer. See “Controlling Apple Remote Desktop Clients” on page 78 or “Controlling VNC Servers” on page 82 for detailed information. 2 Click the Lock Computer Screen While You Control button in the control window toolbar. Alternatively, if you are not currently in a Control window and have added the “Control Computer in Curtain Mode” button to your toolbar, click that toolbar icon. You can also select Interact > Curtain. Logging In a User at the Login Window Apple Remote Desktop can log in any user on a client computer by using AppleScript System Events and the Send UNIX Command feature. Using these powerful features you can log in any number of client computers to the same user name simultaneously from the login window. This script is for use on computers at the login screen only. To log in a user: This method uses the osascript command. For detailed information on osascript, see the osascript man page. 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Send UNIX Command. 4 Type the following AppleScript in the UNIX Command window, adding the user name and password: osascript <" keystroke tab delay 0.5 keystroke "" delay 0.5 Chapter 8 Administering Client Computers 141 keystroke return end tell EndOfMyScript 5 Choose user “root” to run the command. 6 Click Send. The client computer executes the script. Logging Out the Current User Apple Remote Desktop can log out the current user on a client computer. Other users, besides the current active user, who are logged in using Fast User Switching are not logged out using this command. Using this command returns the client computer to the login window. Unsaved work will stop the logout process. To log out a user: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Log Out Current User. 4 Click Log Out. Restarting a Computer Apple Remote Desktop can restart a client computer. This has the same result as choosing the Restart command from the client computer’s Apple menu. This feature is especially useful when used with the Install Packages command. Install Packages doesn’t restart the computer, even if the package requires it. You can restart the computer using Remote Desktop after installing a package. To restart a computer: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Restart. 4 Select the type of restart. You can allow users to save files or cancel the restart, or you can force an immediate restart, which will cause the users to lose unsaved changes to any open files. 5 Click Restart.142 Chapter 8 Administering Client Computers Shutting Down a Computer Apple Remote Desktop can shut down a client computer. This has the same result as choosing the Shut Down command from the client computer’s Apple menu. Note: If you shut down an Apple Remote Desktop client, you cannot start it up using Remote Desktop. This command is especially useful when used with Energy Saver preferences. You can set your client computers to start up every morning at a designated time and use Remote Desktop to shut them down at night. The next morning, they will start up and be ready to administer. To shut down a computer: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Shut Down. 4 Select the type of shutdown. You can choose to allow users to save files or cancel the shutdown, or you can force an immediate shutdown, which will cause the users to lose unsaved changes to any open files. 5 Click Shut Down.Chapter 8 Administering Client Computers 143 UNIX Shell Commands In addition to its own tasks, Apple Remote Desktop provides a way to easily execute UNIX commands on client computers. In order to send UNIX commands to the client computers, the client computers must have the BSD subsystem installed. The UNIX commands are shell command, which means you can write a script with conditionals, loops, and other functions of the shell, and not just send a single command. Send UNIX Command Templates Remote Desktop has a few built-in UNIX shell command templates for use with Send UNIX Command. In the Send UNIX Command task configuration dialog, you can select any one of the commands from the Templates pop-up menu. Selecting a template pastes a generic script into the UNIX command field. All you have to do is customize the script to your situation. For example, if you want to set a manual IP address for a client computer, you would select the Manual IP template from the Template > Network Setup pop-up menu, replace the placeholder indicated in the pasted-in UNIX command with the real IP address, and send the command. You are free to make as many templates as your want from either existing templates or from scratch. Once saved, a template can be made the task’s default, with all new instances of the task opening with the default template settings.144 Chapter 8 Administering Client Computers For more information about Task Templates, see “Creating and Using Task Templates” on page 100. The built-in Send UNIX Command templates include: Template sub-menu Template name Network Setup  List All Services  Manual IP  DHCP  BOOTP  Manual with DHCP Router  DNS Servers  Search Domains  Web Proxy System Setup  Allow Power Button To Sleep  Bonjour Name  Current Date  Current Time  Time Zone  Network Time  Network Time Server  Remote Apple Events  Remote Login (SSH)  Restart After Freeze  Restart After Power Failure  System Sleep Time  Display Sleep Time  Hard Disk Sleep Time  Delay After Power Failure  Wake On Modem Activity  Wake On Network Access Miscellaneous  Login User  Quit Application  Volume Off  Volume On  List Required Software Updates  Install Required Software Updates  Repair Disk Permissions  Computer Uptime  Free Swap Space  Top UsersChapter 8 Administering Client Computers 145 Executing a Single UNIX Command Using the UNIX Command window, you can send a single command to the selected client computers. The command is executed using the bash shell. To execute a single UNIX command: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Send UNIX Command. 4 Type or paste the command. If your command is a multi-line script, enter each command on its own line. If you want to break up a single-line command for better readability, use a backslash (\) to begin a new line. 5 Set the permissions used to execute the command. You can choose the currently logged-in user, or choose the name of another user on the client computers. 6 Click Send. Executing Scripts Using Send UNIX Command There are two kinds of scripts you can execute via the command line. First, and most common with command lines, is a shell script. A shell script is a file containing a collection of UNIX commands that are all executed in sequence. Shell scripts can have normal programming procedures like loops, conditionals, and variables. Shell scripts are text files with UNIX line endings. Shell scripts are interpreted using the bash shell. The second kind of script you can execute, and the most common in the Mac OS X environment, is an AppleScript. AppleScripts are files that contain English-like commands, using the AppleScript programming language and they are created using the Script Editor application. Running a UNIX command as the current user will fail if the target computer is at the login window, since there is no current user at that point. You can use root user for tasks by entering root in the specified user field of the task dialog. You don’t actually need to have the root account enabled on the client computer to specify the root user. You should never use sudo or su to do tasks as the root user. They are interactive and expect further input and response from your script. Instead, run your script as root or whatever user you were planning on. Executing Shell Scripts with Remote Desktop Shell scripts can be copied, then executed. If a script has any degree of complexity, or if it cannot be expressed on a single line, you can use Copy Items to copy the script file to the client computers, then execute it using Send UNIX Command. To send a single-line command you can simply use Send UNIX Command.146 Chapter 8 Administering Client Computers To copy and execute a script: 1 Prepare and save your script. Make sure your script is saved as plain text with UNIX line breaks. 2 Open Remote Desktop. 3 Select a computer list in the Remote Desktop window. 4 Select one or more computers in the selected computer list. 5 Use the Copy Items command to copy your script to the client computers. See “Copy Options” on page 107 and “Copying from Administrator to Clients” on page 108 for more information. 6 After copying the script, choose Manage > Send UNIX Command. 7 Execute the script by typing: sh script pathname 8 Click Send. Executing AppleScripts with Remote Desktop AppleScripts can be executed on client computers in two ways. They can be saved and executed as an application, or sent at once using the command line. To learn more about AppleScript, see AppleScript Help in Help Viewer or go to: www.apple.com/applescript/. To send and execute an AppleScript: 1 Save the AppleScript as an application. 2 Open Remote Desktop. 3 Select a computer list in the Remote Desktop window. 4 Select one or more computers in the selected computer list. 5 Use the Copy Items command with the Open Items option selected in the Copy Items dialog. See “Copy Options” on page 107 for more information. To execute an AppleScript using the Send UNIX Command: This method uses the osascript command. See the osascript man page for more information. 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Send UNIX Command. 4 Type or paste the AppleScript in the UNIX Command window, like this: osascript -e 'First line of script' -e 'Next line of script' [ -e ... ]Chapter 8 Administering Client Computers 147 Alternatively, you could use a UNIX “read standard input” redirection which looks like: osascript < value must be a multiple of 30 seconds. Example: systemsetup - setWaitForStartupAfterPowerFailure 30 -setwakeonmodem ( on | off ) Use this command to specify whether or not the server will wake from sleep when modem activity is detected. Example: systemsetup -setwakeonmodem on -setwakeonnetworkaccess ( on | off ) Use this command to specify whether the server wakes from sleep when a network admin packet is sent to it. Example: systemsetup -setwakeonnetworkaccess on Flag DescriptionChapter 8 Administering Client Computers 151 Any command in the Mac OS X Server command-line guide that uses systemsetup can be used in Remote Desktop using the Send UNIX Command task. Using kickstart The kickstart command-line utility is embedded within the Apple Remote Desktop client software. It allows you to install, uninstall, activate, configure, and restart components of Apple Remote Desktop without restarting the computer. You can configure all the features found in the Remote Desktop section of the Sharing System Preferences. The kickstart utility can be used via SSH to configure remote computers, including Xserves. The kickstart utility is located at: /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/ Resources/kickstart. The syntax and list of actions possible with kickstart are available by running kickstart as follows: $sudo /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/ Resources/kickstart -help If you are running the kickstart utility through Apple Remote Desktop’sSend UNIX Command function, you don’t need the full path, just the name kickstart and root as the command’s user. You can use the sudo command with an administrator account to use the kickstart utility, or you can use the root user via Send UNIX Command. All commands presented in this section should be typed as one line of text. It’s OK if the text wraps as you enter it; just be sure not to enter return characters. The following are some examples of actions possible with kickstart:  Activate Remote Desktop sharing, enable access privileges for all users, and restart the Apple Remote Desktop Agent: $ sudo /System/Library/CoreServices/RemoteManagement/ARDAgent.app/ Contents/Resources/kickstart -activate -configure -access -on -restart -agent -privs -all  Activate Remote Desktop sharing, enable access privileges for the users “admin”, grant full privileges for the users “admin,” and restart the Apple Remote Desktop Agent and Menu item: $ sudo /System/Library/CoreServices/RemoteManagement/ARDAgent.app/ Contents/Resources/kickstart -activate -configure -access -on -users admin -privs -all -restart -agent -menu  Activate Remote Desktop sharing, and disable access privileges for all users: $ sudo /System/Library/CoreServices/RemoteManagement/ARDAgent.app/ Contents/Resources/kickstart -activate -configure -access -off  Shut down the Apple Remote Desktop Agent process: $ sudo /System/Library/CoreServices/RemoteManagement/ARDAgent.app/ Contents/Resources/kickstart -agent -stop152 Chapter 8 Administering Client Computers  Deactivate Remote Desktop access for a computer: $ sudo /System/Library/CoreServices/RemoteManagement/ARDAgent.app/ Contents/Resources/kickstart -deactivate -configure -access -off Automating Functions You can automate any command or function in Remote Desktop. Additionally, Remote Desktop supports scripting (either UNIX or AppleScript) to help automate their client management. Setting the Client’s Data Reporting Policy To speed up reporting and allow reporting from offline clients, Apple Remote Desktop uses saved client system and file information. You can automate the collection of this information by setting the data reporting policy. This schedule determines how often the client updates its system and file information for reports. In accordance with the collection schedule you set, each client computer connects to a central reporting database and uploads the information you designate. There are certain trade-offs to the frequency of these updates. If you require all the clients to update their information too often, you run the risk of added network traffic and slower client performance during updates. If you don’t require the clients to update often enough, the report data that you receive may be out of date. You should take care to balance your reporting needs and your network and client performance needs. The collection policy includes four kinds of information: system data, file data, user accounting data, and application usage data. System data includes all possible reported information for the following reports:  System Overview  Storage  USB Devices  FireWire Devices  Memory  PCI Cards  Network Interfaces The file data includes all possible reported information for the following reports:  File Search  Software Version  Software DifferenceChapter 8 Administering Client Computers 153 The user accounting data includes all possible reported information for the following report:  User History The application usage data includes all possible reported information for the following report:  Application Usage To set a client’s data reporting policy: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose File > Get Info. 4 If you have selected only one computer, select the Data Settings tab, and click the Edit button. If you have selected more than one computer, this tab is already selected. 5 Select “Upload on a schedule.” To disable a client’s automatic data collection, deselect “Upload on a schedule.” 6 If you have already made a default schedule, you can use it by clicking “Use default schedule” to automatically fill in the appropriate information and click Done. Otherwise, choose the day or days the data collection should occur. For more information about setting a default schedule, see “Creating a Template Data Reporting Policy” on page 153. 7 Set the time at which the collection occurs. 8 Choose which data types to upload: System Data, File Search Data, Application Usage Data or User Accounting Data, or any combination. 9 In order to upload Application Usage Data and User Accounting Data, you need to specify collection of that data. Choose Collect Application Usage Data to tell a client computer to save report information for the Application Usage Report. Choose User Accounting Data to tell a client computer to save report information for the User History Report. 10 Click Apply. Creating a Template Data Reporting Policy To speed up client configuration for data reporting, you can set a default time and frequency of report data collection. This template must be applied to any computer or group of computers that you want to use it. Afterwards, the setting can be customized on a per-computer or group basis.154 Chapter 8 Administering Client Computers To set the default data reporting policy template: 1 Choose Remote Desktop > Preferences. 2 Select Task Server. 3 Check which additional data types the clients will collect: Application Usage Data, User Accounting Data, or both. 4 Check “Upload report data to the Task Server on a schedule.” 5 Click Change Schedule. 6 Choose the day or days the data collection should occur. 7 Set the time at which the collection should occur. 8 Choose which data types to upload: “System Data,” “File Search Data,” “Application Usage Data,” “User Accounting Data,” or any combination. 9 Click OK. Designating the Task Server and Setting the Report Data Collection Location To speed up reporting, Apple Remote Desktop uses a database of client system and file information. You can automate the collection of this data for reports, and determine where the database will reside. By default, the database is stored on the administrator computer. Use these instructions to change the data collection location. First, determine where the data will be located: on the administrator computer, or a remote computer (called a Task Server). A Task Server needs to be an unlimited-client licensed Apple Remote Desktop administrator computer and have TCP and UDP ports 3283 open to all of the reporting client computers (and TCP port 5900 open, if you want to control the clients). If you choose to use another Apple Remote Desktop administrator computer’s database, you must configure it to allow data access to other Apple Remote Desktop administrators. The default Task Server is the computer upon which you installed Remote Desktop. See also “Using a Task Server for Report Data Collection” on page 112. If you choose to store the data locally and you have an unlimited client license, you can allow other Apple Remote Desktop administrators with unlimited-managed computer licenses to access the database on your computer by selecting the “Allow remote connections to this server” option. Warning: If you change the location of the report database from the one selected in the initial setup, you will need to reset the collection policies for the client computers. The database will not be moved, but will be regenerated at the next collection interval.Chapter 8 Administering Client Computers 155 To set the Task Server location: 1 Open Remote Desktop. 2 Choose Remote Desktop > Preferences. 3 Click Task Server. 4 If you want to use the database on this administrator computer, select “Use Task Server on this computer.” 5 If you use your Remote Desktop administration computer as a Task Server on the local administrator computer, click “Allow remote connections to this server.” 6 If you want to use a database on another administrator computer, select “Use remote Task Server.” Then, enter the IP address or fully qualified domain name of the other Apple Remote Desktop administrator computer, and click Select. 7 Close the window to save changes. Scheduled Tasks You can use Apple Remote Desktop to automate and schedule almost any task. For example, you can make sure a particular application or a specific set of fonts is always available on a client computer by setting Remote Desktop to copy applications and fonts to the client every night. When you schedule an automated task, information about the scheduled task is saved on the administrator computer. At the appointed time, the client software on that computer activates and initiates the task. Remote Desktop must be open to perform a scheduled task. Setting Scheduled Tasks Any task with the Schedule Task button in the task configuration window can be scheduled. Tasks that you have scheduled appear on the left in the main Remote Desktop window. To schedule a task: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose the task you want to schedule from the menu bar. 4 Configure the task as needed. 5 Before executing the task, click the Schedule button. The scheduling information is revealed. 6 Choose when and how often you want the task to execute. 7 If you want the task to repeat, click Repeating Every then set the repeat interval.156 Chapter 8 Administering Client Computers 8 Click OK. 9 Save the task and choose where the task will appear in the Remote Desktop window. Editing Scheduled Tasks Once saved, a task can be changed and all future executions of the task will reflect the changes. You may want to edit which computers are affected by the task or any other task parameter. To edit a task schedule: 1 Double-click a scheduled task in the Remote Desktop window. 2 Edit the task, as needed. 3 Click the Schedule Task button. 4 Edit the task schedule, as needed. 5 Click OK. 6 Click Save. Deleting Scheduled Tasks Unneeded tasks can be deleted. If you want to keep the task, but stop it from repeating, you should edit the scheduled task instead of deleting it. See “Editing Scheduled Tasks” for more information. To delete a scheduled task: 1 Select the saved task in the Remote Desktop window. 2 Press the Delete key. 3 Click Delete. Using AppleScript with Remote Desktop AppleScript is a powerful and versatile scripting language that is built into Mac OS X. You can use AppleScript to create shortcuts, automate repetitive tasks, or even make custom applications that save you a great amount of time. AppleScript is an Englishlike language you can use to write scripts that contain commands. Scripts can make decisions based on user interaction, or by parsing and analyzing data, documents, or situations. Remote Desktop is scriptable, as are many other Mac OS X applications, and it can be controlled with AppleScript commands. AppleScript is a complete language with conditional statements, comparison and arithmetic operations, and the ability to store variables. This documentation doesn’t teach AppleScript language syntax or programming practices. For information about learning how to program with AppleScript, see the AppleScript online help. This section provides a brief description of AppleScript, a brief discussion of using the Remote Desktop AppleScript Dictionary, and a sample script.Chapter 8 Administering Client Computers 157 Remote Desktop’s AppleScript Basics AppleScript scripts consist of commands that are sent to objects. Objects can be a wide variety of things, including applications, scripts, windows, settings, or the Finder. These objects can receive a specific set of commands and respond with the desired actions. Essentially, a script tells an application (Remote Desktop in this case) to either complete a certain task or retrieve information. You can give the script decision-making capabilities by using conditional statements; you can give the script a memory by defining variables. Remote Desktop has made all of its fundamental functions scriptable. The tasks that you perform as an administrator by pointing and clicking the mouse can all be accomplished by running an AppleScript. For example, you can:  Get information on or rename a computer  Add computers to a list  Copy or install items  Execute a report task Using the Remote Desktop AppleScript Dictionary Each scriptable application contains an AppleScript dictionary—the list of objects and messages that an application can understand. For example, in Remote Desktop’s dictionary there is an object named “computer list” that has this entry: A “computer list” is an object which contains other objects (“computers” in this case) and has properties like its “id” and its “name.” When queried, this object can return the values for the properties (in Unicode text as indicated), but you can’t change “id” from within the script (it’s labeled r/o for read-only). This object can be acted upon by the “verbs,” or messages, in a script. The dictionary also contains “verbs,” or messages. These verbs are commands that act on the objects in the dictionary. For example, in Remote Desktop’s dictionary there is a verb named “add,” and this is its entry: computer list n [inh. item] : A list which holds computers. ELEMENTS contains computers; contained by application. PROPERTIES id (Unicode text, r/o) : The unique identifier (UUID) of the computer list. name (Unicode text) : The name of the computer list. add v : Add a computer to a task. add computer : The computer. to computer list : The computer list (or task) to add the computer to.158 Chapter 8 Administering Client Computers This entry tells you what the verb can act on and how. This entry says that Remote Desktop can add a specified computer to a computer list. The objects “computer” and “computer list” are being acted upon by “add.” To access the full AppleScript dictionary for Remote Desktop: 1 Launch Script Editor in the /Applications/AppleScript/ folder. 2 Select File > Open Dictionary. 3 Choose Remote Desktop. 4 Click Open. The AppleScript Dictionary for Remote Desktop is also available in Appendix C, “AppleScript Remote Desktop Suite.” Sample AppleScript This AppleScript is one that could be used to do a quick cleanup of a group of computers. First, it locks the computer screens to prevent interference. Second, it deletes all items left on the currently active desktops of the client computers. Finally, it finishes by emptying the clients’ trash and unlocking the screens. This script is for educational use only and no warranty is explicit or implied as to the suitability of this script for your computing environment. Additionally, this sample script deletes items on the target computers. Use at your own risk. -- Start commanding the local copy of Remote Desktop tell application "Remote Desktop" -- decide which list to perform this on, in this case it's called "Classroom" set these_computers to computer list "Classroom" -- decide what locked screen text you want displayed set screen_message to "Please wait" as Unicode text -- make a UNIX script which executes an AppleScript on the remote computers set the UNIX_script to "osascript -e 'tell application \"Finder\" to delete every item of the desktop whose class is not disk'" -- set the lock task parameters set lock_task to make new lock screen task with properties {name:”Lock Classroom”, message:screen_message} -- perform the task execute lock_task on these_computers -- set the UNIX script parameters set clean_task to make new send unix command task with properties {name:”Clean Desktop”, showing output:false, script:UNIX_script}Chapter 8 Administering Client Computers 159 -- perform the task execute clean_task on these_computers -- empty the trash afterward execute (make new empty trash task) on these_computers -- unlock the screen when finished execute (make new unlock screen task) on these_computers end tell Using Automator with Remote Desktop Accomplish all of your time-consuming, repetitive manual tasks quickly, efficiently, and effortlessly with Automator workflows. It’s simple to create custom workflows just by dragging items, pointing, and clicking. You can easily automate Remote Desktop tasks such as Lock Screen or Install Packages, then repeat those tasks again and again. Simple and easy-to-understand application actions are the building blocks, so you don’t have to write any code. Each actions has all of the options and settings available to you. Here’s the sample AppleScript above, but done using Automator:160 Chapter 8 Administering Client Computers Using Automator actions, you can even create your own interfaces to Apple Remote Desktop functions without having to give users access to Remote Desktop. For instance, say you wanted to give all your teachers a tool to lock and unlock screens in their classrooms. You still need to configure Remote Desktop and set up computer lists, but instead of giving the teachers all access to Remote Desktop, you can create an Automator plug-in or application. This plug-in lets them select only the computers in their classroom, and the plug-in does the rest of the work for them. You can create an Automator workflow, application, Finder plug-in, or iCal alarm similar to the AppleScript mentioned above. By stringing together Remote Desktop actions in Automator, you accomplish the same work as an AppleScript, but without having to write code. 161 A Appendix A Icon and Port Reference The following tables illustrate some of the icons found in the main window of Remote Desktop. The final table shows which network port numbers are in use by Apple Remote Desktop. Client Status Icons The following icons appear next to the names of computers in a scanner search results list. The icons show the status of each computer in the list. Apple Remote Desktop Status Icons The Apple Remote Desktop status icon appears in the menu bar of each Apple Remote Desktop client. The status icon has several states, depending on the status of the client computer. Icon What it means Accessible to Apple Remote Desktop Offline Apple Remote Desktop client Ping response at IP address, but no Apple Remote Desktop client response Icon What it means Not Active Apple Remote Desktop is installed but is not currently running on the client computer. Ready Apple Remote Desktop is installed and running on the client. Administered Apple Remote Desktop is installed and running on the client computer, the administrator is actively observing or controlling, and the client is set to indicate when it is being observed.162 Appendix A Icon and Port Reference List Menu Icons The following icons are used in the Apple Remote Desktop list area of Remote Desktop’s main window. Task Status Icons The following icons are used in task list areas of Remote Desktop’s main window. Icon What it means Master list Apple Remote Desktop list Smart list Scanner Active Task list Task History list Task Server queue Icon What it means Running Finished successfully Exited with error Incomplete Queued ScheduledAppendix A Icon and Port Reference 163 System Status Icons (Basic) The following icons are shown as initial high-level status indicators for observed client computers. System Status Icons (Detailed) The following icons are shown after further inspection of observed client computer status indicators. Icon Indicates or One or more service statistic is red. This takes precedence over any yellow or green indicator. or One or more service statistic is yellow This takes precedence over any green indicator Service is operating within established parameters. No service informaiton available. Service Icon Status CPU Usage Usage is at 60% or less Usage is between 60% to 85% Usage is at 85% or higher No status information is available DIsk Usage Usage is at 90% or less Usage is between 90% and 95% Usage is at 95% or higher No status information is available Free Memory Less than 80% used Between 80% and 95% used164 Appendix A Icon and Port Reference TCP and UDP Port Reference Apple Remote Desktop uses the following TCP and UDP ports for the functions indicated. Over 95% used No status information is available Service Icon Status Port Protocol Function 5900 TCP Observe and Control 5900 UDP Send screen, share screen 3283 TCP Reporting 3283 UDP Everything else 22 TCP Encrypted file transfer, observe, and control (via SSH tunnel) 165 B Appendix B Report Field Definitions Reference The following sections describe the available fields in some of the Apple Remote Desktop reports. For information on generating reports, see “Creating Reports” on page 111. The file search reports (File Search, Software Version, and Software Difference) are not included because their fields closely match those already found in the Finder. System Overview Report List category Field name Notes or example AirPort AirPort Active Yes/No AirPort Firmware Version Version number AirPort Hardware Address 00:30:65:01:79:EC AirPort Locale AirPort Type AirPort Installed Yes/No AirPort Network Channel Channel number 1-11 AirPort Network Name Network name AppleTalk AppleTalk Active Yes/No AppleTalk Network AppleTalk Node AppleTalk Zone Computer Active Processors Number of processors Available user memory Memory in KB Boot ROM ROM version number Bus Clock Speed In MHz Bus Data Size CPU Speed In MHz Serial number 166 Appendix B Report Field Definitions Reference Velocity Engine Yes/No L2 Cache Size In KB L3 Cache Size In KB Machine Model Memory In KB Empty RAM Slots PCI slots Used Processor Count CPU Type Internal value Sales Order Number VM Size Total RAM Slots Devices ATA Device Count Firewire Device Count Keyboard Connected Mouse Connected Optical Drive Type SCSI Device Count USB Device Count Display 2nd Monitor Depth In bits 2nd Monitor Type 2nd Monitor Resolution Pixels horizontal and vertical Monitor Depth In bits Monitor Type Monitor Resolution Pixels horizontal and vertical Modem Modem Country Modem Driver Modem Firmware Version Modem Installed Yes/No Modem Interface Modem Model Network First Ethernet Address en0 MAC address NetBooted Yes/No Primary IP Address Primary Network Collisions Primary Network Flags List category Field name Notes or exampleAppendix B Report Field Definitions Reference 167 Primary Network Hardware Address Primary Network Input Errors Primary Network Input Packets Primary Network Output Errors Primary Network Output Packets Primary Network Preferences Sleep Display Yes/No Sleep Hard Disk Yes/No Sleep Computer Yes/No Wake for Ethernet Access Yes/No Printing Printer Name Printer Sharing Yes/No Printer Type Printer Version Remote Desktop Computer Info #1 Computer Info #2 Computer Info #3 Computer Info #4 Sharing Computer Name File sharing name, “Bob’s Computer” FTP Access Yes/No Remote AppleEvents Yes/No Remote Login Yes/No UNIX hostname foo.example.com Web Sharing Yes/No Windows Sharing Yes/No Software Kernel Version System Version Mac OS X v10.4.2 (8C46) Storage Free Disk Space In KB, MB, or GB Total Disk Space In KB, MB, or GB Trash Size In KB, MB, or GB List category Field name Notes or example168 Appendix B Report Field Definitions Reference Storage Report List category Field name Notes or example Hardware Options Drive Manufacturer Drive Model Drive Revision Drive Protocol Removable Yes/No Serial Number Logical Unit Number Detachable Volume Options Creation date UNIX GMT format Disk Name Macintosh HD File Count Folder Count Total Disk Space Free Space In KB, MB, or GB Startup Disk UNIX Mount Point /dev/disk0s10 File System Options Disk Format HFS, HFS+, UFS Owner Group Yes/No Permission Modes Permissions Yes/No Write Access Modification date UNIX GMT format Case Sensitive Yes/No Preserves Case Yes/No Backup Options Journaling Capable Yes/No Journaled Yes/No Last Backup date UNIX GMT format Last Check date UNIX GMT formatAppendix B Report Field Definitions Reference 169 USB Devices Report FireWire Devices Report Memory Report PCI Cards Report Field name Notes or example Product Name Product ID Vendor ID Vendor Name Device Speed 1.5Mb, 12Mb Bus Power In mA Date collected Field name Notes or example Device Speed 200, 400, 800 Mbits per second Software Version Manufacturer Model Firmware Revision Date collected Field name Notes or example Slot Identifier DIMM0/J21 Size In MB Speed PC133-222 (Mac OS X 10.3 only) Type SDRAM Date collected Field name Notes or example Card Name Slot Name Slot4 Card Type Display Vendor ID Device ID170 Appendix B Report Field Definitions Reference Network Interfaces Report ROM Revision Displays only Card Revision Card Memory Displays only Date collected Field name Notes or example List category Field name Notes or example Network Overview Name Location name Active Yes/No Primary Yes/No Configured With Ethernet Hardware Address 00:30:65:01:79:EC Interface Name en0 Flags Active Interface Domain example.com Router Address IP Address Broadcast Address DNS Server Subnet Mask IP Addresses Broadcast Addresses DNS Servers Subnet Masks Network Statistics Network Collisions Network Input Errors Network Input Packets Network Output Errors Network Output Packets Output Statistics Output Queue Capacity Output Queue Size Output Queue Peak Size Output Queue Drop Count Output Queue Output Count Output Queue Retry CountAppendix B Report Field Definitions Reference 171 Output Queue Stall Count Ethernet Statistics Ethernet Alignment Errors Ethernet FCS Errors Frame Check Sequence errors Ethernet Single Collision Frames Ethernet Multiple Collision Frames Ethernet SQE Test Errors “heartbeat” test errors Ethernet Deferred Transmissions Ethernet Late Collisions Ethernet Excessive Collisions Ethernet Internal MACTransmit Errors Ethernet Carrier Sense Errors Ethernet Frame Too Long Ethernet Internal Mac Receive Errors Ethernet Chip Set Ethernet Missed Frames Ethernet Receiver Overruns Ethernet Receiver Watchdog Timeouts Ethernet Receiver Frame Too Short Ethernet Receiver Collision Errors Ethernet Receiver PHY Errors Ethernet Receiver Timeouts Ethernet Receiver Interrupts Ethernet Receiver Resets Ethernet Receiver Resource Errors Ethernet Transmitter Underruns Ethernet Transmitter Jabber Events Ethernet Transmitter PHY Errors Physical Errors Ethernet Transmitter Timeouts Ethernet Transmitter Interrupts Ethernet Transmitter Resets List category Field name Notes or example172 Appendix B Report Field Definitions Reference Network Test Report Administration Settings Report Ethernet Transmitter Resource Errors Ethernet Collision Frequencies List category Field name Notes or example Field name Notes or example Computer Computer sharing name Min,. Time Shortest time for ping response Max. TIme Longest time for a ping response Avg. Time Average time for ping response Lost Packets Number of pings without a response Total Packets Number of pings sent. List category Field name Notes or example Computer Computer sharing name Privileges Generate Reports On or off Send Messages On or off Open & Quit On or off Restart & Shutdown On or off Change Settings On or off Copy Items On or off Delete Items On or off Control On or off Observe On or off Show Observe On or off Data Settings Collect Application Usage Data On or off Collect User Accounting Data On or off Upload Schedule Time and days to upload information Upload System Data On or off Upload File Data On or off Upload Application Usage Data On or off Upload User Accounting Data On or offAppendix B Report Field Definitions Reference 173 Application Usage Report User History Report General Version Apple Remote Desktop version and build number Last Contacted Relative date List category Field name Notes or example Field name Notes or example Computer name File sharing computer name Name Application name Launch date 24 hour local time and date Total run time Length of time the application was running Frontmost Length of time the application was the frontmost application User name Short user name of application process owner State What the application is doing now (running, terminated, etc.) Field name Notes or example Computer name file sharing computer name User name Login type) Console, tty, ssh Login time Date and 24 hour format local time Logout time Date 24 hour format local time Remote Login Host Originating host to the login session, localhost, or some remote computer174 C Appendix C AppleScript Remote Desktop Suite This appendix shows the contents of Remote Desktop’s AppleScript Dictionary. This appendix is not a substitute for the AppleScript Dictionary view in Script Editor. It is included as a quick reference so that AppleScript commands might be found by a search of PDF contents. The Dictionary itself has the most recent information about scriptable objects and events in Remote Desktop, and better usability. Classes and Commands for the Remote Desktop Application. add v: Add a computer to a task. add computer: The computer. to computer list: The computer list (or task) to add the computer to. control v: Start a control session with the computer. control computer: The computer to control. execute v: Executes a task. execute task: The task to execute. [on computer list]: The computer list (or computer) on which to run the task. observe v: Start an observation session. observe item: The computer, list, or computer list to observe. release v: Release computers from a control or observation session. release item: The computer, list, or computer list to release. remove v: Remove a computer from a task. remove computer: The computer to remove. from computer list: The computer list (or task) to remove the computer from. stop v: Stops an executing share screen task. stop task: The task to stop.Appendix C AppleScript Remote Desktop Suite 175 application n [inh. application; see also Standard Suite]: Remote Desktop’s top level scripting object. ELEMENTS contains computers, computer lists, copy items tasks, copy to me tasks, documents, empty trash tasks, install package tasks, lock screen tasks, logout tasks, open application tasks, open item tasks, rename computer tasks, restart tasks, send message tasks, send unix command tasks, set local startup disk tasks, set network startup disk tasks, share screen tasks, shutdown tasks, sleep tasks, unlock screen tasks, upgrade client tasks, wake up tasks, windows. PROPERTIES selection (item, r/o): The current selection. computer n [inh. item]: A physical computer. ELEMENTS contained by application, computer lists. PROPERTIES boot volume (Unicode text, r/o): The boot volume of the computer. CPU (Unicode text, r/o): The CPU type of the computer. current application (Unicode text, r/o): The current frontmost application on the computer. current user (Unicode text, r/o): The currently logged in user on the computer. DNS name (Unicode text, r/o): The DNS name of the computer. id (Unicode text, r/o): The unique identifier (UUID) of the computer. Internet address (Unicode text, r/o): The Internet address of the computer. last activity (date, r/o): The time of the most recent activity on the computer. last contacted (date, r/o): The time of last contact with the computer. machine model (Unicode text, r/o): The model of the computer. name (Unicode text, r/o): The name of the computer. physical memory (Unicode text, r/o): The physical ram installed in the computer. primary Ethernet address (Unicode text, r/o): The primary ethernet address of the computer. remote desktop version (Unicode text, r/o): The version of the Remote Desktop client running on the computer. status message (Unicode text, r/o): The current status of the computer. system version (Unicode text, r/o): The Mac OS version running on the computer. computer list n [inh. item]: A list which holds computers. ELEMENTS contains computers; contained by application. PROPERTIES id (Unicode text, r/o): The unique identifier (UUID) of the computer list. name (Unicode text): The name of the computer list.176 Appendix C AppleScript Remote Desktop Suite copy items task n [inh. task > item]: Copy items to the target computers. ELEMENTS contained by application. PROPERTIES bandwidth limit (integer): Network usage limit in kilobytes per second (0 = unlimited). conflict resolution (ask what to do/rename the existing item/rename the item being copied/replace/replace if older): Specifies what to do if the item(s) already exist in this location. copy items (list): A list of files and/or folders to copy. destination group (Unicode text): If ownership is set to a ‘specific owner’, a valid group name on the destination computer. destination owner (Unicode text): If ownership is set to a ‘specific owner’, a valid user name on the destination computer. destination path (alias): If the location is ‘specific folder’, a fully specified path to the destination folder. encrypting (boolean): Should the items be encrypted during copying location (applications folder/current users desktop folder/current users home directory/ same relative location/specific folder/system folder/system fonts folder/system preferences folder/top folder of the boot disk): The target location to copy to. ownership (current console user/current owner/destination folder owner/specific owner): Specifies the new ownership of the copied item(s). should open (boolean): Should the items be opened after being copied stopping on error (boolean): Should the copy terminate if an error occurs during copying copy to me task n [inh. task > item]: Copy items from the target computers to the administrator computer. ELEMENTS contained by application. PROPERTIES bandwidth limit (integer): Network usage limit in kilobytes per second (0 = unlimited). conflict resolution (ask what to do/rename the existing item/rename the item being copied/replace/replace if older): Specifies what to do if the item(s) already exist in this location. copy items (list): A list of files and/or folders to copy. destination path (alias): If the location is ‘specific folder’, a fully specified path to the destination folder. encrypting (boolean): Should the items be encrypted during copying location (applications folder/current users desktop folder/current users home directory/ same relative location/specific folder/system folder/system fonts folder/system preferences folder/top folder of the boot disk): The target location to copy to.Appendix C AppleScript Remote Desktop Suite 177 empty trash task n [inh. task > item]: Empty the trash on the target computers. ELEMENTS contained by application. install package task n [inh. task > item]: Install package(s) on the target computers. ELEMENTS contained by application. PROPERTIES after installing (attempt restart/do nothing/force immediate restart): Specifies what to do after installing the package(s). bandwidth limit (integer): Network usage limit in kilobytes per second (0 = unlimited). delegating to task server (boolean): Should this task be delegated to the task server encrypting (boolean): Should the packages be encrypted during copying packages (list): A list of packages to install. stopping on error (boolean): Should the copy terminate if an error occurs during copying lock screen task n [inh. task > item]: Lock the screen(s) on the target computers. ELEMENTS contained by application. PROPERTIES message (Unicode text): Message to display on the screen(s). logout task n [inh. task > item]: Log out the current user on the target computers. ELEMENTS contained by application. open application task n [inh. task > item]: Launch an application on the target computers. ELEMENTS contained by application. PROPERTIES application (alias): The path to the application to open. open item task n [inh. task > item]: Open files on the target computers. ELEMENTS contained by application. PROPERTIES files (list): A list of files to open. rename computer task n [inh. task > item]: Change the name of the target computers. ELEMENTS contained by application. PROPERTIES178 Appendix C AppleScript Remote Desktop Suite naming uniquely (boolean): Should each machine be forced to have a numerically unique name target name (Unicode text): The new name for the computer. restart task n [inh. task > item]: Restart the target computers. ELEMENTS contained by application. PROPERTIES user can save changes or cancel (boolean): Is the user allowed to save changes or cancel the restart send message task n [inh. task > item]: Send a text message to the target computers. ELEMENTS contained by application. PROPERTIES message (Unicode text): Message to display on the screen(s). send unix command task n [inh. task > item]: Send a UNIX command or script to the target computers. ELEMENTS contained by application. PROPERTIES script (Unicode text): The command string to be executed. showing output (boolean): Should the complete output of command be displayed in a window user (Unicode text): The user to execute the command as. set local startup disk task n [inh. task > item]: Set the startup volume on the target computers. ELEMENTS contained by application. PROPERTIES boot volume (Unicode text): Specific volume of drive to boot (optional). restarting (boolean): Should the machine be restarted after setting the startup volume set network startup disk task n [inh. task > item]: Set the startup volume on the target computers. ELEMENTS contained by application. PROPERTIES from server (Unicode text): Internet address of the server to boot from. mount volume (Unicode text): Volume name on server to mount. restarting (boolean): Should the machine be restarted after setting the startup volume Appendix C AppleScript Remote Desktop Suite 179 share screen task n [inh. task > item]: Share a computers screen to the target computers. ELEMENTS contained by application. PROPERTIES source computer (computer): The computer (other than the admin) whose screen to share. shutdown task n [inh. task > item]: Shutdown the target computers. ELEMENTS contained by application. PROPERTIES user can save changes or cancel (boolean): Is the user allowed to save changes or cancel the shutdown sleep task n [inh. task > item]: Put the target computers to sleep. ELEMENTS contained by application. task n [inh. item]: A task. This abstract class represents the tasks which can be executed by Remote Desktop. There are subclasses for each specific type of task. ELEMENTS contained by application. PROPERTIES computer list (computer list): The computer list associated with the task. id (Unicode text, r/o): The unique identifier (UUID) of the computer. name (Unicode text): The name of the task. recurrence (Unicode text, r/o): A string which describes the task recurrence, if defined. starting at (date): If the task is scheduled, the date and time of the first execution. unlock screen task n [inh. task > item]: Release the screen(s) of the target computers. ELEMENTS contained by application. upgrade client task n [inh. task > item]: Upgrade the Remote Desktop client on the target computers. ELEMENTS contained by application. wake up task n [inh. task > item]: Wake up the target computers. ELEMENTS contained by application.180 D Appendix D PostgreSQL Schema Sample This chapter contains SQL commands to assist SQL programmers in obtaining the database schema used in Apple Remote Desktop’s report database. You can use this knowledge about the schema to create your own applications that access Apple Remote Desktop report information. Sample list of main database schema Command: /System/Library/CoreServices/RemoteManagement/rmdb.bundle/bin/psql -U ard -c "\\d propertynamemap" ard Output: Table "public.propertynamemap" Column | Type | Modifiers ---------------+------------------------+----------- objectname | character varying(128) | not null propertyname | character varying(128) | not null propertymapid | integer | Sample list of system information table Command: /System/Library/CoreServices/RemoteManagement/rmdb.bundle/bin/psql -U ard -c "\\d systeminformation" ard Output: Table "public.systeminformation" Column | Type | Modifiers --------------+--------------------------+----------- computerid | character(17) | not null objectname | character varying(128) | not null propertyname | character varying(128) | not null itemseq | integer | value | character varying(512) | Appendix D PostgreSQL Schema Sample 181 lastupdated | timestamp with time zone | Sample list of property names Command: /System/Library/CoreServices/RemoteManagement/rmdb.bundle/bin/psql -U ard -c "select * from propertynamemap" ard Output: objectname | propertyname | propertymapid -----------------------+------------------------------+--------------- Mac_SystemInfoElement | WirelessCardIsActive | 0 Mac_SystemInfoElement | WirelessCardFirmwareVersion | 1 Mac_SystemInfoElement | WirelessCardHardwareAddress | 2 Mac_SystemInfoElement | WirelessCardLocale | 3 Mac_SystemInfoElement | WirelessCardType | 4 Mac_SystemInfoElement | WirelessCardInstalled | 5 Mac_SystemInfoElement | WirelessChannelNumber | 6 Mac_SystemInfoElement | WirelessNetworkAvailable | 7 Mac_SystemInfoElement | WirelessIsComputerToComputer | 8 ...... Sample list of table from one computer Command: /System/Library/CoreServices/RemoteManagement/rmdb.bundle/bin/psql -U ard -c "select * from systeminformation" ard Output: computerid | objectname | propertyname | itemseq | value | lastupdated -------------------+----------------------+-----------------+---------+----- ----------------+------------------------ 00:03:93:af:15:cc | Mac_HardDriveElement | CreationDate | 0 | 2005-02-25T03:30:07Z| 2005-02-26 22:21:38-08 00:03:93:af:15:cc | Mac_HardDriveElement | FileSystemType | 0 | 18475 | 2005-02-26 22:21:38-08 00:03:93:af:15:cc | Mac_HardDriveElement | FreeSpace | 0 | 4101610 | 2005-02-26 22:21:38-08 00:03:93:af:15:cc | Mac_HardDriveElement | GroupName | 0 | admin | 2005-02-26 22:21:38-08Index 182 Index A aborting a task 98 access changing privileges 69 group-based 62 via local account 61 Access Privileges 59 adding Dock items 131 administrator announce 92 Apple keyboard keys 79 Apple Remote Desktop menu icon 94, 95 application use report 115 asset tracking application use 115 FireWire devices 121 hardware 119 management 118 memory 123 PCI cards 123 software 118 software changes 118 USB devices 121 B basic file copy 108 best practices networking 71 reporting 113–114 security 73 C chat 92 cleaning up hard disks 128 client data upload policy 152 clipboard sharing 82 computer audio volume 130 computer list making a new 54 removing 54 smart 54 computer lists 49 description of 53 computer sharing names 129 Control/Observe preferences 36 controlling a client 78 control window 32 buttons 79–82 Copy and Open 108 copying items data encryption 107 overview 106 UNIX permissions 107 copying to relative locations 107 Copy Items options 107 CPU serial number, accessing 120 Create Custom Installer 43, 44 curtain mode 81, 140 customizing reports 35 D Dashboard observe 91 deleting files 128 demonstration mode 93 designated data collector 112 directory services 62 drag and drop copies 109 installation 104 E enabling SSH on clients 133 encryption one-time use 76 scheme description 75 setting defaults 75 Ethernet address tracking 122 F file mirroring 110 file system maintenance 131 finding free disk space 120 firewall settings 49 full screen display 81Index 183 G General preferences 36 group-based authorization 65 guest access 65 H hard disk maintenance 131 hardware asset management 119 Help Desk Mode. See sharing control human interface customizing 36 icons 29 tips and shortcuts 37 I installation, Remote Desktop 40 Install Packages options 107 K keyboard shortcut exceptions 78 kickstart tool 147, 151 L launching remote applications 136 limiting access privileges 66 limiting features to administrators 66 logging in remote users 140 logging out users 141 M main window 29 Managed Client settings 46 mcx_setting attribute 62, 64 metadata search 116 mirroring a folder 110 moving computer lists 56–57 multi-observe 85, 91 window 33 muting a computer 130 N NetBoot 128 networking best practices 71 networking with AirPort 72 Network Install 128 network interface audit 122 network performance tuning 73 networksetup tool 147 Network Time Protocol (NTP) server 129 notification script 97 O observation settings 87, 88 Observe Widget 91 observe window 32, 33 offline installation 103 Open Directory 62 P package installation 101, 105 preferences 36 preference standardization 133 printer setup 133 Property List Editor tool 62 putting wired clients to sleep 137 Q quitting applications 137 R reclaiming hard disk space 127 Remote 42 removing client software 47, 48 removing files 127 removing Remote Desktop 46 renaming copied items 108 multiple computers 129 repairing UNIX permissions 131 replacing copied items 108 report access privileges 69 Application Usage 115 File Search 117 Software Difference 118 Software Version 118 System Overview 119 User History 114 report data sources 111 reporting best practices 113–114 reporting policy template 153 report window 34 restarting client computers 141 reusing tasks 99, 100 S saving reporting policy preferences 153 saving reports 125 saving settings 99 saving tasks 99, 100 scan file import 52 IP range 50, 52 LAN 50 scanner display 49 scanners 49 screen pushing 93 screen sharing console 94 Scripting Remote Desktop AppleScript 156–159184 Index Automator 159 Secure Screen Blanking. See curtain mode. security best practices 73 preferences 36 sending scripts via UNIX command 145–147 serial number 40 setting boot disk 128 setting encryption defaults 75 setting Energy Saver preferences 132 setting up a Task Server 154 setting wake-on-LAN 132 sharing control 80 Sharing Preference 59 sharing screens 93 software installation 101 software version report 105 Spotlight search 116 SSH access description 68 start VNC server 68 system requirements 39 systemsetup tool 132, 133, 147, 149 T task history 96 task progress 96, 98 task results 99 task schedules 155 Task Server data collection 112 Install Package 103 preferences 36 setup 154 task status 98 task templates saving 100 UNIX commands 143 templates UNIX commands 143 temporary access 65 testing network performance 124–125 text announce 92 text chat 92 third-party installers 104 Tiger-only features Spotlight search 116 tips using report windows 126 using the observe window 90 tracking. See asset tracking. trashing files 127, 128 U uninstalling client software 47, 48 uninstalling Remote Desktop 46 unique computer names 129 UNIX command templates 143 updating software 118 upgrading client software 42 Remote Desktop 41 user history report 114 user interface. See human interface. user login report 114 user mode 66 user requests, viewing 93 using a time server 129 V VNC 67 connecting to server 82 Control-Alt-Delete 83 custom display designation 84 Mac OS X Client as VNC server 85 non–Mac OS X basic set-up 83 port customization 84 W wakeonlan packet 138 waking wired clients 138 window, shortcuts 37 Workgroup Manager 46, 131 X XML 64 Finger Tips Quick Start Guide Welcome to iPhone. This Quick Start guide tells you how to set up your iPhone and use its key features. To start, turn on your iPhone by pressing and holding the On/Off button for a few seconds. Then follow the onscreen instructions to set up your iPhone. Button basics. To turn off or restart iPhone, press and hold the On/Off button for a few seconds, then drag the slider to confirm. To turn off the screen but still receive calls, press On/Off once. Press the Home button at any time to return to the Home screen. To quickly switch between recently used apps, double-click the Home button and tap an app icon. Voice Control. Use Voice Control to make a hands-free call or play music. To activate Voice Control, hold down the Home button or the center button on the iPhone headset until the Voice Control screen appears. After the tone, speak a command such as “call Elliot” or “dial 555-1212.” You can also ask iPhone to play a specific album, artist, or playlist or to “play more songs like this.” You can even ask iPhone “what’s playing?” or say “play songs by the Rolling Stones,” for example. Notifications. When you receive a notification, it appears briefly at the top of the screen without interrupting what you’re doing. Ignore it or tap it to respond right away. To see a summary of your recent notifications, swipe down from the top of any screen. You can access a new notification from the Lock screen by sliding its icon to the right. Messages. Tap the Messages icon to send an iMessage to other iPhone, iPad, and iPod touch users running iOS 5, or to send an SMS or MMS to other mobile phone users. Type a name or phone number in the To field or select someone from your contacts. Type your message, then tap Send. To send photos or video, tap the Camera button. Make a call. Tap a phone number in Contacts, Favorites, an email, a text message, or almost anywhere in iPhone to make a call. Or open the Phone app and tap the Keypad button to dial manually. To silence an incoming call, press the On/Off button once. To send a call directly to voicemail, press On/Off twice. To answer a call while using the iPhone headset, press the center button once. Press it again to end your call. Search. To search your iPhone or the web, go to the main Home screen and press the Home button or swipe the screen from left to right. Type in what you’d like to find—a name, app, song, artist, movie, or any keyword. iPhone offers suggestions as you type to make searching even faster. To search within an app like Mail, Contacts, or Messages, tap the status bar. Intelligent keyboard. iPhone automatically corrects and suggests words as you type. So if you tap a wrong letter, just keep typing. To accept the suggested word, tap the space bar. Or tap the “x” to ignore the suggestion. The keyboard automatically inserts apostrophes in contractions. If you tap the space bar twice, it adds a period. You can double-tap a word to look it up in the dictionary. Cut, copy, and paste. Tap the text you want to edit, or touch and hold to bring up the magnifying glass, then slide your finger to move the insertion point. You can select a word by double-tapping it, and select more or less text by dragging the grab points. Then tap to cut, copy, or paste. To copy text from web pages, email, or text messages, touch and hold to select the text, then tap Copy. On/Off Sleep/Wake Ring/Silent Volume Up/Down HomeNot all features are available in all areas. TM and © 2011 Apple Inc. Designed by Apple in California. Printed in China. 034-6177-A Learn more. Learn more about iPhone features at www.apple.com/iphone. For the iPhone User Guide and important information, visit support.apple.com/manuals/ iphone. To view the guide on iPhone, download it from the iBookstore or use the Safari bookmark. Get support. Contact your wireless service provider for support on network services, voicemail, and billing. Visit www.apple.com/support/ iphone for support on iPhone and iTunes. Photos. Tap the Photos icon on the Home screen to see your pictures. Flick right or left to move between images. Double-tap or pinch to zoom. Tap once to bring up the onscreen controls. You can edit or enhance a photo, share it, print it, and more. If you have Photo Stream enabled in iCloud, new pictures you take are automatically pushed to all your other devices. Cars 2 will be available on iTunes beginning November 1, 2011. Cars 2 © Disney/Pixar. *Requires second-generation Apple TV. Video and song controls. While playing music or watching a movie, tap anywhere on the screen to bring up the controls. Tap again to hide them. To stream your music or video to an Apple TV, tap the AirPlay button.* From the Lock screen, you can double-click the Home button to quickly access your audio controls. See the web up close. In Safari, double-tap any element on a web page—picture or text—to zoom in. Doubletap again to zoom back out. Rotate iPhone to see the web in widescreen. Tap the Reader button at the top of the screen to view an article without clutter. Tap the Multi-page button to flick between multiple web pages or open a new one. Google, the Google logo, and Google Maps are trademarks of Google Inc. © 2011. All rights reserved. Find location. Search surroundings. To see where you are on a map, tap the Location button. A blue dot appears at your current position. To see which way you’re facing, tap the Location button again to turn on compass view. Find places around you by typing words like “Starbucks” or “pizza” in the search field. Double-tap to zoom in. Tap once with two fingers to zoom out. You can also get directions or tap the Page Curl button for additional map views. App Store. Tap the App Store icon to browse hundreds of thousands of apps in categories like games, business, travel, social networking, and more. Browse by Featured, Categories, or Top 25 or search by name. To purchase and download an app directly to your iPhone, tap Buy Now. Many apps are free. iTunes Store. You can access the iTunes Store by tapping the iTunes icon. Search the store for music, movies, TV shows, music videos, and more. Browse, purchase, and download from the store directly to your iPhone. Tap any item to hear or see a preview. Create folders. Organize apps. Touch and hold any app icon until it starts to jiggle. Then drag one app onto another to create a folder. Folders are automatically named by category, or you can rename them. You can customize your Home screen by dragging apps and folders to different positions and screens. When you’re done, press the Home button. Get directions. In Maps, tap Directions, then enter start and end points. You can use your current location, type in an address, or select an address from your contacts or bookmarked locations. Tap Route to display driving directions. Tap the Walk button for walking directions or the Bus button to view transit routes and times. iPhone can track and show your progress along whichever route you take. iCloud. iCloud stores your music, photos, apps, calendars, documents, and more. It’s seamlessly integrated into your apps and wirelessly pushes your content to all your devices. Tap the Settings icon and choose iCloud to turn on Photo Stream and other iCloud features. You can also download music and apps you’ve previously purchased from the iTunes Store and the App Store. This guide contains all the information you need to get from setup to your sofa. Welcome. You’re watching Apple TV.Contents 3 Contents Chapter 1: Connect. 7 What’s in the Box 8 Apple TV at a Glance 10 What You Need 11 Setting Up Apple TV Chapter 2: Configure. 16 Network Configuration 17 Connecting to iTunes Chapter 3: Watch. 20 Using Your Apple Remote 21 Basic Remote Functions 21 Pairing Apple TV with a Remote 22 Unpairing Apple TV from a Remote 23 Changing the Remote Battery 24 Renting Movies and Purchasing TV Shows4 Contents Chapter 4: Problem? No Problem. 26 Troubleshooting 31 Status Light 32 Service and Support 32 Serial Number 33 Care and Cleaningwww.apple.com/support/appletv Connect. 16 Chapter 1 Connect. Chapter 1 Connect. With Apple TV, you can rent high-definition movies, purchase TV shows, watch streaming content from Netflix, and enjoy podcasts, YouTube and Vimeo videos, and Internet radio. And, you can stream your personal iTunes content wirelessly from a Mac or PC, and view photos from your computer or Flickr on your widescreen HDTV, from the comfort of your couch. And with AirPlay, you can wirelessly stream videos, music, and photos from your iPhone, iPad, and iPod touch to Apple TV. Note:  Content availability varies by region. For information about See What you need to get started “What You Need” on page 10 Setting up Apple TV “Setting Up Apple TV” on page 11 Setting up your network connection “Network Configuration” on page 16 Using the Apple Remote “Using Your Apple Remote” on page 20 Troubleshooting Apple TV “Troubleshooting” on page 26 Apple TV safety and warranty The Apple TV Important Product Information GuideChapter 1 Connect. Chapter 1 Connect. 7 What’s in the Box AC power cord Apple Remote Note:  Your power cord may look different from the one pictured here.8 Chapter 1 Connect. Chapter 1 Connect. Apple TV at a Glance IR receiver Status light £ HDMI port d Micro USB port Optical digital audio port Power port G Ethernet portChapter 1 Connect. Chapter 1 Connect. 9 IR receiver Use with the included Apple Remote to control Apple TV. Status light The status light flashes slowly when Apple TV starts up.When Apple TV is on, the status light glows. See “Status Light” on page 31. d Micro USB port For service and diagnostics. ≤ Power port Connect the included AC power cord to the power port on Apple TV. G Ethernet port If your network is Ethernet-based, connect an Ethernet cable. £ HDMI port Connect Apple TV to the HDMI port of a high-definition TV using an HDMI cable. Optical digital audio port Connect Apple TV to a home theater receiver that has an optical digital audio port, using an optical digital audio (also called S/PDIF or TOSLINK) cable. Z Built-in 802.11n Wi-Fi technology Connect Apple TV to your wireless network.10 Chapter 1 Connect. Chapter 1 Connect. What You Need To start using Apple TV, you need the following: High-Definition TV A high-definition TV capable of displaying 720p video Cables  An HDMI cable to connect Apple TV to your TV  An optical digital audio cable (if you plan to use one) Network  An 802.11b, g, or n Wi-Fi wireless network (wireless video streaming requires 802.11g or 802.11n), or 10/100Base-T Ethernet network  A broadband Internet connection (DSL, cable, or LAN)  Your wireless network name and password (if you use one) Software and Accounts To play content from a Mac or PC on Apple TV, you need the following:  An Apple ID to rent movies or purchase TV shows from the iTunes store, and to use Home Sharing to stream content from a Mac or PC  iTunes 10.2 or later  A Netflix account to stream contentChapter 1 Connect. Chapter 1 Connect. 11 Setting Up Apple TV Apple TV connects to your TV through an HDMI port that delivers both audio and video. Before you set up Apple TV, look at the ports on the back of your TV to make sure you have the right cables. You can connect Apple TV to a high-definition TV or home theater receiver that has an HDMI port, using an HDMI cable for both video and audio. You can also use an optical digital audio cable to connect Apple TV to a receiver for audio. Important:  Before you connect Apple TV to a power outlet, carefully read these installation instructions and the safety information in the included Important Product Information Guide.12 Chapter 1 Connect. Chapter 1 Connect. Step 1: Connecting the cables 1 Connect one end of an HDMI cable to the back of your TV. 2 Connect the other end of the cable to the HDMI port on the back of Apple TV. 3 If you’re using an optical digital audio cable for audio, connect one end of the cable to the audio input port on your receiver or TV, and the other end to the optical digital audio port on the back of Apple TV. Apple TV Television HDMI port HDMI port HDMI cable Note:  The built-in 802.11 Wi-Fi technology connects Apple TV to your wireless network. If your network is Ethernet-based, connect Apple TV to your network using an Ethernet cable.Chapter 1 Connect. Chapter 1 Connect. 13 Step 2: Connect the power cord Connect one end of the power cord to the power port on the back of Apple TV and the other end to a power outlet. Power port Important:  Don’t place anything on top of Apple TV. Objects placed on top may interfere with the wireless signal. Don’t place Apple TV on other electronic equipment in a media cabinet. Step 3: Turn on your TV and select the input The first time you use Apple TV, it helps you choose a language, select a network, and configure Apple TV to work with your network (if necessary). See Chapter 2, “Configure.” on page 15. If you see just a black screen the first time you use Apple TV, make sure the input setting you’ve selected on your TV matches the input you connected the cables to on your TV or home theater receiver. See Chapter 4,“Problem? No Problem.” on page 25, and refer to the documentation that came with your TV for information about its inputs.www.apple.com/support/appletv Configure. 216 Chapter 2 Configure. Chapter 2 Configure. Apple TV helps you select and configure your wireless network connection, and, if you want to watch or listen to the contents of your iTunes library, connect to iTunes on your computer. Network Configuration Have your network name and password (if you use one) and your Apple Remote handy when you configure Apple TV. Make sure there are no obstructions between the remote and Apple TV. For information about using your remote, see Chapter 3,“Watch.” on page 19. If you:  Use a wired Ethernet network to connect, Apple TV automatically detects your network.  Use a wireless network to connect, Apple TV helps you select and configure your network connection. Connecting to Your Wireless Network Apple TV helps you connect to your wireless network. If you use a name and password to access your network, have them ready. Use the Apple Remote to: 1 Select your network from the list, or enter your network name if the network is hidden. 2 Enter your network password (if you use one).Chapter 2 Configure. Chapter 2 Configure. 17 If you don’t connect using DHCP, you may need to enter your IP address, subnet mask, router address, and DNS address. To complete the network connection, follow the onscreen instructions. Connecting to iTunes To access the content in your iTunes library on Apple TV, you need iTunes 10.2 or later installed on your computer. For a complete list of system requirements, see “Software and Accounts” on page 10. Updating Your iTunes Software You can update to the latest version of iTunes.  On a Mac, use Software Update to update to the latest version of iTunes. To use Software Update, choose Apple () > Software Update.  On a Windows-based computer, go to iTunes Help to update to the latest version of iTunes. Open iTunes, and then choose Help > Check for Updates. Setting Up Home Sharing After you set up your network connection, you need to set up iTunes and Apple TV to share the contents of your iTunes library. Use Home Sharing in iTunes and on Apple TV to share the iTunes library of any computer on your local network that has Home Sharing set up.18 Chapter 2 Configure. To set up Home Sharing in iTunes: 1 Open iTunes on your computer. 2 Choose Advanced > Turn On Home Sharing. 3 Type your Apple ID and password, and then click Create Home Share. 4 Repeat steps 1 through 3 on each computer you want to use for Home Sharing. For more information about iTunes, open iTunes and choose Help > iTunes Help. To set up Home Sharing on Apple TV: 1 On Apple TV, choose Settings > Computers. 2 Choose Turn On Home Sharing, and then enter the same Apple ID and password you entered on your computer.www.apple.com/support/appletv Watch. 320 Chapter 3 Watch. Chapter 3 Watch. Read on to learn about pairing and using your Apple Remote with Apple TV. Using Your Apple Remote Use the Apple Remote to control Apple TV settings and navigate your content. Make sure there are no obstructions between the remote and Apple TV. MENU Up Down Menu Play/Pause Left Right SelectChapter 3 Watch. Chapter 3 Watch. 21 Basic Remote Functions Your Apple Remote has the basic functions described below. To Do this Move through the menu options Press Up, Down, Left, or Right Select an option from a menu Press Select Return to a previous menu Press Menu Return to the main menu Hold down Menu Reset Apple TV Hold down Menu and Down until the Apple TV status light blinks rapidly Pair Apple TV and a remote Hold down Menu and Right for 6 seconds Up and Down on the Apple Remote don’t control the volume on your TV or home theater receiver. Use the remote that came with your TV or receiver to change the volume. Pairing Apple TV with a Remote The Apple Remote works with the built-in IR receiver on Apple TV. You can set Apple TV to work only with the included remote by pairing Apple TV and the remote.22 Chapter 3 Watch. Chapter 3 Watch. To pair Apple TV with the included remote: 1 Choose Settings from the Apple TV main menu. 2 Choose General > Remotes > Pair Apple Remote. You can also hold down Menu and Right for 6 seconds to pair Apple TV and the Apple Remote. When you successfully pair your Apple Remote, Apple TV displays a chainlink symbol ( ) above a picture of a remote. Apple TV now works only with the paired remote. Unpairing Apple TV from a Remote If you lose the Apple Remote that you paired Apple TV with, you can use any Apple Remote to unpair Apple TV from the lost remote by holding down Menu and Left for 6 seconds. You can also follow these steps. To unpair Apple TV from a paired remote: 1 Choose Settings from the Apple TV main menu. 2 Choose General > Remotes > Unpair Apple Remote. When you successfully unpair the lost remote, Apple TV displays a broken chainlink symbol ( ) above a picture of a remote. You can now pair Apple TV with a different remote.Chapter 3 Watch. Chapter 3 Watch. 23 Changing the Remote Battery When the battery charge in your Apple Remote is low, Apple TV displays a picture of a remote and a warning symbol (·). Replace the battery with a CR2032 battery. Battery compartment To replace the battery: 1 Use a coin to remove the battery compartment cover. 2 Remove the battery. 3 Insert a CR2032 battery with the positive side (∂) facing up. 4 Replace the battery compartment cover and use a coin to tighten it. Important:  Dispose of the used battery according to your local environmental laws and guidelines.24 Chapter 3 Watch. Renting Movies and Purchasing TV Shows You can rent standard or high-definition movies and purchase TV shows directly on Apple TV (where available). Follow the onscreen instructions to find out when a rented movie expires. Purchased TV shows don’t expire. When a rented movie expires, it’s no longer available for playback. To watch it again, you can rent it again from iTunes. Note:  Rented movies are not available in all regions.www.apple.com/support/appletv Problem? No Problem. 426 Chapter 4 Problem? No Problem. Chapter 4 Problem? No Problem. Most problems with Apple TV can be solved quickly by following the advice in this chapter. For additional tips and troubleshooting information, see the Apple TV Support page at www.apple.com/support/appletv. Troubleshooting If you have a problem with Apple TV, there’s usually a quick and simple solution. First, make sure:  The cables between Apple TV and your TV are pushed in all the way.  The power cords for Apple TV and your TV are securely connected to a working power source.  Your TV is turned on and set to the correct input.  Apple TV is connected to your network. Go to the Settings menu on Apple TV, select Network, and see if Apple TV has an IP address.  Your network and Internet connections are on and working properly. If you still have trouble, try resetting your equipment by disconnecting Apple TV, your TV, your wireless networking equipment or base station, and your router from the power outlet.Wait 30 seconds, and then reconnect everything. If the remote isn’t working  Point the remote directly at Apple TV.  If you paired Apple TV with an Apple Remote, make sure you’re using the paired remote.Chapter 4 Problem? No Problem. Chapter 4 Problem? No Problem. 27  If the Apple TV status light flashes once when you press buttons on the paired remote, the problem isn’t with the remote. See “If you can see a picture but Apple TV isn’t responding” on page 28.  If you’re using an unpaired remote, the Apple TV status light flashes three times.  If you paired Apple TV with an Apple Remote and you can’t find the paired remote, set Apple TV to work with any Apple Remote by holding down Menu and Left for 6 seconds on another remote.  Make sure the front of Apple TV isn’t blocked.  If Apple TV displays a picture of a remote and a warning symbol (·), you need to replace the battery in the remote. See “Changing the Remote Battery” on page 23. If Apple TV can’t access the network  Check the IP address Apple TV is using. If it starts with 169.x.x.x, the router or base station may not be configured properly. Check to see if DHCP access is available, or configure Apple TV with a manual IP address.  Check for any obstructions, and adjust the location of the base station or Apple TV.  If security is enabled on the network, temporarily disable it on the base station and try connecting again.  Apple TV cannot connect to a wireless network that contains high (extended) ASCII or double-byte (Unicode) characters (such as Japanese, Korean, or Chinese) in the name or password.  If your network has security enabled, make sure you enter the correct password.28 Chapter 4 Problem? No Problem. Chapter 4 Problem? No Problem. If your TV screen appears fuzzy or black  Make sure you’re using the correct HDMI cable and that it’s connected firmly to Apple TV and to your TV.  Make sure the input setting on your TV matches the input port the HDMI cable is connected to. For information, see the documentation that came with your TV.  Make sure your HDTV supports 720p video. If you can see a picture but Apple TV isn’t responding  Hold down Menu on the Apple Remote to return to the Apple TV main menu.  Make sure your TV is turned on and functioning properly. For information, see the documentation that came with your TV.  If you paired an Apple Remote with Apple TV, make sure you’re using the paired remote. See “Pairing Apple TV with a Remote” on page 21.  Reset Apple TV by doing one of the following:  Hold down both Menu and Down on the Apple Remote until the Apple TV status light blinks rapidly.  Disconnect Apple TV from the power outlet, wait about five seconds, and then reconnect it.  Choose General > Reset Settings from the main menu on Apple TV.Chapter 4 Problem? No Problem. Chapter 4 Problem? No Problem. 29 If Apple TV doesn’t respond, try restoring it  On Apple TV, choose Settings > General > Reset, and then select Restore. Restoring Apple TV can take some time, so be patient.  If your network doesn’t use DHCP, choose Configure TCP/IP and enter the TCP/IP configuration.  If Apple TV still doesn’t respond:  Disconnect the power and HDMI cables from Apple TV.  Connect one end of a micro USB cable (sold separately) to the back of Apple TV, and the other end to your computer.  Open iTunes on your computer, select Apple TV in the Source list, and then click Restore. If you can’t hear sound  If Apple TV is connected to a home theater receiver, make sure the receiver is turned on.  Make sure the input setting you selected on your TV or receiver matches the input you have your audio cable connected to. For more information, see the documentation that came with your receiver.  Make sure the volume on your TV or receiver is turned up and isn’t muted.  Make sure you’re using the correct audio cable and that it’s connected firmly to Apple TV and to your TV or receiver.  If you’re using the HDMI port for audio, make sure your TV supports audio through its HDMI port. The HDMI ports on some older TVs support only video.30 Chapter 4 Problem? No Problem. Chapter 4 Problem? No Problem. If Apple TV isn’t playing your photo albums or slideshows  Make sure you have photos in your photo library or in a folder on your computer.  Make sure Apple TV and the computer you’re using are set up for Home Sharing. See “Setting Up Home Sharing” on page 17.  Make sure the photos you want to share are selected. In iTunes, choose Advanced >“Choose Photos to Share,” and then select the photos you want to share.  Make sure Apple TV and your computer are on the same local network.  Make sure Apple TV and your computer are using the same Home Sharing account. If noise is coming from your TV speakers:  If your TV or speakers support Dolby Digital audio, make sure the Dolby Digital Out setting is correct for your TV or speakers. On Apple TV, choose Settings > Audio & Video > Dolby Digital Out, and select On or Off. If you don’t see your iTunes library under Computers on Apple TV:  Make sure Apple TV and your computer are on the same local network.  Make sure Apple TV and iTunes are using the same account name and password.Chapter 4 Problem? No Problem. Chapter 4 Problem? No Problem. 31 Status Light The status light on the front of Apple TV indicates what’s happening. If Apple TV is The status light On Glows Off or in standby Is off Starting up Flashes slowly Accepting a command from the remote Flashes once Rejecting a command from the remote (you paired a remote with Apple TV, but you’re using a remote that’s not paired) Flashes three times Having problems Flashes quickly32 Chapter 4 Problem? No Problem. Chapter 4 Problem? No Problem. Service and Support More information about using Apple TV is available in iTunes onscreen help and on the web. The following table describes where to get software and service information. To learn about Do this Service and support, discussions, tutorials, and Apple software downloads Go to: www.apple.com/support/appletv Using iTunes Open iTunes and choose Help > iTunes Help. For an onscreen iTunes tutorial (available in some areas only), go to: www.apple.com/support/itunes Using iPhoto (in Mac OS X) Open iPhoto and choose iPhoto > iPhoto Help Safety and regulatory compliance information See the Important Product Information Guide that comes with Apple TV. Serial Number The serial number is printed on the bottom of Apple TV. You can also find the serial number in the Apple TV Settings menu. On Apple TV, choose Settings > General > About.Chapter 4 Problem? No Problem. Chapter 4 Problem? No Problem. 33 Care and Cleaning NOTICE:  Failure to follow these care and cleaning instructions could result in damage to Apple TV or other property. Using Connectors and Ports Never force a connector into a port. Check for obstructions on the port. If the connector and port don’t join with reasonable ease, they probably don’t match. Make sure that the connector matches the port and that you have positioned the connector correctly in relation to the port. Keeping Apple TV Within Acceptable Temperatures Operate Apple TV in a place where the temperature is always between 0º and 40º C (32º to 104º F). Keeping the Outside of Apple TV Clean To clean Apple TV, unplug the power cord and all cables. Then use a soft, lint-free cloth. Avoid getting moisture in openings. Don’t use window cleaners, household cleaners, aerosol sprays, solvents, alcohol, ammonia, or abrasives to clean Apple TV. Disposing of Apple TV Properly For information about the proper disposal of Apple TV, and for other important regulatory compliance information, see the Important Product Information Guide.K Apple Inc. © 2011 Apple Inc. All rights reserved. Under the copyright laws, this manual may not be copied, in whole or in part, without the written consent of Apple. Every effort has been made to ensure that the information in this manual is accurate. Apple is not responsible for printing or clerical errors. Apple 1 Infinite Loop Cupertino, CA 95014 408-996-1010 www.apple.com The Apple logo is a trademark of Apple Inc., registered in the U.S. and other countries. Use of the “keyboard”Apple logo (Option-Shift-K) for commercial purposes without the prior written consent of Apple may constitute trademark infringement and unfair competition in violation of federal and state laws. Apple, the Apple logo, AirPlay, Apple TV, iPad, iPhone, iPhoto, iPod touch, iTunes, Mac, and Mac OS are trademarks of Apple Inc., registered in the U.S. and other countries. Apple Store and iTunes Store are service marks of Apple Inc., registered in the U.S. and other countries. Manufactured under license from Dolby Laboratories.“Dolby,”“Pro Logic,” and the double-D symbol are trademarks of Dolby Laboratories. Confidential Unpublished Works, © 1992-1997 Dolby Laboratories, Inc. All rights reserved. Other company and product names mentioned herein may be trademarks of their respective companies. Mention of third-party products is for informational purposes only and constitutes neither an endorsement nor a recommendation. Apple assumes no responsibility with regard to the performance or use of these products. USB Device Interface GuideContents Introduction to USB Device Interface Guide 4 Organization of This Document 4 See Also 4 USB Device Overview 6 USB Device Types and Bus Speeds 6 USB Device Architecture and Terminology 7 USB Device Component Descriptors 8 USB Composite Class Devices 8 USB Transfer Types 8 Stalls and Halts 9 Data Synchronization in Non-Isochronous Transfers 10 USB 2.0 and Isochronous Transfers 10 USB Devices on OS X 11 Finding USB Devices and Interfaces 12 USB Family Error Codes 14 Determining Which Interface Version to Use 14 Tasks and Caveats 15 Handling Stalls, Halts, and Data Toggle Resynchronization 15 Using the Low Latency Isochronous Functions 15 Errors Reported by the EHCI Hub 17 Changes in Isochronous Functions to Support USB 2.0 17 USB Device Access in an Intel-Based Macintosh 18 Working With USB Device Interfaces 20 Using USB Device Interfaces 20 Accessing a USB Device 22 Definitions and Global Variables 22 The main Function 23 Working With the Raw Device 27 Working With the Bulk Test Device 34 Working With Interfaces 36 Document Revision History 46 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 2Tables and Listings USB Device Overview 6 Table 1-1 Examples of USB devices 6 Table 1-2 Keys for finding a USB device 12 Table 1-3 Keys for finding a USB interface 13 Working With USB Device Interfaces 20 Listing 2-1 Definitions and global variables 22 Listing 2-2 The main function 24 Listing 2-3 Accessing and programming the raw device 27 Listing 2-4 Releasing the raw device objects 30 Listing 2-5 Configuring a USB device 30 Listing 2-6 Two functions to download firmware to the raw device 32 Listing 2-7 Accessing the bulk test device 34 Listing 2-8 Finding interfaces on the bulk test device 36 Listing 2-9 Two asynchronous I/O completion functions 43 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 3Note: This document was previously titled Working With USB Device Interfaces. The I/O Kit provides a device interface mechanism that allows applications to communicate with and control hardware from outside the kernel. This document focuses on how to use that mechanism to create an application that detects the attachment of a USB device, communicates with it, and detects its detachment. This document does not describe how to develop an in-kernel driver for a USB modem or networking device. If you need to do this, refer to the documentation and sample code listed in “See Also” (page 4). Important: If your application is sandboxed, it must request the com.apple.security.device.usb entitlement in order to access USB devices. Organization of This Document This document contains the following chapters: ● “USB Device Overview” (page 6) provides an overview of USB device architecture and terminology and describes how USB devices are represented in OS X. ● “Working With USB Device Interfaces” (page 20) describes how to use the device interface mechanism to create a command-line tool that accesses a USB device. ● “Document Revision History” (page 46) lists the revisions of this document. See Also The ADC Reference Library contains several documents on device driver development for OS X and numerous sample drivers and applications. ● Accessing Hardware From Applications describes various ways to access devices from outside the kernel, including the device interface mechanism provided by the I/O Kit. For an overview of the I/O Kit terms and concepts used in this document, read the chapter Device Access and the I/O Kit. 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 4 Introduction to USB Device Interface Guide● I/O Kit Framework Reference contains API reference for I/O Kit methods and functions and for specific device families. ● Sample Code > Hardware & Drivers > USB includes both application-level and in-kernel code samples. Of particular relevance to this document is the application-level sample USBPrivateDataSample . ● OS X Man Pages provides access to existing reference documentation for BSD and POSIX functions and tools in a convenient HTML format. ● The usb mailing list provides a forum for discussing technical issues relating to USB devices in OS X. If you need to develop an in-kernel driver for a USB modem or networking device, refer to the following: ● I/O Kit Fundamentals describesthe architecture ofthe I/OKit,the object-oriented framework for developing OS X device drivers. ● ADC members can view the AppleUSBCDCDriver project in the source code for OS X v10.3.7 and later, available at Darwin Releases. To find the source code, select a version of OS X equal to or greater than v10.3.7 and click Source (choose the source for the PPC version, if there's a choice). This displays a new page, which lists the open source projects available for the version of OS X you've chosen. Scroll down to AppleUSBCDCDriver and click it to view the source. Be prepared to supply your ADC member name and password. ● Additional code samples that demonstrate specific in-kernel driver programming techniques are included as part of the OS X Developer Toolsinstallation package in /Developer/Examples/Kernel/IOKit/usb. If you're ready to create a universal binary version of your USB device-access application to run in an Intel-based Macintosh,seeUniversalBinaryProgrammingGuidelines.TheUniversalBinaryProgrammingGuidelines describes the differences between the Intel and PowerPC architectures and provides tips for developing a universal binary. If you are working with a device that complies with the USB mass storage specification but declares its device class to be vendor specific, see Mass Storage Device Driver Programming Guide for information on how to ensure the correct built-in driver loads for the device. Apple provides additional USB information (including the OS X USB Debug Kits) at http://developer.apple.com/hardwaredrivers/usb/index.html. A detailed description of the USB device specification is beyond the scope of this document—for more information, see Universal Serial Bus Specification Revision 2.0 available at http://www.usb.org. Introduction to USB Device Interface Guide See Also 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 5This chapter provides a summary of USB device architecture and describes how USB devices are represented in OS X. It also presents a few specific guidelines for working with USB devices in an application.For details on the USB specification, see http://www.usb.org. USB Device Types and Bus Speeds The USB specification supports a wide selection of devices that range from lower-speed devices such as keyboards, mice, and joysticks to higher-speed devices such as scanners and digital cameras. The specification lists a number of device classes that each define a set of expected device behaviors. Table 1-1 (page 6) lists some examples of USB devices, categorized by class. Table 1-1 Examples of USB devices USB device class USB devices in class Audio class Speakers, microphones Chip Card Interface Device Class Smart cards, chip cards Communication class Speakerphone, modem A device in which all class-specific information is embedded in its interfaces Composite class HID class Keyboards, mice, joysticks, drawing tablets Hub class Hubs provide additional attachment points for USB devices Hard drives, flash memory readers, CD Read/Write drives, digital cameras, and high-end media players Mass storage class Printing class Printers A device that doesn’t fit into any other predefined class or one that doesn’t use the standard protocols for an existing class Vendor specific Digital camcorders, webcams, digital still cameras that support video streaming Video class 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 6 USB Device OverviewVersion 1.1 of the USB specification supports two bus speeds: ● Low speed (1.5 Mbps) ● Full speed (12 Mbps) Version 2.0 of the specification adds another bus speed to this list: ● High speed (480 Mbps) The USB 2.0 specification is fully compatible with low-speed and full-speed USB devices and even supports the use of cables and connectors made to meet earlier versions of the specification. Apple provides USB 2.0 ports on all new Macintosh computers and fully supports the new specification with Enhanced Host Controller Interface (EHCI) controllers and built-in, low-level USB drivers. For the most part, you do not have to change existing applications to support the faster data rate because the speed increase and other enhancements are implemented at such a low level. The exceptions to this are some differences in isochronous transfers. For information on how the USB 2.0 specification affects isochronous transfers, see “USB 2.0 and Isochronous Transfers” (page 10). USB Device Architecture and Terminology The architecture of a generic USB device is multi-layered. A device consists of one or more configurations, each of which describes a possible setting the device can be programmed into. Such settings can include the power characteristics of the configuration (for example, the maximum power consumed by the configuration and whether it is self-powered or not) and whether the configuration supports remote wake-up. Each configuration contains one or more interfacesthat are accessible after the configuration isset. An interface provides the definitions of the functions available within the device and may even contain alternate settings within a single interface. For example, an interface for an audio device may have different settings you can select for different bandwidths. Each interface contains zero or more endpoints. An endpoint is a uniquely identifiable portion of a USB device that is the source or sink of information in a communication flow between the host and the device. Each endpoint has characteristics that describe the communication it supports, such as transfer type (control, isochronous, interrupt, or bulk, described in “USB Transfer Types” (page 8)), maximum packet size, and transfer direction (input or output). Communication with a USB device is accomplished through a pipe, a logical association between an endpoint and software running on the host. Endpoint and pipe are often used synonymously although an endpoint is a component of a USB device and a pipe is a logical abstraction of the communications link between endpoint and host. USB Device Overview USB Device Architecture and Terminology 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 7USB Device Component Descriptors Each layer of a USB device providesinformation about its attributes and resource requirementsin its descriptor, a data structure accessible through device interface functions. By examining the descriptors at each layer, you can determine exactly which endpoint you need to communicate successfully with a particular device. At the top layer is the device descriptor, which has fields associated with information such as the device’s class and subclass, vendor and product numbers, and number of configurations. Each configuration in turn has a configuration descriptor containing fields that describe the number of interfaces it supports and the power characteristics of the device when it is in that configuration, along with other information. Each interface supported by a configuration has its own descriptor with fields for information such as the interface class, subclass, and protocol, and the number of endpoints in that interface. At the bottom layer are the endpoint descriptors that specify attributes such as transfer type and maximum packet size. The USB specification defines a name for each descriptor field, such as the bDeviceClass field in the device descriptor and the bNumInterfaces field in the configuration descriptor, and each field is associated with a value. For a complete listing of all descriptor fields, see the USB specification at www.usb.org. The USB family defines structures that represent the descriptors defined by the USB specification. For the definitions of these structures, see USB in Kernel Framework Reference . USB Composite Class Devices The USB specification defines a composite class device as a device whose device-descriptor fields for device class (bDeviceClass) and device subclass (bDeviceSubClass) both have the value 0. A composite class device appears to the system as a USB device using a single bus address that may present multiple interfaces, each of which represents a separate function. A good example of a composite class device is a multifunction device, such as a device that performs printing, scanning, and faxing. In such a device, each function is represented by a separate interface. In OS X, the I/O Kit loads the AppleUSBComposite device driver for composite class devices that do not already have vendor-specific device drivers to drive them. The AppleUSBComposite driver configures the device and causes drivers to be loaded for each USB interface. Although most multifunction USB devices are composite class devices, not all composite class devices are multifunction devices. The manufacturer of a single-function USB device is at liberty to classify the device as a composite class device as long as the device meets the USB specifications. For more information on how OS X represents USB devices and interfaces, see “USB Devices on OS X” (page 11). USB Transfer Types The USB specification defines four types of pipe transfer: ● Control—intended to support configuration, command, and status communication between the host software and the device. Control transfers support error detection and retry. USB Device Overview USB Device Architecture and Terminology 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 8● Interrupt—used to support small, limited-latency transfers to or from a device such as coordinates from a pointing device or status changes from a modem. Interrupt transfers support error detection and retry. ● Isochronous—used for periodic, continuous communication between the host and the device, usually involving time-relevant information such as audio or video data streams. Isochronous transfers do not support error detection or retry. ● Bulk—intended for non-periodic, large-packet communication with relaxed timing constraints such as between the host software and a printer or scanner. Bulk transfers support error detection and retry. Pipes also have a transfer direction associated with them. A control pipe can support bidirectional communication but all other pipes are strictly uni-directional. Therefore, two-way communication requires two pipes, one for input and one for output. Every USB device is required to implement a default control pipe that provides access to the device’s configuration, status, and control information. This pipe, implemented in the IOUSBDevice nub object (described in “USB Devices on OS X” (page 11)), is used when a driver such as the AppleUSBComposite driver configures the device or when device-specific control and status information is needed. For example, your application would use the default control pipe if it needs to set or choose a configuration for the device. The default control pipe is connected to the default endpoint (endpoint 0). Note that endpoint 0 does not provide an endpoint descriptor and it is never counted in the total number of endpoints in an interface. The interfaces associated with a configuration can contain any combination of the three remaining pipe types (interrupt, isochronous, and bulk), implemented in the IOUSBInterface nub objects (described in “USB Devices on OS X” (page 11)). Your application can query the interface descriptors of a device to select the pipe most suited to its needs. Stalls and Halts Although a stall and a halt are different, they are closely related in their effect on data transmission. Halt is a feature of an endpoint and it can be set by either the host or the device itself in response to an error. A stall is a type of handshake packet an endpoint returns when it is unable to transmit or receive data or when its halt feature is set (the host never sends a stall packet). When an endpoint sends a stall packet, the host can halt the endpoint. Depending on the precise circumstances and on how compliant the device is, the halt feature must be cleared in the host, the endpoint, or both before data transmission can resume. When the halt is cleared the data toggle bit, used to synchronize data transmission, is also reset (see “Data Synchronization in Non-Isochronous Transfers” (page 10) for more information about the data toggle). For information on how to handle these conditions in your application, see “Handling Stalls, Halts, and Data Toggle Resynchronization” (page 15). USB Device Overview USB Device Architecture and Terminology 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 9Data Synchronization in Non-Isochronous Transfers The USB specification defines a simple protocol to provide data synchronization across multiple packets for non-isochronoustransfers(recall that isochronoustransfers do notsupport error recovery or retry). The protocol is implemented by means of a data toggle bit in both the host and the endpoint which is synchronized at the start of a transaction (or when a reset occurs). The precise synchronization mechanism varies with the type of transfer; see the USB specification for details. Both the host and the endpoint begin a transaction with their data toggle bitsset to zero. In general, the entity receiving data toggles its data toggle bit when it is able to accept the data and it receives an error-free data packet with the correct identification. The entity sending the data toggles its data toggle bit when it receives a positive acknowledgement from the receiver. In this way, the data toggle bits stay synchronized until, for example, a packet with an incorrect identification is received. When this happens, the receiver ignores the packet and does not increment its data toggle bit. When the data toggle bits get out of synchronization (for this or any other reason), you will probably notice that alternate transactions are not getting through in your application. The solution to this is to resynchronize the data toggle bits. For information on how to do this, see “Handling Stalls, Halts, and Data Toggle Resynchronization” (page 15). USB 2.0 and Isochronous Transfers The USB 2.0 specification supports the same four transfer types as earlier versions of the specification. In addition to supporting a higher transfer rate, the new specification defines an improved protocol for high-speed transfers and new ways of handling transactions for low-speed and full-speed devices. For details on the protocols and transaction-handling methods, see the specification at http://www.usb.org. For the most part, these enhancements are implemented at the hostsoftware level and do not require changes to your code. For isochronous transfers, however, you should be aware of the following differences: ● Earlier versions of the specification divide bus time into 1-millisecond frames, each of which can carry multiple transactionsto multiple destinations. (A transaction containstwo or more packets: a token packet and one or more data packets, a handshake packet, or both.) The USB 2.0 specification divides the 1-millisecond frame into eight, 125-microsecond microframes, each of which can carry multiple transactions to multiple destinations. ● The maximum amount of data allowed in a transaction is increased to 3 KB. ● Any isochronous endpoints in a device’s default interface must have a maximum packet size of zero. (This means that the default setting for an interface containing isochronous pipes is alternate setting zero and the maximum packet size for that interface’s isochronous endpoints must be zero.) This ensures that the host can configure the device no matter how busy the bus is. For a summary of how these differences affect the OS X USB API, see “Changes in Isochronous Functions to Support USB 2.0” (page 17). USB Device Overview USB Device Architecture and Terminology 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 10USB Devices on OS X When a USB device is plugged in, the OS X USB family abstracts the contents of the device descriptor into an I/O Kit nub object called an IOUSBDevice. This nub object is attached to the IOService plane of the I/O Registry as a child of the driver for the USB controller. The IOUSBDevice nub object is then registered for matching with the I/O Kit. If the device is a composite class device with no vendor-specific driver to match against it, the AppleUSBComposite driver matches against it and starts as its provider. The AppleUSBComposite driver then configures the device by setting the configuration in the device’s list of configuration descriptors with the maximum power usage that can be satisfied by the port to which the device is attached. This allows a device with a low power and a high power configuration to be configured differently depending on whether it’s attached to a bus-powered hub or a self-powered hub. In addition, if the IOUSBDevice nub object has the “Preferred Configuration” property, the AppleUSBComposite driver will always use that value when it attempts to configure the device. The configuration of the device causes the USB family to abstract each interface descriptor in the chosen configuration into an IOUSBInterface nub object. These nub objects are attached to the I/O Registry as children of the original IOUSBDevice nub object and are registered for matching with the I/O Kit. Important: Because a composite class device is configured by the AppleUSBComposite driver, setting the configuration again from your application will result in the destruction of the IOUSBInterface nub objects and the creation of new ones. In general, the only reason to set the configuration of a composite class device that’s matched by the AppleUSBComposite driver is to choose a configuration other than the first one. For non-composite class devices or composite class devices with vendor-specific drivers that match against them, there is no guarantee that any configuration will be set and you may have to perform this task within your application. It's important to be mindful of the difference between a USB device (represented in the I/O Registry by an IOUSBDevice nub object) and its interfaces (each represented by an IOUSBInterface nub object). A multifunction USB device, for example, is represented in the I/O Registry by one IOUSBDevice object and one IOUSBInterface object for each interface. The distinction between interface and device isimportant because it determines which object your application must find in the I/O Registry and which type of device interface to get. For example, if your application needs to communicate with a specific interface in a multifunction USB device, it must find that interface and get an IOUSBInterfaceInterface to communicate with it. An application that needs to communicate with the USB device as a whole, on the other hand, would need to find the device in the I/O Registry and get an IOUSBDeviceInterface to communicate with it. For more information on finding devices and interfaces in USB Device Overview USB Devices on OS X 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 11the I/O Registry, see “Finding USB Devices and Interfaces” (page 12); for more information on how to get the proper device interface to communicate with a device or interface, see “Using USB Device Interfaces” (page 20). Finding USB Devices and Interfaces To find a USB device or interface, use the keys defined in the Universal Serial Bus Common Class Specification, Revision 1.0 (available for download from http://www.usb.org/developers/devclass_docs/usbccs10.pdf) to create a matching dictionary that defines a particular search. If you are unfamiliar with the concept of device matching, see the section “Finding Devices in the I/O Registry” in Accessing Hardware From Applications. The keys defined in the specification are listed in the tables below. Each key consists of a specific combination of elements in a device or interface descriptor. In the tables below, the elements in a key are separated by the ‘+’ character to emphasize the requirement that all a key’s elements must appear together in your matching dictionary. Both tables present the keys in order of specificity: the first key in each table defines the most specific search and the last key defines the broadest search. Before you build a matching dictionary, be sure you know whether your application needs to communicate with a device or a specific interface in a device. It’s especially important to be aware of this distinction when working with multifunction devices. A multifunction device is often a composite class device that defines a separate interface for each function. If, for example, your application needs to communicate with the scanning function of a device that does scanning, faxing, and printing, you need to build a dictionary to match on only the scanning interface (an IOUSBInterface object), not the device as a whole (an IOUSBDevice object). In this situation, you would use the keys defined for interface matching (those shown in Table 1-3 (page 13)), not the keys for device matching. Table 1-2 (page 12) lists the keys you can use to find devices (not interfaces). Each key element is a piece of information contained in the device descriptor for a USB device. Table 1-2 Keys for finding a USB device Key Notes bcdDevice contains the release number of the device idVendor + idProduct + bcdDevice idVendor + idProduct Use this key only if the device’s bDeviceClass is $FF idVendor + bDeviceSubClass + bDeviceProtocol Use this key only if the device’s bDeviceClass is $FF idVendor + bDeviceSubClass USB Device Overview USB Devices on OS X 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 12Key Notes Use this key only if the device’s bDeviceClass is not $FF bDeviceClass + bDeviceSubClass + bDeviceProtocol Use this key only if the device’s bDeviceClass is not $FF bDeviceClass + bDeviceSubClass Table 1-3 (page 13) lists the keys you can use to find interfaces (not devices). Each key element is a piece of information contained in an interface descriptor for a USB device. Table 1-3 Keys for finding a USB interface Key Notes idVendor + idProduct + bcdDevice + bConfigurationValue + bInterfaceNumber idVendor + idProduct + bConfigurationValue + bInterfaceNumber Use this key only if bInterfaceClass is $FF idVendor + bInterfaceSubClass + bInterfaceProtocol Use this key only if bInterfaceSubClass is $FF idVendor + bInterfaceSubClass Use this key only if bInterfaceSubClass is not $FF bInterfaceClass + bInterfaceSubClass + bInterfaceProtocol Use this key only if bInterfaceSubClass is not $FF bInterfaceClass + bInterfaceSubClass For a successful search, you must add the elements of exactly one key to your matching dictionary. If your matching dictionary contains a combination of elements not defined by any key, the search will be unsuccessful. For example, if you create a matching dictionary containing values representing a device’s vendor, product, and protocol, the search will be unsuccessful even if a device with those precise values in its device descriptor is currently represented by an IOUSBDevice nub in the I/O Registry. This is because there is no key in Table 1-2 (page 12) that combines the idVendor, idProduct, and bDeviceProtocol elements. USB Device Overview USB Devices on OS X 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 13USB Family Error Codes As you develop an application to access a USB device or interface, you will probably encounter error codes specific to the OS X USB family. If you are using Xcode, you can search for information about these error codes in the Xcode documentation window. To find error code documentation, select Documentation from the Xcode Help menu. Select Full-Text Search from the pull-down menu associated with the search field (click the magnifying glass icon to reveal the menu). Select Reference Library in the Search Groups pane at the left of the window. Type an error code number in the search field, such as 0xe0004057, and press Return. Select the most relevant entry in the search results to display the document in the lower portion of the window. Use the Find command (press Command-F) to find the error code in this document. Using the example of error code 0xe0004057, you’ll see that this error is returned when the endpoint has not been found. For help with deciphering I/O Kit error codes in general, see Technical Q&A QA1075, “Making sense of I/O Kit error codes.” Determining Which Interface Version to Use As described in “USB Devices on OS X” (page 11), the OS X USB family provides an IOUSBDeviceInterface object you use to communicate with a USB device as a whole and an IOUSBInterfaceInterface object you use to communicate with an interface in a USB device. There are a number of different versions of the USB family, however, some of which provide new versions of these interface objects. (One way to find the version of the USB family installed in your computer is to view the Finder preview information for the IOUSBFamily.kext located in /System/Library/Extensions.) This section describes how to make sure you use the correct interface object and how to view the documentation for the interface objects. The first version of the USB family was introduced in OS X v10.0 and contains the first versions of the interface objects IOUSBDeviceInterface and IOUSBInterfaceInterface. When new versions of the USB family introduce new functions for an interface object, a new version of the interface object is created, which gives access to both the new functions and all functions defined in all previous versions of that interface object. For example, the IOUSBDeviceInterface197 object provides two new functions you can use with version 1.9.7 of the USB family (available in OS X v10.2.3 and later), in addition to all functions available in the previous device interface objects IOUSBDeviceInterface187, IOUSBDeviceInterface182, and IOUSBDeviceInterface. As you develop an application that accesses a USB device or interface, you should use the latest version of the interface object that is available in the earliest version of OS X that you want to support. For example, if your application must run in OS X v10.0, you must use the IOUSBDeviceInterface and IOUSBInterfaceInterface objects. If, however, you develop an application to run in OS X v10.4 and later, you use the IOUSBDeviceInterface197 object to access the device as a whole and the USB Device Overview USB Devices on OS X 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 14IOUSBInterfaceInterface220 object to access an interface in it. This is because IOUSBDeviceInterface197 is available inOS X version 10.2.3 and later and IOUSBInterfaceInterface220 is available in OS X v10.4 and later. Note: When you view the documentation for these interface objects, notice that each version is documented separately. For example, the documentation for IOUSBDeviceInterface197 contains information about the two new functions introduced in this version, but does not repeat the documentation for the functions introduced in IOUSBDeviceInterface187, IOUSBDeviceInterface182, and IOUSBDeviceInterface. Tasks and Caveats This section presents some specific tasks your application might need to perform, along with some caveats related to USB 2.0 support of which you should be aware. Handling Stalls, Halts, and Data Toggle Resynchronization As described in “Stalls and Halts ” (page 9), stalls and halts are closely related in their effect on data transmission. To simplify the API, the USB family uses the pipe stall terminology in the names of the functions that handle these conditions: ● ClearPipeStall ● ClearPipeStallBothEnds The ClearPipeStall function operates exclusively on the host controller side, clearing the halt feature and resetting the data toggle bit to zero. If the endpoint’s halt feature and data toggle bit must be reset as well, your application must do so explicitly, using one of the ControlRequest functions to send the appropriate device request. See the documentation for the USB.h header file in I/O Kit Framework Reference for more information about standard device requests. In OS X version 10.2 and later, you can use the ClearPipeStallBothEnds function which, as its name suggests, clears the halt and resets the data toggle bit on both sides at the same time. Using the Low Latency Isochronous Functions In OS X, the time between when an isochronous transaction completes on the USB bus and when you receive your callback can stretch to tens of milliseconds. This is because the callback happens on the USB family work loop, which runs at a lower priority than some other threads in the system. In most cases, you can work around USB Device Overview Tasks and Caveats 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 15this delay by queuing read and write requests so that the next transaction is scheduled and ready to start before you receive the callback from the current transaction. In fact, this scheme is a good way to achieve higher performance whether or not low latency is a requirement of your application. In a few cases, however, queuing isochronous transactions to keep the pipe busy is not enough to prevent a latency problem that a user might notice. Consider an application that performs audio processing on some USB input (from a musical instrument, for example) before sending the processed data out to USB speakers. In this scenario, a user hears both the raw, unprocessed output of the instrument and the processed output of the speakers. Of course, some small delay between the time the instrument creates the raw sound waves and the time the speaker emits the processed sound waves is unavoidable. If this delay is greater than about 8 milliseconds, however, the user will notice. In OS X version 10.2.3 (version 1.9.2 of the USB family) the USB family solves this problem by taking advantage of the predictability of isochronous data transfers. By definition, isochronous mode guarantees the delivery of some amount of data every frame or microframe. In earlier versions of OS X, however, it was not possible to find out the exact amount of data that was transferred by a given time. This meant that an application could not begin processing the data until it received the callback associated with the transaction, telling it the transfer status and the actual amount of data that was transferred. Version 1.9.2 of the USB family introduced the LowLatencyReadIsochPipeAsync and LowLatencyWriteIsochPipeAsync functions. These functions update the frame list information (including the transferstatus and the number of bytes actually transferred) at primary interrupt time. Using these functions, an application can request that the frame list information be updated as frequently as every millisecond. This means an application can retrieve and begin processing the number of bytes actually transferred once a millisecond, without waiting for the entire transaction to complete. Important: Because these functions cause processing at primary interrupt time, it is essential you use them only if it is absolutely necessary. Overuse of these functions can cause degradation of system performance. To support the low latency isochronous read and write functions, the USB family also introduced functions to create and destroy the buffers that hold the frame list information and the data. Although you can choose to create a single data buffer and a single frame list buffer or multiple buffers of each type, you must use the LowLatencyCreateBuffer function to create them. Similarly, youmust use the LowLatencyDestroyBuffer function to destroy the buffers after you are finished with them. This restricts all necessary communication with kernel entities to the USB family. For reference documentation on the low latency isochronous functions, see the IOUSBLib.h documentation in I/O Kit Framework Reference . USB Device Overview Tasks and Caveats 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 16Errors Reported by the EHCI Hub The EHCI hub that supports high-speed devices (as well as low-speed and full-speed devices) provides coarser-grained error reporting than the OHCI hub does. For example, with an OHCI hub, you might receive an “endpoint timed out” error if you unplug the device while it is active. If you perform the same action with an EHCI hub, you might receive a “pipe stalled” error instead. The Apple EHCI hub driver cannot get more detailed error information from the hub, so it alternates between reporting “device not responding” and “pipe stalled” regardless of the actual error reported by the device. To avoid problems with your code, be sure your application does not rely on other, more specific errors to make important decisions. Changes in Isochronous Functions to Support USB 2.0 Recall that the USB 2.0 specification divides the 1-millisecond frame into eight, 125-microsecond microframes. The USB family handles this by reinterpreting some function parameters (where appropriate) and adding a couple of new functions. This section summarizes these changes; for reference documentation, see documentation for IOUSBLib.h in I/O Kit Framework Reference . The functions you use to read from and write to isochronous endpoints are ReadIsochPipeAsync and WriteIsochPipeAsync. Both functions include the following two parameters: ● numFrames—The number of frames for which to transfer data ● frameList—A pointer to an array of structures that describe the frames If you need to handle high-speed isochronous transfers, you can think of these parameters as referring to “transfer opportunities” instead of frames. In other words, numFrames can refer to a number of frames for full-speed devices or to a number of microframes for high-speed devices. Similarly, frameList specifies the list of transfers you want to occur, whether they are in terms of frames or microframes. Note: The ReadIsochPipeAsync and WriteIsochPipeAsync functions also have the frameStart parameter in common, but it does not get reinterpreted. Thisis because all isochronoustransactions, including high-speed isochronoustransactions,start on a frame boundary, not amicroframe boundary. To help you determine whether a device isfunctioning in full-speed or high-speed mode, the USB family added the GetFrameListTime function, which returns the number of microseconds in a frame. By examining the result (kUSBFullSpeedMicrosecondsInFrame or kUSBHighSpeedMicrosecondsInFrame) you can tell in which mode the device is operating. USB Device Overview Tasks and Caveats 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 17The USB family also added the GetBusMicroFrameNumber function which is similar to the GetBusFrameNumber function, except that it returns both the current frame and microframe number and includes the time at which that information was retrieved. To handle the new specification’s requirement that isochronous endpoints in a device’s default interface have a maximum packetsize of zero, the USB family added functionsthat allow you to balance bandwidth allocations among isochronous endpoints. A typical scenario is this: 1. Call GetBandwidthAvailable (available inOS X version 10.2 and later)to determine howmuch bandwidth is currently available for allocation to isochronous endpoints. 2. Call GetEndpointProperties (available in OS X version 10.2 and later) to examine the alternate settings of an interface and find one that uses an appropriate amount of bandwidth. 3. Call SetAlternateInterface (available in OS X version 10.0 and later) to create the desired interface and allocate the pipe objects. 4. Call GetPipeProperties (available in OS X version 10.0 and later) on the chosen isochronous endpoint. Thisis a very importantstep because SetAlternateInterface willsucceed, even if there is not enough bandwidth for the endpoints. Also, another device might have claimed the bandwidth that was available at the time the GetBandwidthAvailable function returned. If this happens, the maximum packet size for your chosen endpoint (contained in the maxPacketSize field) is now zero, which means that the bandwidth is no longer available. In addition, in OS X version 10.2, the USB family added the SetPipePolicy function, which allows you to relinquish bandwidth that might have been specified in an alternate setting. USB Device Access in an Intel-Based Macintosh This section provides an overview of some of the issues related to developing a universal binary version of an application that accesses a USB device. Before you read this section, be sure to read Universal Binary Programming Guidelines. That document covers architectural differences and byte-ordering formats and provides comprehensive guidelines for code modification and building universal binaries. The guidelines in that document apply to all types of applications, including those that access hardware. Before you build your application as a universal binary, make sure that: ● You port your project to GCC 4 (Xcode uses GCC 4 to target Intel-based Macintosh computers) ● You install the OS X v10.4 universal SDK ● You develop your project in Xcode 2.1 or later USB Device Overview USB Device Access in an Intel-Based Macintosh 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 18The USB bus is a little-endian bus. Structured data appears on the bus in the little-endian format regardless of the native endian format of the computer an application isrunning in. If you've developed a USB device-access application to run in a PowerPC-based Macintosh, you probably perform some byte swapping on data you read from the USB bus because the PowerPC processor uses the big-endian format. For example, the USB configuration descriptor structure contains a two-byte field that holds the descriptor length. If your PowerPC application reads this structure from the USB bus (instead of receiving it from a USB device interface function), you need to swap the value from the USB bus format (little endian) to the PowerPC format (big endian). The USB family provides several swapping macros that swap from USB to host and from host to USB (for more information on these macros, see USB.h). The Kernel framework also provides byte-swapping macros and functions you can use in high-level applications (see the OSByteOrder.h header file in libkern). If you use these macros in your application, you shouldn't have any trouble developing a universal binary version of your application. This is because these macros determine at compile time if a swap is necessary. If, however, your application uses hard-coded swaps from little endian to big endian, your application will not run correctly in an Intel-based Macintosh. As you develop a universal binary version of your application, therefore, be sure to use the USB family swapping macros or the macros in libkern/OSByteOrder.h for all byte swapping. Although you may need to perform byte swapping on values your application reads from the USB bus, you do not need to perform any byte swapping on values you pass in arguments to functions in the USB family API. You should pass argument values in the computer's host format. Likewise, any values you receive from the USB family functions will be in the computer's host format. USB Device Overview USB Device Access in an Intel-Based Macintosh 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 19This chapter describes how to develop a user-space tool that finds and communicates with an attached USB device and one of its interfaces. Important: The sample code featured in this document isintended to illustrate how to access a USB device from an application. It is not intended to provide guidance on error handling and other features required for production-quality code. Using USB Device Interfaces Applications running in OS X get access to USB devices by using I/O Kit functions to acquire a device interface, a type of plug-in that specifies functions the application can call to communicate with the device. The USB family provides two types of device interface: ● IOUSBDeviceInterface for communicating with the device itself ● IOUSBInterfaceInterface for communicating with an interface in the device Both device interfaces are defined in /System/Library/Frameworks/IOKit.framework/Headers/usb/IOUSBLib.h. Communicating with the device itself is usually only necessary when you need to set or change its configuration. For example, vendor-specific devices are often not configured because there are no default drivers that set a particular configuration. In this case, your application must use the device interface for the device to set the configuration it needs so the interfaces become available. Important: If your application is sandboxed, it must request the com.apple.security.device.usb entitlement in order to access USB devices. The process of finding and communicating with a USB device is divided into two sets of steps. The first set outlines how to find a USB device, acquire a device interface of type IOUSBDeviceInterface for it, and set or change its configuration. The second set describes how to find an interface in a device, acquire a device interface of type IOUSBInterfaceInterface for it, and use it to communicate with that interface. If you need to communicate with an unconfigured device or if you need to change a device’s configuration, you follow both sets of steps. If you need to communicate with a device that is already configured to your 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 20 Working With USB Device Interfacesspecification, you follow only the second set of steps. The sample code in “Accessing a USB Device” (page 22) follows both sets of steps and extends them to include setting up notifications it can receive when devices are dynamically added or removed. Follow this first set of steps only to set or change the configuration of a device. If the device you’re interested in is already configured for your needs, skip these steps and follow the second set of steps. 1. Find the IOUSBDevice object that represents the device in the I/O Registry. This includes setting up a matching dictionary with a key from the USB Common Class Specification (see “Finding USB Devices and Interfaces” (page 12)). The sample code usesthe key elements kUSBVendorName and kUSBProductName to find a particular USB device (this is the second key listed in Table 1-2 (page 12)). 2. Create a device interface of type IOUSBDeviceInterface for the device. This device interface provides functionsthat perform taskssuch assetting or changing the configuration of the device, getting information about the device, and resetting the device. 3. Examine the device’s configurations with GetConfigurationDescriptorPtr, choose the appropriate one, and call SetConfiguration to set the device’s configuration and instantiate the IOUSBInterface objects for that configuration. Follow thissecond set ofstepsto find and choose an interface, acquire a device interface for it, and communicate with the device. 1. Create an interface iterator to iterate over the available interfaces. 2. Create a device interface for each interface so you can examine its properties and select the appropriate one. To do this, you create a device interface of type IOUSBInterfaceInterface. This device interface providesfunctionsthat perform taskssuch as getting information about the interface,setting the interface’s alternate setting, and accessing its pipes. 3. Use the USBInterfaceOpen function to open the selected interface. This will cause the pipes associated with the interface to be instantiated so you can examine the properties of each and select the appropriate one. 4. Communicate with the device through the selected pipe. You can write to and read from the pipe synchronously or asynchronously—the sample code in “Accessing a USB Device” (page 22) shows how to do both. Working With USB Device Interfaces Using USB Device Interfaces 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 21Accessing a USB Device This section provides snippets of sample code that show how to access a Cypress EZ-USB chip with an 8051 microcontroller core. The sample code followsthe firstset ofstepsin section “Using USB Device Interfaces” (page 20) to find the Cypress EZ-USB chip in its default, unprogrammed state (also referred to as the “raw device”). It then configures the device and downloads firmware provided by Cypress to program the chip to behave as a device that echoes all information it receives on its bulk out pipe to its bulk in pipe. Once the chip has been programmed, the device nub representing the default, unprogrammed device is detached from the I/O Registry and a new device nub, representing the programmed chip, is attached. To communicate with the programmed chip (also referred to as the “bulk test device”), the sample code must perform the first set of steps again to find the device, create a device interface for it, and configure it. Then it performs the second set of steps to find an interface, create a device interface for it, and test the device. The sample code also shows how to set up notifications for the dynamic addition and removal of a device. Important: If your application is sandboxed, it must request the com.apple.security.device.usb entitlement in order to access USB devices. Definitions and Global Variables The code in the USB Notification Example uses the definitions and global variables shown in Listing 2-1 (page 22). The definition of USE_ASYNC_IO allows you to choose to use either synchronous or asynchronous calls to read from and write to the chip by commenting out the line or leaving it in, respectively. The definition of kTestMessage sets up a simple message to write to the device. The remaining definitions are specific to the Cypress EZ-USB chip. Listing 2-1 Definitions and global variables #define USE_ASYNC_IO //Comment this line out if you want to use //synchronous calls for reads and writes #define kTestMessage "Bulk I/O Test" #define k8051_USBCS 0x7f92 #define kOurVendorID 1351 //Vendor ID of the USB device #define kOurProductID 8193 //Product ID of device BEFORE it //is programmed (raw device) #define kOurProductIDBulkTest 4098 //Product ID of device AFTER it is //programmed (bulk test device) //Global variables Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 22static IONotificationPortRef gNotifyPort; static io_iterator_t gRawAddedIter; static io_iterator_t gRawRemovedIter; static io_iterator_t gBulkTestAddedIter; static io_iterator_t gBulkTestRemovedIter; static char gBuffer[64]; The main Function The main function in the USB Notification Example project (contained in the file main.c) accomplishes the following tasks. ● It establishes communication with the I/O Kit and sets up a matching dictionary to find the Cypress EZ-USB chip. ● It sets up an asynchronous notification to be called when an unprogrammed (raw) device is first attached to the I/O Registry and another to be called when the device is removed. ● It modifies the matching dictionary to find the programmed (bulk test) device. ● It sets up additional notifications to be called when the bulk test device is first attached or removed. ● It starts the run loop so the notifications that have been set up will be received. The main function uses I/O Kit functions to set up and modify a matching dictionary and set up notifications, and Core Foundation functions to set up the run loop for receiving the notifications. It calls the following functions to access both the raw device and the bulk test device. ● RawDeviceAdded, shown in Listing 2-3 (page 27), iterates over the set of matching devices and creates a device interface for each one. It calls ConfigureDevice (shown in Listing 2-5 (page 30)) to set the device’s configuration, and then DownloadToDevice (shown in Listing 2-6 (page 32)) to download the firmware to program it. ● RawDeviceRemoved,shown in Listing 2-4 (page 30), iterates over the set of matching devices and releases each one in turn. ● BulkTestDeviceAdded, shown in Listing 2-7 (page 34), iterates over the new set of matching devices, creates a device interface for each one, and calls ConfigureDevice (shown in Listing 2-5 (page 30)) to set the device’s configuration. It then calls FindInterfaces (shown in Listing 2-8 (page 36)) to get access to the interfaces on the device. ● BulkTestDeviceRemoved iterates over the new set of matching devices and releases each one in turn. This function is not shown in this chapter; see RawDeviceRemoved (Listing 2-4 (page 30)) for a nearly identical function. Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 23Listing 2-2 The main function int main (int argc, const char *argv[]) { mach_port_t masterPort; CFMutableDictionaryRef matchingDict; CFRunLoopSourceRef runLoopSource; kern_return_t kr; SInt32 usbVendor = kOurVendorID; SInt32 usbProduct = kOurProductID; // Get command line arguments, if any if (argc > 1) usbVendor = atoi(argv[1]); if (argc > 2) usbProduct = atoi(argv[2]); //Create a master port for communication with the I/O Kit kr = IOMasterPort(MACH_PORT_NULL, &masterPort); if (kr || !masterPort) { printf("ERR: Couldn’t create a master I/O Kit port(%08x)\n", kr); return -1; } //Set up matching dictionary for class IOUSBDevice and its subclasses matchingDict = IOServiceMatching(kIOUSBDeviceClassName); if (!matchingDict) { printf("Couldn’t create a USB matching dictionary\n"); mach_port_deallocate(mach_task_self(), masterPort); return -1; } //Add the vendor and product IDs to the matching dictionary. //This is the second key in the table of device-matching keys of the //USB Common Class Specification Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 24CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorName), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbVendor)); CFDictionarySetValue(matchingDict, CFSTR(kUSBProductName), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbProduct)); //To set up asynchronous notifications, create a notification port and //add its run loop event source to the program’s run loop gNotifyPort = IONotificationPortCreate(masterPort); runLoopSource = IONotificationPortGetRunLoopSource(gNotifyPort); CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode); //Retain additional dictionary references because each call to //IOServiceAddMatchingNotification consumes one reference matchingDict = (CFMutableDictionaryRef) CFRetain(matchingDict); matchingDict = (CFMutableDictionaryRef) CFRetain(matchingDict); matchingDict = (CFMutableDictionaryRef) CFRetain(matchingDict); //Now set up two notifications: one to be called when a raw device //is first matched by the I/O Kit and another to be called when the //device is terminated //Notification of first match: kr = IOServiceAddMatchingNotification(gNotifyPort, kIOFirstMatchNotification, matchingDict, RawDeviceAdded, NULL, &gRawAddedIter); //Iterate over set of matching devices to access already-present devices //and to arm the notification RawDeviceAdded(NULL, gRawAddedIter); //Notification of termination: kr = IOServiceAddMatchingNotification(gNotifyPort, kIOTerminatedNotification, matchingDict, RawDeviceRemoved, NULL, &gRawRemovedIter); Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 25//Iterate over set of matching devices to release each one and to //arm the notification RawDeviceRemoved(NULL, gRawRemovedIter); //Now change the USB product ID in the matching dictionary to match //the one the device will have after the firmware has been downloaded usbProduct = kOurProductIDBulkTest; CFDictionarySetValue(matchingDict, CFSTR(kUSBProductName), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbProduct)); //Now set up two notifications: one to be called when a bulk test device //is first matched by the I/O Kit and another to be called when the //device is terminated. //Notification of first match kr = IOServiceAddMatchingNotification(gNotifyPort, kIOFirstMatchNotification, matchingDict, BulkTestDeviceAdded, NULL, &gBulkTestAddedIter); //Iterate over set of matching devices to access already-present devices //and to arm the notification BulkTestDeviceAdded(NULL, gBulkTestAddedIter); //Notification of termination kr = IOServiceAddMatchingNotification(gNotifyPort, kIOTerminatedNotification, matchingDict, BulkTestDeviceRemoved, NULL, &gBulkTestRemovedIter); //Iterate over set of matching devices to release each one and to //arm the notification. NOTE: this function is not shown in this document. BulkTestDeviceRemoved(NULL, gBulkTestRemovedIter); //Finished with master port mach_port_deallocate(mach_task_self(), masterPort); masterPort = 0; Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 26//Start the run loop so notifications will be received CFRunLoopRun(); //Because the run loop will run forever until interrupted, //the program should never reach this point return 0; } Working With the Raw Device Now that you’ve obtained an iterator for a set of matching devices, you can use it to gain access to each raw device, configure it, and download the appropriate firmware to it. The function RawDeviceAdded (shown in Listing 2-3 (page 27)) uses I/O Kit functions to create a device interface for each device and then calls the following functions to configure the device and download firmware to it. ● ConfigureDevice, shown in Listing 2-5 (page 30), uses device interface functions to get the number of configurations, examine the first one, and set the device’s configuration. ● DownloadToDevice, shown in Listing 2-6 (page 32), downloads the firmware in bulktest.c to the device. Listing 2-3 Accessing and programming the raw device void RawDeviceAdded(void *refCon, io_iterator_t iterator) { kern_return_t kr; io_service_t usbDevice; IOCFPlugInInterface **plugInInterface = NULL; IOUSBDeviceInterface **dev = NULL; HRESULT result; SInt32 score; UInt16 vendor; UInt16 product; UInt16 release; while (usbDevice = IOIteratorNext(iterator)) { //Create an intermediate plug-in Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 27kr = IOCreatePlugInInterfaceForService(usbDevice, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score); //Don’t need the device object after intermediate plug-in is created kr = IOObjectRelease(usbDevice); if ((kIOReturnSuccess != kr) || !plugInInterface) { printf("Unable to create a plug-in (%08x)\n", kr); continue; } //Now create the device interface result = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID *)&dev); //Don’t need the intermediate plug-in after device interface //is created (*plugInInterface)->Release(plugInInterface); if (result || !dev) { printf("Couldn’t create a device interface (%08x)\n", (int) result); continue; } //Check these values for confirmation kr = (*dev)->GetDeviceVendor(dev, &vendor); kr = (*dev)->GetDeviceProduct(dev, &product); kr = (*dev)->GetDeviceReleaseNumber(dev, &release); if ((vendor != kOurVendorID) || (product != kOurProductID) || (release != 1)) { printf("Found unwanted device (vendor = %d, product = %d)\n", vendor, product); Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 28(void) (*dev)->Release(dev); continue; } //Open the device to change its state kr = (*dev)->USBDeviceOpen(dev); if (kr != kIOReturnSuccess) { printf("Unable to open device: %08x\n", kr); (void) (*dev)->Release(dev); continue; } //Configure device kr = ConfigureDevice(dev); if (kr != kIOReturnSuccess) { printf("Unable to configure device: %08x\n", kr); (void) (*dev)->USBDeviceClose(dev); (void) (*dev)->Release(dev); continue; } //Download firmware to device kr = DownloadToDevice(dev); if (kr != kIOReturnSuccess) { printf("Unable to download firmware to device: %08x\n", kr); (void) (*dev)->USBDeviceClose(dev); (void) (*dev)->Release(dev); continue; } //Close this device and release object kr = (*dev)->USBDeviceClose(dev); kr = (*dev)->Release(dev); Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 29} } The function RawDeviceRemoved simply uses the iterator obtained from the main function (shown in Listing 2-2 (page 24)) to release each device object. This also has the effect of arming the raw device termination notification so it will notify the program of future device removals. RawDeviceRemoved is shown in Listing 2-4 (page 30). Listing 2-4 Releasing the raw device objects void RawDeviceRemoved(void *refCon, io_iterator_t iterator) { kern_return_t kr; io_service_t object; while (object = IOIteratorNext(iterator)) { kr = IOObjectRelease(object); if (kr != kIOReturnSuccess) { printf("Couldn’t release raw device object: %08x\n", kr); continue; } } } Although every USB device has one or more configurations, unless the device is a composite class device that’s been matched by the AppleUSBComposite driver which automatically sets the first configuration, none of those configurations may have been set. Therefore, your application may have to use device interface functions to get the appropriate configuration value and use it to set the device’s configuration. In the sample code, the function ConfigureDevice (shown in Listing 2-5 (page 30)) accomplishes this task. In fact, it is called twice: once by RawDeviceAdded to configure the raw device and again by BulkTestDeviceAdded (shown in Listing 2-7 (page 34)) to configure the bulk test device. Listing 2-5 Configuring a USB device IOReturn ConfigureDevice(IOUSBDeviceInterface **dev) Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 30{ UInt8 numConfig; IOReturn kr; IOUSBConfigurationDescriptorPtr configDesc; //Get the number of configurations. The sample code always chooses //the first configuration (at index 0) but your code may need a //different one kr = (*dev)->GetNumberOfConfigurations(dev, &numConfig); if (!numConfig) return -1; //Get the configuration descriptor for index 0 kr = (*dev)->GetConfigurationDescriptorPtr(dev, 0, &configDesc); if (kr) { printf("Couldn’t get configuration descriptor for index %d (err = %08x)\n", 0, kr); return -1; } //Set the device’s configuration. The configuration value is found in //the bConfigurationValue field of the configuration descriptor kr = (*dev)->SetConfiguration(dev, configDesc->bConfigurationValue); if (kr) { printf("Couldn’t set configuration to value %d (err = %08x)\n", 0, kr); return -1; } return kIOReturnSuccess; } Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 31Now that the device is configured, you can download firmware to it. Cypress makes firmware available to program the EZ-USB chip to emulate different devices. The sample code in this document uses firmware that programs the chip to be a bulk test device, a device that takes the data it receives from its bulk out pipe and echoesit to its bulk in pipe. The firmware, contained in the file bulktest.c, is an array of INTEL_HEX_RECORD structures (defined in the file hex2c.h). The function DownloadToDevice uses the function WriteToDevice (shown together in Listing 2-6 (page 32)) to prepare the device to receive the download and then to write information from each structure to the appropriate address on the device. When all the firmware has been downloaded, DownloadToDevice calls WriteToDevice a last time to inform the device that the download is complete. At this point, the raw device detaches itself from the bus and reattaches as a bulk test device. This causes the device nub representing the raw device to be removed from the I/O Registry and a new device nub, representing the bulk test device, to be attached. Listing 2-6 Two functions to download firmware to the raw device IOReturn DownloadToDevice(IOUSBDeviceInterface **dev) { int i; UInt8 writeVal; IOReturn kr; //Assert reset. This tells the device that the download is //about to occur writeVal = 1; //For this device, a value of 1 indicates a download kr = WriteToDevice(dev, k8051_USBCS, 1, &writeVal); if (kr != kIOReturnSuccess) { printf("WriteToDevice reset returned err 0x%x\n", kr); (*dev)->USBDeviceClose(dev); (*dev)->Release(dev); return kr; } //Download firmware i = 0; while (bulktest[i].Type == 0) //While bulktest[i].Type == 0, this is Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 32{ //not the last firmware record to //download kr = WriteToDevice(dev, bulktest[i].Address, bulktest[i].Length, bulktest[i].Data); if (kr != kIOReturnSuccess) { printf("WriteToDevice download %i returned err 0x%x\n", i, kr); (*dev)->USBDeviceClose(dev); (*dev)->Release(dev); return kr; } i++; } //De-assert reset. This tells the device that the download is complete writeVal = 0; kr = WriteToDevice(dev, k8051_USBCS, 1, &writeVal); if (kr != kIOReturnSuccess) printf("WriteToDevice run returned err 0x%x\n", kr); return kr; } IOReturn WriteToDevice(IOUSBDeviceInterface **dev, UInt16 deviceAddress, UInt16 length, UInt8 writeBuffer[]) { IOUSBDevRequest request; request.bmRequestType = USBmakebmRequestType(kUSBOut, kUSBVendor, kUSBDevice); request.bRequest = 0xa0; request.wValue = deviceAddress; request.wIndex = 0; Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 33request.wLength = length; request.pData = writeBuffer; return (*dev)->DeviceRequest(dev, &request); } Working With the Bulk Test Device After you download the firmware to the device, the raw device is no longer attached to the bus. To gain access to the bulk test device, you repeat most of the same steps you used to get access to the raw device. ● Use the iterator obtained by a call to IOServiceAddMatchingNotification in the main function (shown in Listing 2-2 (page 24)) to iterate over a set of matching devices. ● Create a device interface for each device. ● Configure the device. This time, however, the next step is to find the interfaces on the device so you can choose the appropriate one and get access to its pipes. Because of the similarities of these tasks, the function BulkTestDeviceAdded follows the same outline of the RawDeviceAdded function except that instead of downloading firmware to the device, it calls FindInterfaces (shown in Listing 2-8 (page 36)) to examine the available interfaces and their pipes. The code in Listing 2-7 (page 34) replaces most of the BulkTestDeviceAdded function’s code with comments, focusing on the differences between it and the RawDeviceAdded function. Listing 2-7 Accessing the bulk test device void BulkTestDeviceAdded(void *refCon, io_iterator_t iterator) { kern_return_t kr; io_service_t usbDevice; IOUSBDeviceInterface **device=NULL; while (usbDevice = IOIteratorNext(iterator)) { //Create an intermediate plug-in using the //IOCreatePlugInInterfaceForService function //Release the device object after getting the intermediate plug-in Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 34//Create the device interface using the QueryInterface function //Release the intermediate plug-in object //Check the vendor, product, and release number values to //confirm we’ve got the right device //Open the device before configuring it kr = (*device)->USBDeviceOpen(device); //Configure the device by calling ConfigureDevice //Close the device and release the device interface object if //the configuration is unsuccessful //Get the interfaces kr = FindInterfaces(device); if (kr != kIOReturnSuccess) { printf("Unable to find interfaces on device: %08x\n", kr); (*device)->USBDeviceClose(device); (*device)->Release(device); continue; } //If using synchronous IO, close and release the device interface here #ifndef USB_ASYNC_IO kr = (*device)->USBDeviceClose(device); kr = (*device)->Release(device); #endif } } Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 35The function BulkTestDeviceRemoved simply uses the iterator obtained from the main function (shown in Listing 2-2 (page 24)) to release each device object. This also has the effect of arming the bulk test device termination notification so it will notify the program of future device removals.The BulkTestDeviceRemoved function is identical to the RawDeviceRemoved function (shown in Listing 2-4 (page 30)), with the exception of the wording of the printed error statement. Working With Interfaces Now that you’ve configured the device, you have access to its interfaces. The FindInterfaces function (shown in Listing 2-8 (page 36)) creates an iterator to iterate over all interfaces on the device and then creates a device interface to communicate with each one. For each interface found, the function opens the interface, determines how many endpoints (or pipes) it has, and prints out the properties of each pipe. Because opening an interface causes its pipes to be instantiated, you can get access to any pipe by using its pipe index. The pipe index is the number of the pipe within the interface, ranging from one to the number of endpoints returned by GetNumEndpoints. You can communicate with the default control pipe (described in “USB Transfer Types” (page 8)) from any interface by using pipe index 0, but it is usually better to use the device interface functions for the device itself (see the use of IOUSBDeviceInterface functions in Listing 2-5 (page 30)). The sample code employs conditional compilation using #ifdef and #ifndef to demonstrate both synchronous and asynchronous I/O. If you’ve chosen to test synchronous I/O, FindInterfaces writes the test message (defined in Listing 2-1 (page 22)) to pipe index 2 on the device and readsits echo before returning. For asynchronous I/O, FindInterfaces first creates an event source and adds it to the run loop created by the main function (shown in Listing 2-2 (page 24)). It then sets up an asynchronous write and read that will cause a notification to be sent upon completion. The completion functions WriteCompletion and ReadCompletion are shown together in Listing 2-9 (page 43). Listing 2-8 Finding interfaces on the bulk test device IOReturn FindInterfaces(IOUSBDeviceInterface **device) { IOReturn kr; IOUSBFindInterfaceRequest request; io_iterator_t iterator; io_service_t usbInterface; IOCFPlugInInterface **plugInInterface = NULL; IOUSBInterfaceInterface **interface = NULL; HRESULT result; SInt32 score; Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 36UInt8 interfaceClass; UInt8 interfaceSubClass; UInt8 interfaceNumEndpoints; int pipeRef; #ifndef USE_ASYNC_IO UInt32 numBytesRead; UInt32 i; #else CFRunLoopSourceRef runLoopSource; #endif //Placing the constant kIOUSBFindInterfaceDontCare into the following //fields of the IOUSBFindInterfaceRequest structure will allow you //to find all the interfaces request.bInterfaceClass = kIOUSBFindInterfaceDontCare; request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare; request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare; request.bAlternateSetting = kIOUSBFindInterfaceDontCare; //Get an iterator for the interfaces on the device kr = (*device)->CreateInterfaceIterator(device, &request, &iterator); while (usbInterface = IOIteratorNext(iterator)) { //Create an intermediate plug-in kr = IOCreatePlugInInterfaceForService(usbInterface, kIOUSBInterfaceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score); //Release the usbInterface object after getting the plug-in kr = IOObjectRelease(usbInterface); if ((kr != kIOReturnSuccess) || !plugInInterface) { printf("Unable to create a plug-in (%08x)\n", kr); Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 37break; } //Now create the device interface for the interface result = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), (LPVOID *) &interface); //No longer need the intermediate plug-in (*plugInInterface)->Release(plugInInterface); if (result || !interface) { printf("Couldn’t create a device interface for the interface (%08x)\n", (int) result); break; } //Get interface class and subclass kr = (*interface)->GetInterfaceClass(interface, &interfaceClass); kr = (*interface)->GetInterfaceSubClass(interface, &interfaceSubClass); printf("Interface class %d, subclass %d\n", interfaceClass, interfaceSubClass); //Now open the interface. This will cause the pipes associated with //the endpoints in the interface descriptor to be instantiated kr = (*interface)->USBInterfaceOpen(interface); if (kr != kIOReturnSuccess) { printf("Unable to open interface (%08x)\n", kr); (void) (*interface)->Release(interface); break; Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 38} //Get the number of endpoints associated with this interface kr = (*interface)->GetNumEndpoints(interface, &interfaceNumEndpoints); if (kr != kIOReturnSuccess) { printf("Unable to get number of endpoints (%08x)\n", kr); (void) (*interface)->USBInterfaceClose(interface); (void) (*interface)->Release(interface); break; } printf("Interface has %d endpoints\n", interfaceNumEndpoints); //Access each pipe in turn, starting with the pipe at index 1 //The pipe at index 0 is the default control pipe and should be //accessed using (*usbDevice)->DeviceRequest() instead for (pipeRef = 1; pipeRef <= interfaceNumEndpoints; pipeRef++) { IOReturn kr2; UInt8 direction; UInt8 number; UInt8 transferType; UInt16 maxPacketSize; UInt8 interval; char *message; kr2 = (*interface)->GetPipeProperties(interface, pipeRef, &direction, &number, &transferType, &maxPacketSize, &interval); if (kr2 != kIOReturnSuccess) printf("Unable to get properties of pipe %d (%08x)\n", pipeRef, kr2); else Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 39{ printf("PipeRef %d: ", pipeRef); switch (direction) { case kUSBOut: message = "out"; break; case kUSBIn: message = "in"; break; case kUSBNone: message = "none"; break; case kUSBAnyDirn: message = "any"; break; default: message = "???"; } printf("direction %s, ", message); switch (transferType) { case kUSBControl: message = "control"; break; case kUSBIsoc: message = "isoc"; break; case kUSBBulk: message = "bulk"; break; case kUSBInterrupt: message = "interrupt"; Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 40break; case kUSBAnyType: message = "any"; break; default: message = "???"; } printf("transfer type %s, maxPacketSize %d\n", message, maxPacketSize); } } #ifndef USE_ASYNC_IO //Demonstrate synchronous I/O kr = (*interface)->WritePipe(interface, 2, kTestMessage, strlen(kTestMessage)); if (kr != kIOReturnSuccess) { printf("Unable to perform bulk write (%08x)\n", kr); (void) (*interface)->USBInterfaceClose(interface); (void) (*interface)->Release(interface); break; } printf("Wrote \"%s\" (%ld bytes) to bulk endpoint\n", kTestMessage, (UInt32) strlen(kTestMessage)); numBytesRead = sizeof(gBuffer) - 1; //leave one byte at the end //for NULL termination kr = (*interface)->ReadPipe(interface, 9, gBuffer, &numBytesRead); if (kr != kIOReturnSuccess) { printf("Unable to perform bulk read (%08x)\n", kr); (void) (*interface)->USBInterfaceClose(interface); (void) (*interface)->Release(interface); Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 41break; } //Because the downloaded firmware echoes the one’s complement of the //message, now complement the buffer contents to get the original data for (i = 0; i < numBytesRead; i++) gBuffer[i] = ~gBuffer[i]; printf("Read \"%s\" (%ld bytes) from bulk endpoint\n", gBuffer, numBytesRead); #else //Demonstrate asynchronous I/O //As with service matching notifications, to receive asynchronous //I/O completion notifications, you must create an event source and //add it to the run loop kr = (*interface)->CreateInterfaceAsyncEventSource( interface, &runLoopSource); if (kr != kIOReturnSuccess) { printf("Unable to create asynchronous event source (%08x)\n", kr); (void) (*interface)->USBInterfaceClose(interface); (void) (*interface)->Release(interface); break; } CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode); printf("Asynchronous event source added to run loop\n"); bzero(gBuffer, sizeof(gBuffer)); strcpy(gBuffer, kTestMessage); kr = (*interface)->WritePipeAsync(interface, 2, gBuffer, strlen(gBuffer), WriteCompletion, (void *) interface); if (kr != kIOReturnSuccess) Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 42{ printf("Unable to perform asynchronous bulk write (%08x)\n", kr); (void) (*interface)->USBInterfaceClose(interface); (void) (*interface)->Release(interface); break; } #endif //For this test, just use first interface, so exit loop break; } return kr; } When an asynchronous write action is complete, the WriteCompletion function is called by the notification. WriteCompletion then calls the interface function ReadPipeAsync to perform an asynchronous read from the pipe. When the read is complete, control passes to ReadCompletion which simply prints status messages and adds a NULL termination to the global buffer containing the test message read from the device. The WriteCompletion and ReadCompletion functions are shown together in Listing 2-9 (page 43). Listing 2-9 Two asynchronous I/O completion functions void WriteCompletion(void *refCon, IOReturn result, void *arg0) { IOUSBInterfaceInterface **interface = (IOUSBInterfaceInterface **) refCon; UInt32 numBytesWritten = (UInt32) arg0; UInt32 numBytesRead; printf("Asynchronous write complete\n"); if (result != kIOReturnSuccess) { printf("error from asynchronous bulk write (%08x)\n", result); (void) (*interface)->USBInterfaceClose(interface); (void) (*interface)->Release(interface); return; } Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 43printf("Wrote \"%s\" (%ld bytes) to bulk endpoint\n", kTestMessage, numBytesWritten); numBytesRead = sizeof(gBuffer) - 1; //leave one byte at the end for //NULL termination result = (*interface)->ReadPipeAsync(interface, 9, gBuffer, numBytesRead, ReadCompletion, refCon); if (result != kIOReturnSuccess) { printf("Unable to perform asynchronous bulk read (%08x)\n", result); (void) (*interface)->USBInterfaceClose(interface); (void) (*interface)->Release(interface); return; } } void ReadCompletion(void *refCon, IOReturn result, void *arg0) { IOUSBInterfaceInterface **interface = (IOUSBInterfaceInterface **) refCon; UInt32 numBytesRead = (UInt32) arg0; UInt32 i; printf("Asynchronous bulk read complete\n"); if (result != kIOReturnSuccess) { printf("error from async bulk read (%08x)\n", result); (void) (*interface)->USBInterfaceClose(interface); (void) (*interface)->Release(interface); return; } //Check the complement of the buffer’s contents for original data for (i = 0; i < numBytesRead; i++) gBuffer[i] = ~gBuffer[i]; Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 44printf("Read \"%s\" (%ld bytes) from bulk endpoint\n", gBuffer, numBytesRead); } Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 45This table describes the changes to USB Device Interface Guide . Date Notes 2012-01-09 Added information about App Sandbox. 2007-09-04 Made minor corrections. Described how to determine which version of an interface object to use when accessing a USB device or interface. 2007-02-08 2006-04-04 Made minor corrections. Emphasized which type of device interface to get for USB devices and interfaces and clarified definition of composite class device. 2006-03-08 2005-11-09 Made minor corrections. Added information about creating a universal binary for an application that accesses a USB device. 2005-09-08 2005-08-11 Made minor bug fixes. Added information about low latency isochronous transactions and functions. 2005-06-04 Included discussion of USB 2.0 and associated changes to isochronous functions. Changed title from "Working With USB Device Interfaces." 2005-04-29 2004-05-27 Fixed URL for USB Common Class Specification. 2002-11-15 First version. 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 46 Document Revision HistoryApple Inc. © 2002, 2012 Apple Inc. All rights reserved. No part of this publication may be reproduced, stored in a retrievalsystem, or transmitted, in any form or by any means, mechanical, electronic, photocopying, recording, or otherwise, without prior written permission of Apple Inc., with the following exceptions: Any person is hereby authorized to store documentation on a single computer for personal use only and to print copies of documentation for personal use provided that the documentation contains Apple’s copyright notice. No licenses, express or implied, are granted with respect to any of the technology described in this document. Apple retains all intellectual property rights associated with the technology described in this document. This document is intended to assist application developers to develop applications only for Apple-labeled computers. Apple Inc. 1 Infinite Loop Cupertino, CA 95014 408-996-1010 Apple, the Apple logo, Finder, Mac, Macintosh, OS X, Pages, Sand, and Xcode are trademarks of Apple Inc., registered in the U.S. and other countries. Intel and Intel Core are registered trademarks of Intel Corporation or its subsidiaries in the United States and other countries. PowerPC and the PowerPC logo are trademarks of International Business Machines Corporation, used under license therefrom. Even though Apple has reviewed this document, APPLE MAKES NO WARRANTY OR REPRESENTATION, EITHER EXPRESS OR IMPLIED, WITH RESPECT TO THIS DOCUMENT, ITS QUALITY, ACCURACY, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.ASARESULT, THISDOCUMENT IS PROVIDED “AS IS,” AND YOU, THE READER, ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND ACCURACY. IN NO EVENT WILL APPLE BE LIABLE FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL,OR CONSEQUENTIAL DAMAGES RESULTING FROM ANY DEFECT OR INACCURACY IN THIS DOCUMENT, even if advised of the possibility of such damages. THE WARRANTY AND REMEDIES SET FORTH ABOVE ARE EXCLUSIVE AND IN LIEU OF ALL OTHERS, ORAL OR WRITTEN, EXPRESS OR IMPLIED. No Apple dealer, agent, or employee is authorized to make any modification, extension, or addition to this warranty. Some states do not allow the exclusion or limitation of implied warranties or liability for incidental or consequential damages, so the above limitation or exclusion may not apply to you. This warranty gives you specific legal rights, and you may also have other rights which vary from state to state. Core Data Model Versioning and Data Migration Programming GuideContents Core Data Model Versioning and Data Migration 5 At a Glance 5 Prerequisites 6 Understanding Versions 7 Model File Format and Versions 10 Lightweight Migration 12 Core Data Must Be Able to Infer the Mapping 12 Request Automatic Migration Using an Options Dictionary 13 Use a Migration Manager if Models Cannot Be Found Automatically 14 Mapping Overview 17 Mapping Model Objects 17 Creating a Mapping Model in Xcode 19 The Migration Process 20 Overview 20 Requirements for the Migration Process 20 Custom Entity Migration Policies 21 Three-Stage Migration 21 Initiating the Migration Process 23 Initiating the Migration Process 23 The Default Migration Process 24 Customizing the Migration Process 26 Is Migration Necessary 26 Initializing a Migration Manager 27 Performing a Migration 28 Multiple Passes—Dealing With Large Datasets 29 Migration and iCloud 30 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 2Document Revision History 31 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 3 ContentsFigures and Listings Understanding Versions 7 Figure 1-1 Recipes models “Version 1.0” 7 Figure 1-2 Recipes model “Version 1.1” 7 Figure 1-3 Recipes model “Version 2.0” 8 Model File Format and Versions 10 Figure 2-1 Initial version of the Core Recipes model 10 Figure 2-2 Version 2 of the Core Recipes model 11 Mapping Overview 17 Figure 4-1 Mapping model for versions 1-2 of the Core Recipes models 19 Initiating the Migration Process 23 Listing 6-1 Opening a store using automatic migration 24 Customizing the Migration Process 26 Listing 7-1 Checking whether migration is necessary 26 Listing 7-2 Initializing a Migration Manager 27 Listing 7-3 Performing a Migration 28 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 4Core Data provides support for managing changes to a managed object model as your application evolves. You can only open a Core Data store using the managed object model used to create it. Changing a model will therefore make it incompatible with (and so unable to open) the stores it previously created. If you change your model, you therefore need to change the data in existing stores to new version—changing the store format is known as migration. To migrate a store, you need both the version of the model used to create it, and the current version of the model you want to migrate to. You can create a versioned model that contains more than one version of a managed object model. Within the versioned model you mark one version as being the current version. Core Data can then use this model to open persistent stores created using any of the model versions, and migrate the stores to the current version. To help Core Data perform the migration, though, you may have to provide information about how to map from one version of the model to another. This information may be in the form of hints within the versioned model itself, or in a separate mapping model file that you create. At a Glance Typically, as it evolves from one version to another, numerous aspects of your application change: the classes you implement, the user interface, the file format, and so on. You need to be aware of and in control of all these aspects; there is no API that solves the problems associated with all these—for example Cocoa does not provide a means to automatically update your user interface if you add a new attribute to an entity in your managed object model. Core Data does not solve all the issues of how you roll out your application. It does, though, provide support for a small—but important and non-trivial—subset of the tasks you must perform as your application evolves. ● Model versioning allows you to specify and distinguish between different configurations of your schema. There are two distinct views of versioning: your perspective as a developer, and Core Data’s perspective. These may not always be the same. The differences are discussed in “Understanding Versions” (page 7). The format of a versioned managed object model, and how you add a version to a model, is discussed in “Model File Format and Versions” (page 10). ● Core Data needs to know how to map from the entities and properties in a source model to the entities and properties in the destination model. 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 5 Core Data Model Versioning and Data MigrationIn many cases, Core Data can infer the mapping from existing versions of the managed object model. This is described in “Lightweight Migration” (page 12). If you make changes to your models such that Core Data cannot infer the mapping from source to destination, you need to create a mapping model. A mapping model parallels a managed object model, specifying how to transform objects in the source into instances appropriate for the destination. How you create a mapping model is discussed in “Mapping Overview” (page 17). ● Data migration allows you to convert data from one model (schema) to another, using mappings. The migration process itself is discussed in “The Migration Process” (page 20). How you perform a migration is discussed in “Initiating the Migration Process” (page 23). You can also customize the migration process—that is, how you programmatically determine whether migration is necessary; how you find the correct source and destination models and the appropriate mapping model to initialize the migration manager; and then how you perform the migration. You only customize the migration process if you want to initiate migration yourself. You might do this to, for example, search locations other than the application’s main bundle for models or to deal with large data sets by performing the migration in several passes using different mapping models. How you can customize the process is described in “Customizing the Migration Process” (page 26). ● If you are using iCloud, there are some constraints on what migration you can perform. If you are using iCloud, you must use lightweight migration. Other factors to be aware of are described in “Migration and iCloud” (page 30). Although Core Data makes versioning and migration easier than would typically otherwise be the case, these processes are still non-trivial in effect. You still need to carefully consider the implications of releasing and supporting different versions of your application. Prerequisites This document assumes that you are familiar with the Core Data architecture and the fundamentals of using Core Data. You should be able to identify the parts of the Core Data stack and understand the roles of the model, the managed object context, and the persistent store coordinator. You need to know how to create a managed object model, how to create and programmatically interact with parts of the Core Data stack. If you do not meet these requirements, you should first read the Core Data Programming Guide and related materials. You are strongly encouraged also to work through the Core Data Utility Tutorial . Core Data Model Versioning and Data Migration Prerequisites 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 6There are two distinct views of versioning: your perspective as a developer, and Core Data’s perspective. These may not always be the same—consider the following models. Figure 1-1 Recipes models “Version 1.0” Recipe Attributes cuisine directions name Relationships chef ingredients Chef Attributes name training Relationships recipes Ingredient Attributes amount name Relationships recipes Figure 1-2 Recipes model “Version 1.1” Recipe Attributes cuisine directions name Relationships chef ingredients Chef Attributes name training Relationships recipes Ingredient Attributes amount name Relationships recipes Recipe changes: • Add validation rules • Change User Info values • Use custom class 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 7 Understanding VersionsFigure 1-3 Recipes model “Version 2.0” Recipe Attributes directions name rating Relationships chef cuisines ingredients Chef Attributes firstName lastName Relationships recipes Ingredient Attributes amount name Relationships recipe Cuisine Attributes name Relationships recipes As a developer, your perspective is typically that a version is denoted by an identifier—a string or number, such as “9A218”, “2.0.7”, or “Version 1.1”. To support this view, managed object models have a set of identifiers (see versionIdentifiers)—typically for a single model you provide a single string (the attribute itself is a set so that if models are merged all the identifiers can be preserved). How the identifier should be interpreted is up to you, whether it represents the version number of the application, the version that was committed prior to going on vacation, or the last submission before it stopped working. Core Data, on the other hand, treats these identifiers simply as “hints”. To understand why, recall that the format of a persistent store is dependent upon the model used to create it, and that to open a persistent store you must have a model that is compatible with that used to create it. Consider then what would happen if you changed the model but not the identifier—for example, if you kept the identifier the same but removed one entity and added two others. To Core Data, the change in the schema is significant, the fact that the identifier did not change is irrelevant. Core Data’s perspective on versioning isthat it is only interested in features of the model that affect persistence. This means that for two models to be compatible: ● For each entity the following attributes must be equal: name, parent, isAbstract, and properties. className, userInfo, and validation predicates are not compared. ● For each property in each entity, the following attributes must be equal: name, isOptional, isTransient, isReadOnly, for attributes attributeType, and for relationships destinationEntity, minCount, maxCount, deleteRule, and inverseRelationship. userInfo and validation predicates are not compared. Notice that Core Data ignores any identifiers you set. In the examples above, Core Data treats version 1.0 (Figure 1-1 (page 7)) and 1.1 (Figure 1-2 (page 7)) as being compatible. Understanding Versions 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 8Rather than enumerating through all the relevant parts of a model, Core Data creates a 32-byte hash digest of the components which it compares for equality (see versionHash (NSEntityDescription) and versionHash (NSPropertyDescription)). These hashes are included in a store’s metadata so that Core Data can quickly determine whether the store format matches that of the managed object model it may use to try to open the store. (When you attempt to open a store using a given model, Core Data compares the version hashes of each of the entities in the store with those of the entities in the model, and if all are the same then the store is opened.) There is typically no reason for you to be interested in the value of a hash. There may, however, be some situations in which you have two versions of a model that Core Data would normally treat as equivalent that you want to be recognized as being different. For example, you might change the name of the class used to represent an entity, or more subtly you might keep the model the same but change the internal format of an attribute such as a BLOB—this is irrelevant to Core Data, but it is crucial for the integrity of your data. To support this, Core Data allows you to set a hash modifier for an entity or property see versionHashModifier (NSEntityDescription) and versionHashModifier (NSPropertyDescription). In the examples above, if you wanted to force Core Data to recognize that “Version 1.0” (Figure 1-1 (page 7)) and “Version 1.1” (Figure 1-2 (page 7)) of your models are different, you could set an entity modifier for the Recipe entity in the second model to change the version hash Core Data creates. Understanding Versions 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 9A managed object model that supports versioning is represented in the filesystem by a .xcdatamodeld document. An .xcdatamodeld document is a file package (see “Document Packages”) that groups versions of the model, each represented by an individual .xcdatamodel file, and an Info.plist file that contains the version information. The model is compiled into a runtime format—a file package with a .momd extension that containsindividually compiled model files with a .mom extension. You load the .momd model bundle using NSManagedObjectModel’s initWithContentsOfURL:. To add a version to a model, you start with a model such as that illustrated in Figure 2-1. Figure 2-1 Initial version of the Core Recipes model 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 10 Model File Format and VersionsTo add a version, select Editor > Add Model Version. In the sheet that appears, you enter the name of the new model version and select the model on which it should be based. To set the new model asthe current version of the model,select the .xcdatamodeld document in the project navigator, then select the new model in the pop-up menu in the Versioned Core Data Model area in the Attributes Inspector (see Figure 2-2). Figure 2-2 Version 2 of the Core Recipes model Model File Format and Versions 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 11If you just make simple changes to your model (such as adding a new attribute to an entity), Core Data can perform automatic data migration, referred to aslightweightmigration. Lightweight migration isfundamentally the same as ordinary migration, except that instead of you providing a mapping model (as described in “Mapping Overview” (page 17)), Core Data infers one from differences between the source and destination managed object models. Lightweight migration is especially convenient during early stages of application development, when you may be changing your managed object model frequently, but you don’t want to have to keep regenerating test data. You can migrate existing data without having to create a custom mapping model for every model version used to create a store that would need to be migrated. A further advantage of using lightweight migration—beyond the fact that you don’t need to create the mapping model yourself—is that if you use an inferred model and you use the SQLite store, then Core Data can perform the migration in situ (solely by issuing SQL statements). This can represent a significant performance benefit as Core Data doesn’t have to load any of your data. Because of this, you are encouraged to use inferred migration where possible, even if the mapping model you might create yourself would be trivial. Core Data Must Be Able to Infer the Mapping To perform automatic lightweight migration, Core Data needs to be able to find the source and destination managed object models itself at runtime. Core Data looks for models in the bundles returned by NSBundle’s allBundles and allFrameworks methods. If you store your models elsewhere, you must follow the steps described in “Use a Migration Manager if Models Cannot Be Found Automatically ” (page 14). Core Data must then analyze the schema changes to persistent entities and properties and generate an inferred mapping model. For Core Data to be able to generate an inferred mapping model, changes must fit an obvious migration pattern, for example: ● Simple addition of a new attribute ● Removal of an attribute ● A non-optional attribute becoming optional ● An optional attribute becoming non-optional, and defining a default value 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 12 Lightweight Migration● Renaming an entity or property If you rename an entity or property, you can set the renaming identifier in the destination model to the name of the corresponding property or entity in the source model. You set the renaming identifier in the managed object model using the Xcode Data Modeling tool’s property inspector (for either an entity or a property). For example, you can: ● Rename a Car entity to Automobile ● Rename a Car’s color attribute to paintColor The renaming identifier creates a “canonical name,” so you should set the renaming identifier to the name of the property in the source model (unless that property already has a renaming identifier). This means you can rename a property in version 2 of a model then rename it again version 3, and the renaming will work correctly going from version 2 to version 3 or from version 1 to version 3. In addition, Core Data supports: ● Adding relationships and changing the type of relationship ● You can add a new relationship or delete an existing relationship. ● Renaming a relationship (by using a renaming identifier, just like an attribute) ● Changing a relationship from a to-one to a to-many, or a non-ordered to-many to ordered (and visa-versa) ● Changing the entity hierarchy ● You can add, remove, rename entities ● You can create a new parent or child entity and move properties up and down the entity hierarchy ● You can move entities out of a hierarchy You cannot, however, merge entity hierarchies; if two existing entities do not share a common parent in the source, they cannot share a common parent in the destination Request Automatic Migration Using an Options Dictionary You request automatic lightweight migration using the options dictionary you pass in addPersistentStoreWithType:configuration:URL:options:error:, by setting values corresponding to both the NSMigratePersistentStoresAutomaticallyOption and the NSInferMappingModelAutomaticallyOption keys to YES: NSError *error = nil; Lightweight Migration Request Automatic Migration Using an Options Dictionary 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 13NSURL *storeURL = <#The URL of a persistent store#>; NSPersistentStoreCoordinator *psc = <#The coordinator#>; NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil]; BOOL success = [psc addPersistentStoreWithType:<#Store type#> configuration:<#Configuration or nil#> URL:storeURL options:options error:&error]; if (!success) { // Handle the error. } If you want to determine in advance whether Core Data can infer the mapping between the source and destination models without actually doing the work of migration, you can use NSMappingModel’s inferredMappingModelForSourceModel:destinationModel:error: method. Thisreturnsthe inferred model if Core Data is able to create it, otherwise nil. Use a Migration Manager if Models Cannot Be Found Automatically To perform automatic migration, Core Data has to be able to find the source and destination managed object models itself at runtime (see “Core Data Must Be Able to Infer the Mapping” (page 12)). If you need to put your models in the locations not checked by automatic discovery, then you need to generate the inferred model and initiate the migration yourself using a migration manager (an instance of NSMigrationManager). The following code sample illustrates how to generate an inferred model and initiate the migration using a migration manager. The code assumes that you have implemented two methods—sourceModel and destinationModel—that return the source and destination managed object models respectively. - (BOOL)migrateStore:(NSURL *)storeURL toVersionTwoStore:(NSURL *)dstStoreURL error:(NSError **)outError { // Try to get an inferred mapping model. NSMappingModel *mappingModel = [NSMappingModel inferredMappingModelForSourceModel:[self sourceModel] destinationModel:[self destinationModel] error:outError]; Lightweight Migration Use a Migration Manager if Models Cannot Be Found Automatically 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 14// If Core Data cannot create an inferred mapping model, return NO. if (!mappingModel) { return NO; } // Create a migration manager to perform the migration. NSMigrationManager *manager = [[NSMigrationManager alloc] initWithSourceModel:[self sourceModel] destinationModel:[self destinationModel]]; BOOL success = [manager migrateStoreFromURL:storeURL type:NSSQLiteStoreType options:nil withMappingModel:mappingModel toDestinationURL:dstStoreURL destinationType:NSSQLiteStoreType destinationOptions:nil error:outError]; return success; } Lightweight Migration Use a Migration Manager if Models Cannot Be Found Automatically 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 15Note: Prior to OS X v10.7 and iOS 4, you need to use a store-specific migration manager to perform lightweight migration. You get the migration manager for a given persistent store type using migrationManagerClass, as illustrated in the following example. - (BOOL)migrateStore:(NSURL *)storeURL toVersionTwoStore:(NSURL *)dstStoreURL error:(NSError **)outError { // Try to get an inferred mapping model. NSMappingModel *mappingModel = [NSMappingModel inferredMappingModelForSourceModel:[self sourceModel] destinationModel:[self destinationModel] error:outError]; // If Core Data cannot create an inferred mapping model, return NO. if (!mappingModel) { return NO; } // Get the migration manager class to perform the migration. NSValue *classValue = [[NSPersistentStoreCoordinator registeredStoreTypes] objectForKey:NSSQLiteStoreType]; Class sqliteStoreClass = (Class)[classValue pointerValue]; Class sqliteStoreMigrationManagerClass = [sqliteStoreClass migrationManagerClass]; NSMigrationManager *manager = [[sqliteStoreMigrationManagerClass alloc] initWithSourceModel:[self sourceModel] destinationModel:[self destinationModel]]; BOOL success = [manager migrateStoreFromURL:storeURL type:NSSQLiteStoreType options:nil withMappingModel:mappingModel toDestinationURL:dstStoreURL destinationType:NSSQLiteStoreType destinationOptions:nil error:outError]; return success; } Lightweight Migration Use a Migration Manager if Models Cannot Be Found Automatically 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 16In many cases, Core Data may be able to infer how to transform data from one schema to another (see “Lightweight Migration” (page 12). If Core Data cannot infer the mapping from one model to another, you need a definition of how to perform the transformation. This information is captured in a mapping model. A mapping model is a collection of objects that specifies the transformations that are required to migrate part of a store from one version of your model to another (for example, that one entity is renamed, an attribute is added to another, and a third split into two). You typically create a mapping model in Xcode. Much as the managed object model editor allows you to graphically create the model, the mapping model editor allows you to customize the mappings between the source and destination entities and properties. Mapping Model Objects Like a managed object model, a mapping model is a collection of objects. Mapping model classes parallel the managed object model classes—there are mapping classes for a model, an entity, and a property (NSMappingModel, NSEntityMapping, and NSPropertyMapping respectively). ● An instance of NSEntityMapping specifies a source entity, a destination entity (the type of object to create to correspond to the source object) and mapping type (add, remove, copy as is, or transform). ● An instance of NSPropertyMapping specifiesthe name of the property in the source and in the destination entity, and a value expression to create the value for the destination property. The model does not contain instances of NSEntityMigrationPolicy or any of its subclasses, however amongst other attributes instance of NSEntityMapping can specify the name of an entity migration policy class (a subclass of NSEntityMigrationPolicy) to use to customize the migration. For more about entity migration policy classes, see “Custom Entity Migration Policies” (page 21). You can handle simple property migration changes by configuring a custom value expression on a property mapping directly in the mapping model editor in Xcode. For example, you can: ● Migrate data from one attribute to another. To rename amount to totalCost, enter the custom value expression for the totalCost property mapping as $source.amount. ● Apply a value transformation on a property. 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 17 Mapping OverviewTo convert temperature from Fahrenheit to Celsius, use the custom value expression ($source.temperature - 32.0) / 1.8. ● Migrate objects from one relationship to another. To rename trades to transactions, enter the custom value expression for the transactions property mapping as FUNCTION($manager, "destinationInstancesForEntityMappingNamed:sourceInstances:", "TradeToTrade", $source.trades). (This assumes the entity mapping that migrates Trade instances is named TradeToTrade.) There are six predefined keys you can reference in custom value expressions. To access these keys in source code, you use the constants as declared. To access them in custom value expression strings in the mapping model editor in Xcode, follow the syntax rules outlined in the predicate format string syntax guide and refer to them as: NSMigrationManagerKey: $manager NSMigrationSourceObjectKey: $source NSMigrationDestinationObjectKey: $destination NSMigrationEntityMappingKey: $entityMapping NSMigrationPropertyMappingKey: $propertyMapping NSMigrationEntityPolicyKey: $entityPolicy Mapping Overview Mapping Model Objects 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 18Creating a Mapping Model in Xcode From the File menu, you select New File and in the New File pane select Design > Mapping Model. In the following pane, you select the source and destination models. When you click Finish, Xcode creates a new mapping model that contains as many default mappings as it can deduce from the source and destination. For example, given the model files shown in Figure 1-1 (page 7) and Figure 1-2 (page 7), Xcode creates a mapping model as shown in Figure 4-1. Figure 4-1 Mapping model for versions 1-2 of the Core Recipes models Reserved words in custom value expressions: If you use a custom value expression, you must escape reserved words such as SIZE, FIRST, and LAST using a # (for example, $source.#size). Mapping Overview Creating a Mapping Model in Xcode 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 19During migration, Core Data creates two stacks, one for the source store and one for the destination store. Core Data then fetches objects from the source stack and inserts the appropriate corresponding objects into the destination stack. Note that Core Data must re-create objects in the new stack. Overview Recall that stores are bound to their models. Migration is required when the model doesn't match the store. There are two areas where you get default functionality and hooks for customizing the default behavior: ● When detecting version skew and initializing the migration process. ● When performing the migration process. To perform the migration processrequirestwo Core Data stacks—which are automatically created for you—one for the source store, one for the destination store. The migration process is performed in 3 stages, copying objects from one stack to another. Requirements for the Migration Process Migration of a persistent store is performed by an instance of NSMigrationManager. To migrate a store, the migration manager requires several things: ● The managed object model for the destination store. This is the persistent store coordinator’s model. ● A managed object model that it can use to open the existing store. ● Typically, a mapping model that defines a transformation from the source (the store’s) model to the destination model. You don’t need a mapping model if you’re able to use lightweight migration—see “Lightweight Migration” (page 12). 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 20 The Migration ProcessYou can specify custom entity migration policy classes to customize the migration of individual entities. You specify custom migration policy classesin the mapping model (note the “Custom Entity Policy Name” text field in Figure 4-1 (page 19)). Custom Entity Migration Policies If your new model simply adds properties or entities to your existing model, there may be no need to write any custom code. If the transformation is more complex, however, you might need to create a subclass of NSEntityMigrationPolicy to perform the transformation; for example: ● If you have a Person entity that also includes address information that you want to split into a separate Address entity, but you want to ensure uniqueness of each Address. ● If you have an attribute that encodes data in a string format that you want to change to a binary representation. The methods you override in a custom migration policy correspond to the different phases of the migration process—these are called out in the description of the process given in “Three-Stage Migration.” Three-Stage Migration The migration process itself is in three stages. It uses a copy of the source and destination models in which the validation rules are disabled and the class of all entities is changed to NSManagedObject. To perform the migration, Core Data sets up two stacks, one for the source store and one for the destination store. Core Data then processes each entity mapping in the mapping model in turn. It fetches objects of the current entity into the source stack, creates the corresponding objects in the destination stack, then recreates relationships between destination objects in a second stage, before finally applying validation constraints in the final stage. Before a cycle starts, the entity migration policy responsible for the current entity is sent a beginEntityMapping:manager:error: message. You can override this method to perform any initialization the policy requires. The process then proceeds as follows: 1. Create destination instances based on source instances. At the beginning of this phase, the entity migration policy is sent a createDestinationInstancesForSourceInstance:entityMapping:manager:error:message; at the end it is sent a endInstanceCreationForEntityMapping:manager:error: message. In this stage, only attributes (not relationships) are set in the destination objects. The Migration Process Custom Entity Migration Policies 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 21Instances of the source entity are fetched. For each instance, appropriate instances of the destination entity are created (typically there is only one) and their attributes populated (for trivial cases, name = $source.name). A record is kept of the instances per entity mapping since this may be useful in the second stage. 2. Recreate relationships. At the beginning of this phase, the entity migration policy is sent a createRelationshipsForDestinationInstance:entityMapping:manager:error: message; at the end it is sent a endRelationshipCreationForEntityMapping:manager:error: message. For each entity mapping (in order), for each destination instance created in the first step any relationships are recreated. 3. Validate and save. In this phase, the entity migration policy is sent a performCustomValidationForEntityMapping:manager:error: message. Validation rules in the destination model are applied to ensure data integrity and consistency, and then the store is saved. At the end of the cycle, the entity migration policy issent an endEntityMapping:manager:error: message. You can override this method to perform any clean-up the policy needs to do. Note that Core Data cannot simply fetch objects into the source stack and insert them into the destination stack, the objects must be re-created in the new stack. Core Data maintains “association tables” which tell it which object in the destination store isthe migrated version of which object in the source store, and vice-versa. Moreover, because it doesn't have a means to flush the contexts it is working with, you may accumulate many objects in the migration manager as the migration progresses. If this presents a significant memory overhead and hence gives rise to performance problems, you can customize the process as described in “Multiple Passes—Dealing With Large Datasets” (page 29). The Migration Process Three-Stage Migration 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 22This chapter describes how to initiate the migration process and how the default migration process works. It does not describe customizing the migration process—this is described in “Customizing the Migration Process” (page 26). Initiating the Migration Process When you initialize a persistent store coordinator, you assign to it a managed object model (see initWithManagedObjectModel:); the coordinator uses that model to open persistent stores. You open a persistent store using addPersistentStoreWithType:configuration:URL:options:error:. How you use this method, however, depends on whether your application uses model versioning and on how you choose to support migration—whether you choose to use the default migration process or custom version skew detection and migration bootstrapping. The following list describes different scenarios and what you should do in each: ● Your application does not support versioning You use addPersistentStoreWithType:configuration:URL:options:error: directly. If for some reason the coordinator’s model is not compatible with the store schema (that is, the version hashes current model’s entities do not equal those in the store’s metadata), the coordinator detects this, generates an error, and addPersistentStoreWithType:configuration:URL:options:error: returns NO. You must deal with this error appropriately. ● Your application does support versioning and you choose to use either the lightweight or the default migration process You use addPersistentStoreWithType:configuration:URL:options:error: as described in “Lightweight Migration” (page 12) and “The Default Migration Process” (page 24) respectively. The fundamental difference from the non-versioned approach is that you instruct the coordinator to automatically migrate the store to the current model version by adding an entry to the options dictionary where the key is NSMigratePersistentStoresAutomaticallyOption and the value is an NSNumber object that represents YES. ● Your application does support versioning and you choose to use custom version skew detection and migration bootstrapping 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 23 Initiating the Migration ProcessBefore opening a store you use isConfiguration:compatibleWithStoreMetadata: to check whether its schema is compatible with the coordinator’s model: ● If it is, you use addPersistentStoreWithType:configuration:URL:options:error: to open the store directly; ● If it is not, you must migrate the store first then open it (again using addPersistentStoreWithType:configuration:URL:options:error:). You could simply use addPersistentStoreWithType:configuration:URL:options:error: to check whether migration is required, however this is a heavyweight operation and inefficient for this purpose. It is important to realize that there are two orthogonal concepts: 1. You can execute custom code during the migration. 2. You can have custom code for version skew detection and migration bootstrapping. The migration policy classes allow you to customize the migration of entities and properties in a number of ways, and these are typically all you need. You might, however, use custom skew detection and migration bootstrapping so that you can take control of the migration process. For example, if you have very large stores you could set up a migration manager with the two data models, and then use a series of mapping models to migrate your data into your destination store (if you use the same destination URL for each invocation, Core Data adds new objects to the existing store). This allows the framework (and you) to limit the amount of data in memory during the conversion process. The Default Migration Process To open a store and perform migration (if necessary), you use addPersistentStoreWithType:configuration:URL:options:error: and add to the options dictionary an entry where the key is NSMigratePersistentStoresAutomaticallyOption and the value is an NSNumber object that represents YES. Your code looks similar to the following example: Listing 6-1 Opening a store using automatic migration NSError *error; NSPersistentStoreCoordinator *psc = <#The coordinator#>; NSURL *storeURL = <#The URL of a persistent store#>; NSDictionary *optionsDictionary = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] Initiating the Migration Process The Default Migration Process 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 24forKey:NSMigratePersistentStoresAutomaticallyOption]; NSPersistentStore *store = [psc addPersistentStoreWithType:<#Store type#> configuration:<#Configuration or nil#> URL:storeURL options:optionsDictionary error:&error]; If the migration proceeds successfully, the existing store at storeURL is renamed with a “~” suffix before any file extension and the migrated store saved to storeURL. In its implementation of addPersistentStoreWithType:configuration:URL:options:error: Core Data does the following: 1. Tries to find a managed object model that it can use to open the store. Core Data searches through your application’s resources for models and tests each in turn. If it cannot find a suitable model, Core Data returns nil and a suitable error. 2. Tries to find a mapping model that maps from the managed object model for the existing store to that in use by the persistent store coordinator. Core Data searches through your application’s resources for available mapping models and tests each in turn. If it cannot find a suitable mapping, Core Data returns NO and a suitable error. Note that you must have created a suitable mapping model in order for this phase to succeed. 3. Creates instances of the migration policy objects required by the mapping model. Note that even if you use the default migration process you can customize the migration itself using custom migration policy classes. Initiating the Migration Process The Default Migration Process 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 25You only customize the migration process if you want to initiate migration yourself. You might do this to, for example, to search for models in locations other than the application’s main bundle, or to deal with large data sets by performing the migration in several passes using different mapping models (see “Multiple Passes—Dealing With Large Datasets” (page 29)). Is Migration Necessary Before you initiate a migration process, you should first determine whether it is necessary. You can check with NSManagedObjectModel’s isConfiguration:compatibleWithStoreMetadata: asillustrated in Listing 7-1 (page 26). Listing 7-1 Checking whether migration is necessary NSPersistentStoreCoordinator *psc = /* get a coordinator */ ; NSString *sourceStoreType = /* type for the source store, or nil if not known */ ; NSURL *sourceStoreURL = /* URL for the source store */ ; NSError *error = nil; NSDictionary *sourceMetadata = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:sourceStoreType URL:sourceStoreURL error:&error]; if (sourceMetadata == nil) { // deal with error } NSString *configuration = /* name of configuration, or nil */ ; NSManagedObjectModel *destinationModel = [psc managedObjectModel]; BOOL pscCompatibile = [destinationModel 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 26 Customizing the Migration ProcessisConfiguration:configuration compatibleWithStoreMetadata:sourceMetadata]; if (pscCompatibile) { // no need to migrate } Initializing a Migration Manager You initialize a migration manager using initWithSourceModel:destinationModel:; you therefore first need to find the appropriate model for the store. You get the model for the store using NSManagedObjectModel’s mergedModelFromBundles:forStoreMetadata:. If this returns a suitable model, you can create the migration manager as illustrated in Listing 7-2 (page 27) (this code fragment continues from Listing 7-1 (page 26)). Listing 7-2 Initializing a Migration Manager NSArray *bundlesForSourceModel = /* an array of bundles, or nil for the main bundle */ ; NSManagedObjectModel *sourceModel = [NSManagedObjectModel mergedModelFromBundles:bundlesForSourceModel forStoreMetadata:sourceMetadata]; if (sourceModel == nil) { // deal with error } MyMigrationManager *migrationManager = [[MyMigrationManager alloc] initWithSourceModel:sourceModel destinationModel:destinationModel]; Customizing the Migration Process Initializing a Migration Manager 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 27Performing a Migration You migrate a store using NSMigrationManager’s migrateStoreFromURL:type:options:withMappingModel:toDestinationURL:destinationType:destinationOptions:error:. To use this method you need to marshal a number of parameters; most are straightforward, the only one that requires some work is the discovery of the appropriate mapping model (which you can retrieve using NSMappingModel’s mappingModelFromBundles:forSourceModel:destinationModel:method). This is illustrated in Listing 7-3 (page 28) (a continuation of the example shown in Listing 7-2 (page 27)). Listing 7-3 Performing a Migration NSArray *bundlesForMappingModel = /* an array of bundles, or nil for the main bundle */ ; NSError *error = nil; NSMappingModel *mappingModel = [NSMappingModel mappingModelFromBundles:bundlesForMappingModel forSourceModel:sourceModel destinationModel:destinationModel]; if (mappingModel == nil) { // deal with the error } NSDictionary *sourceStoreOptions = /* options for the source store */ ; NSURL *destinationStoreURL = /* URL for the destination store */ ; NSString *destinationStoreType = /* type for the destination store */ ; NSDictionary *destinationStoreOptions = /* options for the destination store */ ; BOOL ok = [migrationManager migrateStoreFromURL:sourceStoreURL type:sourceStoreType options:sourceStoreOptions withMappingModel:mappingModel toDestinationURL:destinationStoreURL destinationType:destinationStoreType destinationOptions:destinationStoreOptions Customizing the Migration Process Performing a Migration 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 28error:&error]; Multiple Passes—Dealing With Large Datasets The basic approach shown above is to have the migration manager take two models, and then iterate over the steps (mappings) provided in a mapping model to move the data from one side to the next. Because Core Data performs a "three stage" migration—where it creates all of the data first, and then relates the data in a second stage—it must maintain “association tables" (which tell it which object in the destination store is the migrated version of which object in the source store, and vice-versa). Further, because it doesn't have a means to flush the contexts it is working with, it means you'll accumulate many objects in the migration manager as the migration progresses. In order to address this, the mapping model is given as a parameter of the migrateStoreFromURL:type:options:withMappingModel:toDestinationURL:destinationType:destinationOptions:error: call itself. What this means is that if you can segregate parts of your graph (as far as mappings are concerned) and create them in separate mapping models, you could do the following: 1. Get the source and destination data models 2. Create a migration manager with them 3. Find all of your mapping models, and put them into an array (in some defined order, if necessary) 4. Loop through the array, and call migrateStoreFromURL:type:options:withMappingModel:toDestinationURL:destinationType:destinationOptions:error: with each of the mappings This allows you to migrate "chunks" of data at a time, while not pulling in all of the data at once. From a "tracking/showing progress” point of view, that basically just creates another layer to work from, so you'd be able to determine percentage complete based on number of mapping models to iterate through (and then further on the number of entity mappings in a model you've already gone through). Customizing the Migration Process Multiple Passes—Dealing With Large Datasets 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 29If you are using iCloud, you can only migrate the contents of a store using automatic lightweight migration. To migrate a persistent store that is in iCloud, you add the store to a persistent store coordinator using addPersistentStoreWithType:configuration:URL:options:error: and pass at least the following options in the options dictionary: NSDictionary *optionsDictionary = [[NSDictionary alloc] initWithObjectsAndKeys: [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, <#Ubiquitous content name#>, NSPersistentStoreUbiquitousContentNameKey, nil]; Changes to a store are recorded and preserved independently for each model version that is associated with a given NSPersistentStoreUbiquitousContentNameKey. A persistent store configured with a given NSPersistentStoreUbiquitousContentNameKey only syncs data with a store on another device data if the model versions match. If you migrate a persistent store configured with a NSPersistentStoreUbiquitousContentNameKey option to a new model version, the store’s history of changes originating from the current device will also be migrated and then merged with any other devices configured with that new model version. Any changes from stores using the new version are also merged in. Existing changes can not, however, be migrated to a new model version if the migration is performed using a custom mapping model. 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 30 Migration and iCloudThis table describes the changes to Core Data Model Versioning and Data Migration Programming Guide . Date Notes 2012-01-09 Updated to describe use of migration with iCloud. 2010-02-24 Added further details to the section on Mapping Model Objects. 2009-06-04 Added an article to describe the lightweight migration feature. 2009-03-05 First version for iOS. 2008-02-08 Added a note about migrating stores from OS X v10.4 (Tiger). New document that describes managed object model versioning and Core Data migration. 2007-05-18 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 31 Document Revision HistoryApple Inc. © 2012 Apple Inc. All rights reserved. No part of this publication may be reproduced, stored in a retrievalsystem, or transmitted, in any form or by any means, mechanical, electronic, photocopying, recording, or otherwise, without prior written permission of Apple Inc., with the following exceptions: Any person is hereby authorized to store documentation on a single computer for personal use only and to print copies of documentation for personal use provided that the documentation contains Apple’s copyright notice. No licenses, express or implied, are granted with respect to any of the technology described in this document. Apple retains all intellectual property rights associated with the technology described in this document. This document is intended to assist application developers to develop applications only for Apple-labeled computers. Apple Inc. 1 Infinite Loop Cupertino, CA 95014 408-996-1010 Apple, the Apple logo, Cocoa, Mac, OS X, Tiger, and Xcode are trademarks of Apple Inc., registered in the U.S. and other countries. iCloud is a service mark of Apple Inc., registered in the U.S. and other countries. iOS is a trademark or registered trademark of Cisco in the U.S. and other countries and is used under license. Even though Apple has reviewed this document, APPLE MAKES NO WARRANTY OR REPRESENTATION, EITHER EXPRESS OR IMPLIED, WITH RESPECT TO THIS DOCUMENT, ITS QUALITY, ACCURACY, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.ASARESULT, THISDOCUMENT IS PROVIDED “AS IS,” AND YOU, THE READER, ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND ACCURACY. IN NO EVENT WILL APPLE BE LIABLE FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL,OR CONSEQUENTIAL DAMAGES RESULTING FROM ANY DEFECT OR INACCURACY IN THIS DOCUMENT, even if advised of the possibility of such damages. THE WARRANTY AND REMEDIES SET FORTH ABOVE ARE EXCLUSIVE AND IN LIEU OF ALL OTHERS, ORAL OR WRITTEN, EXPRESS OR IMPLIED. No Apple dealer, agent, or employee is authorized to make any modification, extension, or addition to this warranty. Some states do not allow the exclusion or limitation of implied warranties or liability for incidental or consequential damages, so the above limitation or exclusion may not apply to you. This warranty gives you specific legal rights, and you may also have other rights which vary from state to state. Kernel Programming GuideContents About This Document 9 Who Should Read This Document 9 Road Map 9 Other Apple Publications 11 Mach API Reference 11 Information on the Web 12 Keep Out 13 Why You Should Avoid Programming in the Kernel 13 Kernel Architecture Overview 14 Darwin 15 Architecture 16 Mach 17 BSD 18 I/O Kit 19 Kernel Extensions 19 The Early Boot Process 21 Boot ROM 21 The Boot Loader 21 Rooting 22 Security Considerations 24 Security Implications of Paging 25 Buffer Overflows and Invalid Input 26 User Credentials 27 Basic User Credentials 28 Access Control Lists 29 Remote Authentication 29 One-Time Pads 30 Time-based authentication 30 Temporary Files 31 /dev/mem and /dev/kmem 31 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 2Key-based Authentication and Encryption 32 Public Key Weaknesses 33 Using Public Keys for Message Exchange 35 Using Public Keys for Identity Verification 35 Using Public Keys for Data Integrity Checking 35 Encryption Summary 36 Console Debugging 36 Code Passing 37 Performance Considerations 39 Interrupt Latency 39 Locking Bottlenecks 40 Working With Highly Contended Locks 40 Reducing Contention by Decreasing Granularity 41 Code Profiling 42 Using Counters for Code Profiling 42 Lock Profiling 43 Kernel Programming Style 45 C++ Naming Conventions 45 Basic Conventions 45 Additional Guidelines 46 Standard C Naming Conventions 47 Commonly Used Functions 48 Performance and Stability Tips 50 Performance and Stability Tips 50 Stability Tips 52 Style Summary 52 Mach Overview 53 Mach Kernel Abstractions 53 Tasks and Threads 54 Ports, Port Rights, Port Sets, and Port Namespaces 55 Memory Management 57 Interprocess Communication (IPC) 58 IPC Transactions and Event Dispatching 59 Message Queues 59 Semaphores 59 Notifications 60 Locks 60 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 3 ContentsRemote Procedure Call (RPC) Objects 60 Time Management 60 Memory and Virtual Memory 61 OS X VM Overview 61 Memory Maps Explained 63 Named Entries 64 Universal Page Lists (UPLs) 65 Using Mach Memory Maps 66 Other VM and VM-Related Subsystems 68 Pagers 68 Working Set Detection Subsystem 69 VM Shared Memory Server Subsystem 69 Address Spaces 70 Background Info on PCI Address Translation 70 IOMemoryDescriptor Changes 71 VM System and pmap Changes: 72 Kernel Dependency Changes 72 Summary 72 Allocating Memory in the Kernel 73 Allocating Memory From a Non-I/O-Kit Kernel Extension 73 Allocating Memory From the I/O Kit 74 Allocating Memory In the Kernel Itself 75 Mach Scheduling and Thread Interfaces 77 Overview of Scheduling 77 Why Did My Thread Priority Change? 78 Using Mach Scheduling From User Applications 79 Using the pthreads API to Influence Scheduling 79 Using the Mach Thread API to Influence Scheduling 80 Using the Mach Task API to Influence Scheduling 83 Kernel Thread APIs 85 Creating and Destroying Kernel Threads 85 SPL and Friends 86 Wait Queues and Wait Primitives 87 Bootstrap Contexts 91 How Contexts Affect Users 92 How Contexts Affect Developers 93 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 4 ContentsI/O Kit Overview 94 Redesigning the I/O Model 94 I/O Kit Architecture 96 Families 96 Drivers 97 Nubs 97 Connection Example 98 For More Information 100 BSD Overview 101 BSD Facilities 102 Differences between OS X and BSD 103 For Further Reading 104 File Systems Overview 106 Working With the File System 106 VFS Transition 107 Network Architecture 108 Boundary Crossings 109 Security Considerations 110 Choosing a Boundary Crossing Method 110 Kernel Subsystems 111 Bandwidth and Latency 111 Mach Messaging and Mach Interprocess Communication (IPC) 112 Using Well-Defined Ports 113 Remote Procedure Calls (RPC) 113 Calling RPC From User Applications 116 BSD syscall API 116 BSD ioctl API 116 BSD sysctl API 117 General Information on Adding a sysctl 118 Adding a sysctl Procedure Call 118 Registering a New Top Level sysctl 121 Adding a Simple sysctl 122 Calling a sysctl From User Space 123 Memory Mapping and Block Copying 125 Summary 127 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 5 ContentsSynchronization Primitives 128 Semaphores 128 Condition Variables 130 Locks 132 Spinlocks 132 Mutexes 134 Read-Write Locks 136 Spin/Sleep Locks 138 Using Lock Functions 139 Miscellaneous Kernel Services 142 Using Kernel Time Abstractions 142 Obtaining Time Information 142 Event and Timer Waits 143 Handling Version Dependencies 145 Boot Option Handling 146 Queues 147 Installing Shutdown Hooks 148 Kernel Extension Overview 150 Implementation of a Kernel Extension (KEXT) 151 Kernel Extension Dependencies 151 Building and Testing Your Extension 152 Debugging Your KEXT 153 Installed KEXTs 154 Building and Debugging Kernels 155 Adding New Files or Modules 155 Modifying the Configuration Files 155 Modifying the Source Code Files 157 Building Your First Kernel 158 Building an Alternate Kernel Configuration 160 When Things Go Wrong: Debugging the Kernel 161 Setting Debug Flags in Open Firmware 161 Avoiding Watchdog Timer Problems 163 Choosing a Debugger 164 Using gdb for Kernel Debugging 164 Using ddb for Kernel Debugging 169 Bibliography 175 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 6 ContentsApple OS X Publications 175 General UNIX and Open Source Resources 175 BSD and UNIX Internals 176 Mach 177 Networking 178 Operating Systems 179 POSIX 179 Programming 179 Websites and Online Resources 180 Security and Cryptography 181 Document Revision History 182 Glossary 184 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 7 ContentsFigures, Tables, and Listings Kernel Architecture Overview 14 Figure 3-1 OS X architecture 14 Figure 3-2 Darwin and OS X 15 Figure 3-3 OS X kernel architecture 16 Kernel Programming Style 45 Table 7-1 Commonly used C functions 49 Mach Scheduling and Thread Interfaces 77 Table 10-1 Thread priority bands 77 Table 10-2 Thread policies 81 Table 10-3 Task roles 83 I/O Kit Overview 94 Figure 12-1 I/O Kit architecture 98 Synchronization Primitives 128 Listing 17-1 Allocating lock attributes and groups (lifted liberally from kern_time.c) 139 Building and Debugging Kernels 155 Table 20-1 Debugging flags 163 Table 20-2 Switch options in ddb 171 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 8The purpose of this document is to provide fundamental high-level information about the OS X core operating-system architecture. It also provides background for system programmers and developers of device drivers, file systems, and network extensions. In addition, it goes into detail about topics of interest to kernel programmers as a whole. This is not a document on drivers. It covers device drivers at a high level only. It does, however, cover some areas of interest to driver writers, such as crossing the user-kernel boundary. If you are writing device drivers, you should primarily read the document I/O Kit Fundamentals, but you may still find this document helpful as background reading. Who Should Read This Document This document has a wide and diverse audience—specifically, the set of potential system software developers for OS X, including the following sorts of developers: ● device-driver writers ● network-extension writers ● file-system writers ● developers of software that modifies file system data on-the-fly ● system programmers familiar with BSD, Linux, and similar operating systems ● developers who want to learn about kernel programming If you fall into one of these categories, you may find this document helpful. It is important to stress the care needed when writing code that resides in the kernel, however, as noted in “Keep Out” (page 13). Road Map The goal of this document is to describe the various major components of OS X at a conceptual level, then provide more detailed programming information for developers working in each major area. It is divided into several parts. 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 9 About This DocumentThe first part is a kernel programming overview, which discusses programming guidelines that apply to all aspects of kernel programming. This includes issues such as security, SMP safety, style, performance, and the OS X kernel architecture as a whole. This part contains the chapters “Keep Out” (page 13), “Kernel Architecture Overview” (page 14), “The Early Boot Process” (page 21), “Security Considerations” (page 24), “Performance Considerations” (page 39), and “Kernel Programming Style” (page 45). The next part describes Mach and the bootstrap task, including information about IPC, bootstrap contexts, ports and port rights, and so on. This includes the chapters “Mach Overview” (page 53), “Memory and Virtual Memory” (page 61), “Mach Scheduling and Thread Interfaces” (page 77), and “Bootstrap Contexts” (page 91). The third part describes the I/O Kit and BSD. The I/O Kit is described at only a high level, since it is primarily of interest to driver developers. The BSD subsystem is covered in more detail, including descriptions of BSD networking and file systems. This includes the chapters “I/O Kit Overview” (page 94), “BSD Overview” (page 101), “File Systems Overview” (page 106), and “Network Architecture” (page 108). The fourth part describes kernelservices, including boundary crossings,synchronization, queues, clocks, timers, shutdown hooks, and boot option handling. This includes the chapters “Boundary Crossings” (page 109), “Synchronization Primitives” (page 128), and “Miscellaneous Kernel Services” (page 142). The fifth part explains how to build and debug the kernel and kernel extensions. This includes the chapters “Kernel Extension Overview” (page 150) and “Building and Debugging Kernels” (page 155). Each part begins with an overview chapter or chapters, followed by chapters that address particular areas of interest. The document ends with a glossary of terms used throughout the preceding chapters as well as a bibliography which provides numerous pointers to other reference materials. Glossary terms are highlighted in bold when first used. While most terms are defined when they first appear, the definitions are all in the glossary for convenience. If a term seems familiar, it probably means what you think it does. If it’s unfamiliar, check the glossary. In any case, all readers may want to skim through the glossary, in case there are subtle differences between OS X usage and that of other operating systems. The goal of this document is very broad, providing a firm grounding in the fundamentals of OS X kernel programming for developers from many backgrounds. Due to the complex nature of kernel programming and limitations on the length of this document, however, it is not always possible to provide introductory material for developers who do not have at least some background in their area of interest. It is also not possible to cover every detail of certain parts of the kernel. If you run into problems, you should join the appropriate Darwin discussion list and ask questions. You can find the lists at http://www.lists.apple.com/. For this reason, the bibliography contains high-level references that should help familiarize you with some of the basic concepts that you need to understand fully the material in this document. About This Document Road Map 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 10This document is, to a degree, a reference document. The introductory sections should be easily read, and we recommend that you do so in order to gain a general understanding of each topic. Likewise, the first part of each chapter, and in many cases, of sections within chapters, will be tailored to providing a general understanding of individual topics. However, you should not plan to read this document cover to cover, but rather, take note of topics of interest so that you can refer back to them when the need arises. Other Apple Publications This document, Kernel Programming , is part of the Apple Reference Library. Be sure to read the first document in the series, Mac Technology Overview, if you are not familiar with OS X. You can obtain other documents from the Apple Developer Documentation website at http://developer.apple.com/documentation. Mach API Reference If you plan to do extensive work inside the OS X kernel, you may find it convenient to have a complete Mach API reference, since this document only documents the most common and useful portions of the Mach API. In order to better understand certain interfaces, it may also be helpful to study the implementations that led up to those used in OS X, particularly to fill in gaps in understanding of the fundamental principles of the implementation. OS X is based on the Mach 3.0 microkernel, designed by Carnegie Mellon University, and later adapted to the Power Macintosh by Apple and the Open Software Foundation Research Institute (now part of Silicomp). This was known as osfmk, and was part of MkLinux (http://www.mklinux.org). Later, this and code from OSF’s commercial development efforts were incorporated into Darwin’s kernel. Throughout this evolutionary process, the Mach APIs used in OS X diverged in many ways from the original CMU Mach 3 APIs. You may find older versions of the Mach source code interesting, both to satisfy historical curiosity and to avoid remaking mistakes made in earlier implementations. MkLinux maintains an active CVS repository with their recent versions of Mach kernel source code. Older versions can be obtained through various Internet sites. You can also find CMU Mach white papers by searching for Mach on the CMU computer science department’s website (http://www.cs.cmu.edu), along with various source code samples. Up-to-date versions of the Mach 3 APIsthat OS X provides are described in the Mach API reference in the kernel sources. The kernel sources can be found in the xnu project on http://kernel.macosforge.org/. About This Document Other Apple Publications 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 11Information on the Web Apple maintains several websites where developers can go for general and technical information on OS X. ● Apple Developer Connection: Developer Documentation (http://developer.apple.com/documentation). Features the same documentation that is installed on OS X, except that often the documentation is more up-to-date. Also includes legacy documentation. ● Apple Developer Connection: OS X (http://developer.apple.com/devcenter/mac/). Offers SDKs, release notes, product notes and news, and other resources and information related to OS X. ● AppleCare Tech Info Library (http://www.apple.com/support/). Contains technical articles, tutorials, FAQs, technical notes, and other information. About This Document Information on the Web 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 12This document assumes a broad general understanding of kernel programming concepts. There are many good introductory operating systems texts. This is not one of them. For more information on basic operating systems programming, you should consider the texts mentioned in the bibliography at the end of this document. Many developers are justifiably cautious about programming in the kernel. A decision to program in the kernel is not to be taken lightly. Kernel programmers have a responsibility to users that greatly surpasses that of programmers who write user programs. Why You Should Avoid Programming in the Kernel Kernel code must be nearly perfect. A bug in the kernel could cause random crashes, data corruption, or even render the operating system inoperable. It is even possible for certain errant operations to cause permanent and irreparable damage to hardware, for example, by disabling the cooling fan and running the CPU full tilt. Kernel programming is a black art that should be avoided if at all possible. Fortunately, kernel programming is usually unnecessary. You can write most software entirely in user space. Even most device drivers (FireWire and USB, for example) can be written as applications, rather than as kernel code. A few low-level drivers must be resident in the kernel's address space, however, and this document might be marginally useful if you are writing drivers that fall into this category. Despite parts of this document being useful in driver writing, this is not a document about writing drivers. In OS X, you write device drivers using the I/O Kit. While this document covers the I/O Kit at a conceptual level, the details of I/O Kit programming are beyond the scope of this document. Driver writers are encouraged to read I/O Kit Fundamentals for detailed information about the I/O Kit. This document covers most aspects of kernel programmingwith the exception of device drivers. Covered topics include scheduling, virtual memory pagers and policies, Mach IPC, file systems, networking protocol stacks, process and thread management, kernel security, synchronization, and a number of more esoteric topics. To summarize, kernel programming is an immense responsibility. You must be exceptionally careful to ensure that your code does not cause the system to crash, does not provide any unauthorized user accessto someone else’s files or memory, does not introduce remote or local root exploits, and does not cause inadvertent data loss or corruption. 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 13 Keep OutOS X provides many benefits to the Macintosh user and developer communities. These benefits include improved reliability and performance, enhanced networking features, an object-based system programming interface, and increased support for industry standards. In creatingOS X, Apple has completely re-engineered the MacOS core operating system. Forming the foundation of OS X is the kernel. Figure 3-1 (page 14) illustrates the OS X architecture. Figure 3-1 OS X architecture Carbon Cocoa BSD Java (JDK) Classic BSD Core Services Kernel environment Application Services QuickTime Application environment The kernel provides many enhancements for OS X. These include preemption, memory protection, enhanced performance, improved networking facilities, support for both Macintosh (Extended and Standard) and non-Macintosh (UFS, ISO 9660, and so on) file systems, object-oriented APIs, and more. Two of these features, preemption and memory protection, lead to a more robust environment. In Mac OS 9, applications cooperate to share processor time. Similarly, all applications share the memory of the computer among them. Mac OS 9 is a cooperative multitasking environment. The responsiveness of all processes is compromised if even a single application doesn’t cooperate. On the other hand, real-time applications such as multimedia need to be assured of predictable, time-critical, behavior. In contrast, OS X is a preemptive multitasking environment. In OS X, the kernel provides enforcement of cooperation,scheduling processesto share time (preemption). Thissupportsreal-time behavior in applications that require it. In OS X, processes do not normally share memory. Instead, the kernel assigns each process its own address space, controlling access to these address spaces. This control ensures that no application can inadvertently access or modify another application’s memory (protection). Size is not an issue; with the virtual memory system included in OS X, each application has access to its own 4 GB address space. 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 14 Kernel Architecture OverviewViewed together, all applications are said to run in user space, but this does not imply that they share memory. User space is simply a term for the combined address spaces of all user-level applications. The kernel itself has its own address space, called kernel space. In OS X, no application can directly modify the memory of the system software (the kernel). Although user processes do not share memory by default as in Mac OS 9, communication (and even memory sharing) between applications is still possible. For example, the kernel offers a rich set of primitives to permit some sharing of information among processes. These primitives include shared libraries, frameworks, and POSIX shared memory. Mach messaging provides another approach, handing memory from one process to another. Unlike Mac OS 9, however, memory sharing cannot occur without explicit action by the programmer. Darwin The OS X kernel is an Open Source project. The kernel, along with other core parts of OS X are collectively referred to as Darwin. Darwin is a complete operating system based on many of the same technologies that underlie OS X. However, Darwin does not include Apple’s proprietary graphics or applications layers, such as Quartz, QuickTime, Cocoa, Carbon, or OpenGL. Figure 3-2 (page 15) shows the relationship between Darwin and OS X. Both build upon the same kernel, but OS X adds Core Services, Application Services and QuickTime, as well as the Classic, Carbon, Cocoa, and Java (JDK) application environments. Both Darwin and OS X include the BSD command-line application environment; however, in OS X, use of environment is not required, and thus it is hidden from the user unless they choose to access it. Figure 3-2 Darwin and OS X Carbon Cocoa BSD Java (JDK) Classic BSD Core Services Kernel environment Application Services QuickTime Application environment Darwin technology is based on BSD, Mach 3.0, and Apple technologies. Best of all, Darwin technology is Open Source technology, which meansthat developers have full accessto the source code. In effect, OS X third-party developers can be part of the Darwin core system software development team. Developers can also see how Apple is doing thingsin the core operating system and adopt (or adapt) code to use within their own products. Refer to the Apple Public Source License (APSL) for details. Kernel Architecture Overview Darwin 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 15Because the same software forms the core of both OS X and Darwin, developers can create low-level software that runs on both OS X and Darwin with few, if any, changes. The only difference is likely to be in the way the software interacts with the application environment. Darwin is based on proven technology from many sources. A large portion of this technology is derived from FreeBSD, a version of 4.4BSD that offers advanced networking, performance,security, and compatibility features. Other parts of the system software, such as Mach, are based on technology previously used in Apple’s MkLinux project, in OS X Server, and in technology acquired from NeXT. Much of the code is platform-independent. All of the core operating-system code is available in source form. The core technologies have been chosen for several reasons. Mach provides a clean set of abstractions for dealing with memory management, interprocess(and interprocessor) communication (IPC), and other low-level operating-system functions. In today’s rapidly changing hardware environment, this provides a useful layer of insulation between the operating system and the underlying hardware. BSD is a carefully engineered, mature operating system with many capabilities. In fact, most of today’s commercial UNIX and UNIX-like operating systems contain a great deal of BSD code. BSD also provides a set of industry-standard APIs. New technologies,such asthe I/OKit and Network Kernel Extensions(NKEs), have been designed and engineered by Apple to take advantage of advanced capabilities,such asthose provided by an object-oriented programming model. OS X combines these new technologies with time-tested industry standards to create an operating system that is stable, reliable, flexible, and extensible. Architecture The foundation layer of Darwin and OS X is composed of several architectural components, as shown in Figure 3-3 (page 16). Taken together, these components form the kernel environment. Figure 3-3 OS X kernel architecture Common services Kernel environment Application environments Mach File system BSD Networking NKE Drivers I/O Kit Kernel Architecture Overview Architecture 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 16Important: Note that OS X uses the term kernel somewhat differently than you might expect. “A kernel, in traditional operating-system terminology, is a small nucleus of software that provides only the minimal facilities necessary for implementing additional operating-system services.” — from The Design and Implementation of the 4.4 BSD Operating System, McKusick, Bostic, Karels, and Quarterman, 1996. Similarly, in traditional Mach-based operating systems, the kernel refers to the Mach microkernel and ignores additional low-level code without which Mach does very little. In OS X, however, the kernel environment contains much more than the Mach kernel itself. The OS X kernel environment includes the Mach kernel, BSD, the I/O Kit, file systems, and networking components. These are often referred to collectively as the kernel. Each of these components is described briefly in the following sections. For further details, refer to the specific component chapters or to the reference material listed in the bibliography. Because OS X contains three basic components (Mach, BSD, and the I/O Kit), there are also frequently as many as three APIs for certain key operations. In general, the API chosen should match the part of the kernel where it is being used, which in turn is dictated by what your code is attempting to do. The remainder of this chapter describes Mach, BSD, and the I/O Kit and outlines the functionality that is provided by those components. Mach Mach manages processor resources such as CPU usage and memory, handles scheduling, provides memory protection, and provides a messaging-centered infrastructure to the rest of the operating-system layers. The Mach component provides ● untyped interprocess communication (IPC) ● remote procedure calls (RPC) ● scheduler support for symmetric multiprocessing (SMP) ● support for real-time services ● virtual memory support ● support for pagers ● modular architecture General information about Mach may be found in the chapter “Mach Overview” (page 53). Information about scheduling can be found in the chapter “Mach Scheduling and Thread Interfaces” (page 77). Information about the VM system can be found in “Memory and Virtual Memory” (page 61). Kernel Architecture Overview Architecture 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 17BSD Above the Mach layer, the BSD layer provides “OS personality” APIs and services. The BSD layer is based on the BSD kernel, primarily FreeBSD. The BSD component provides ● file systems ● networking (except for the hardware device level) ● UNIX security model ● syscall support ● the BSD process model, including process IDs and signals ● FreeBSD kernel APIs ● many of the POSIX APIs ● kernel support for pthreads (POSIX threads) The BSD component is described in more detail in the chapter “BSD Overview” (page 101). Networking OS X networking takes advantage of BSD’s advanced networking capabilities to provide support for modern features, such as Network Address Translation (NAT) and firewalls. The networking component provides ● 4.4BSD TCP/IP stack and socket APIs ● support for both IP and DDP (AppleTalk transport) ● multihoming ● routing ● multicast support ● server tuning ● packet filtering ● Mac OS Classic support (through filters) More information about networking may be found in the chapter “Network Architecture” (page 108). Kernel Architecture Overview Architecture 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 18File Systems OS X providessupport for numeroustypes of file systems, including HFS, HFS+, UFS, NFS, ISO 9660, and others. The default file-system type is HFS+; OS X boots (and “roots”) from HFS+, UFS, ISO, NFS, and UDF. Advanced features of OS X file systems include an enhanced Virtual File System (VFS) design. VFS provides for a layered architecture (file systems are stackable). The file system component provides ● UTF-8 (Unicode) support ● increased performance over previous versions of Mac OS. More information may be found in the chapter “File Systems Overview” (page 106). I/O Kit The I/O Kit provides a framework forsimplified driver development,supporting many categories of devices.The I/O Kit features an object-oriented I/O architecture implemented in a restricted subset of C++. The I/O Kit framework is both modular and extensible. The I/O Kit component provides ● true plug and play ● dynamic device management ● dynamic (“on-demand”) loading of drivers ● power management for desktop systems as well as portables ● multiprocessor capabilities The I/O Kit is described in greater detail in the chapter “I/O Kit Overview” (page 94). Kernel Extensions OS X provides a kernel extension mechanism as a means of allowing dynamic loading of pieces of code into kernel space, without the need to recompile. These pieces of code are known generically as plug-ins or, in the OS X kernel environment, as kernel extensions or KEXTs. Because KEXTs provide both modularity and dynamic loadability, they are a natural choice for any relatively self-contained service that requires access to interfaces that are not exported to user space. Many of the components of the kernel environment support this extension mechanism, though they do so in different ways. For example, some of the new networking features involve the use of network kernel extensions (NKEs). These are discussed in the chapter “Network Architecture” (page 108). Kernel Architecture Overview Kernel Extensions 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 19The ability to dynamically add a new file-system implementation is based on VFS KEXTs. Device drivers and device familiesin the I/O Kit are implemented using KEXTs. KEXTs make development much easier for developers writing drivers or those writing code to support a new volume format or networking protocol. KEXTs are discussed in more detail in the chapter “Kernel Extension Overview” (page 150). Kernel Architecture Overview Kernel Extensions 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 20Boot ROM When the power to a Macintosh computer is turned on, the BootROM firmware is activated. BootROM (which is part of the computer’s hardware) hastwo primary responsibilities: it initializessystem hardware and itselects an operating system to run. BootROM has two components to help it carry out these functions: ● POST (Power-On Self Test) initializes some hardware interfaces and verifies that sufficient memory is available and in a good state. ● EFI does basic hardware initialization and selects which operating system to use. If multiple installations of OS X are available, BootROM chooses the one that was last selected by the Startup Disk System Preference. The user can override this choice by holding down the Option key while the computer boots, which causes EFI to display a screen for choosing the boot volume. The Boot Loader Once BootROM is finished and an OS X partition has been selected, control passes to the boot.efi boot loader. The principal job of this boot loader is to load the kernel environment. As it does this, the boot loader draws the “booting” image on the screen. If full-disk encryption is enabled, the boot loader is responsible for drawing the login UI and prompting for the user’s password, which needed to accessthe encrypted disk to boot from it. (This UI is drawn by loginwindow otherwise.) In the simplest case, the boot loader can be found in the /System/Library/CoreServices directory on the root partition, in a file named boot.efi. Note: Booting from a UFS volume is deprecated as of OS X v10.5. In order to speed up boot time, the boot loader uses several caches. The contents and location of these caches varies between versions of OS X, but knowing some details about the caching may be helpful when debugging kernel extensions. 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 21 The Early Boot ProcessAfter you install or modify a kernel extension, touch the /System/Library/Extensions directory; the system rebuilds the caches automatically. Important: You should not depend on the implementation details of the kernel caches in your software. In OS X v10.7, the boot loader looks for the unified prelinked kernel. This cache contains all kernel extensions that may be needed to boot a Mac with any hardware configuration, with the extensions already linked against the kernel. It islocated at /System/Library/Caches/com.apple.kext.caches/Startup/kernelcache. In OS X v10.6 and earlier, the boot loader first looks for the prelinked kernel (also called the kernel cache). This cache contains exactly the set of kernel extensions that were needed during the previous system startup, already linked against the kernel. If the prelinked kernel is missing or unusable (for example, because a hardware configuration has changed), the booter looks for the mkext cache, which contains all kernel extensions that may be needed to boot the system. Using the mkext cache is much slower because the linker must be run. On OS X v10.5 and v10.6, these caches are located in /System/Library/Caches/com.apple.kext.caches/Startup/; on previous versions of OS X, it was located at /System/Library/Caches/com.apple.kernelcaches/. Finally, if the caches cannot be used, the boot loader searches /System/Library/Extensions for drivers and other kernel extensions whose OSBundleRequired property is set to a value appropriate to the type of boot (for example, local or network boot). This process is very slow, because the Info.plist file of every kernel extension must be parsed, and then the linker must be run. For more information on how drivers are loaded, see I/O Kit Fundamentals, the manual page for kextcache, and Kernel Extension Programming Topics. Rooting Once the kernel and all drivers necessary for booting are loaded, the boot loaderstartsthe kernel’sinitialization procedure. At this point, enough drivers are loaded for the kernel to find the root device. The kernel initializes the Mach and BSD data structures and then initializes the I/O Kit. The I/O Kit links the loaded drivers into the kernel, using the device tree to determine which drivers to link. Once the kernel finds the root device, it roots(*) BSD off of it. The Early Boot Process Rooting 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 22Note: As a terminology aside, the term “boot” was historically reserved for loading a bootstrap loader and kernel off of a disk or partition. In more recent years, the usage has evolved to allow a second meaning: the entire process from initial bootstrap until the OS is generally usable by an end user. In this case, the term is used according to the former meaning. As used here, the term “root” refersto mounting a partition asthe root, or top-level, filesystem. Thus, while the OS boots off of the root partition, the kernel rootsthe OS off of the partition before executing startup scripts from it. Boot≠Root is a technology that allows the system to boot from a partition other than the root partition. This is used to boot systems where the root partition is encrypted using full-disk encryption, or where the root partition islocated on a device which requires additional drivers(such as a RAID array). Boot≠Root uses a helper partition to store the files needed to boot, such as the kernel cache. For more information on how to set up the property in a filter-scheme driver,see “Developing a Filter Scheme” in Mass StorageDeviceDriver Programming Guide . The Early Boot Process Rooting 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 23Kernel-level security can mean many things, depending on what kind of kernel code you are writing. This chapter points out some common security issues at the kernel or near-kernel level and where applicable, describes ways to avoid them. These issues are covered in the following sections: ● “Security Implications of Paging” (page 25) ● “Buffer Overflows and Invalid Input” (page 26) ● “User Credentials” (page 27) ● “Remote Authentication” (page 29) ● “Temporary Files” (page 31) ● “/dev/mem and /dev/kmem” (page 31) ● “Key-based Authentication and Encryption” (page 32) ● “Console Debugging” (page 36) ● “Code Passing” (page 37) Many of these issues are also relevant for application programming, but are crucial for programmers working in the kernel. Others are special considerations that application programers might not expect or anticipate. Note: The terms cleartext and plaintext both refer to unencrypted text. These terms can generally be used interchangeably, although in some circles, the term cleartext is restricted to unencrypted transmission across a network. However, in other circles, the term plaintext (orsometimes plain text) refers to plain ASCII text (as opposed to HTML or rich text. To avoid any potential confusion, this chapter will use the term cleartext to refer to unencrypted text. In order to understand security in OS X, it is important to understand that there are two security models at work. One of these is the kernel security model, which is based on users, groups, and very basic per-user and per-group rights, which are, in turn, coupled with access control lists for increased flexibility. The other is a user-level security model, which is based on keys, keychains, groups, users, password-based authentication, and a host of other details that are beyond the scope of this document. The user level of security contains two basic features that you should be aware of as a kernel programmer: Security Server and Keychain Manager. 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 24 Security ConsiderationsThe Security Server consists of a daemon and various accesslibrariesfor caching permission to do certain tasks, based upon various means of authentication, including passwords and group membership. When a program requests permission to do something, the Security Server basically says “yes” or “no,” and caches that decision so that further requestsfrom that user (forsimilar actions within a single context) do not require reauthentication for a period of time. The Keychain Manager is a daemon that provides services related to the keychain, a central repository for a user’s encryption/authentication keys. For more high level information on keys,see “Key-based Authentication and Encryption” (page 32). The details of the user-level security model use are far beyond the scope of this document. However, if you are writing an application that requires services of this nature, you should consider taking advantage of the Security Server and Keychain Manager from the user-space portion of your application, rather than attempting equivalent services in the kernel. More information about these services can be found in Apple’s Developer Documentation website at http://developer.apple.com/documentation. Security Implications of Paging Paging has long been a major problem for security-conscious programmers. If you are writing a program that does encryption, the existence of even a small portion of the cleartext of a document in a backing store could be enough to reduce the complexity of breaking that encryption by orders of magnitude. Indeed, many types of data,such as hashes, unencrypted versions ofsensitive data, and authentication tokens, should generally not be written to disk due to the potential for abuse. This raises an interesting problem. There is no good way to deal with this in user space (unless a program is running as root). However, for kernel code, it is possible to prevent pages from being written out to a backing store. This process is referred to as “wiring down” memory, and is described further in “Memory Mapping and Block Copying” (page 125). The primary purpose of wired memory is to allow DMA-based I/O. Since hardware DMA controllers generally do not understand virtual addressing, information used in I/O must be physically in memory at a particular location and must not move until the I/O operation is complete. This mechanism can also be used to prevent sensitive data from being written to a backing store. Because wired memory can never be paged out (until it is unwired), wiring large amounts of memory has drastic performance repercussions, particularly on systems with small amounts of memory. For this reason, you should take care not to wire down memory indiscriminately and only wire down memory if you have a very good reason to do so. In OS X, you can wire down memory at allocation time or afterwards. To wire memory at allocation time: ● In I/O Kit, call IOMalloc and IOFree to allocate and free wired memory. Security Considerations Security Implications of Paging 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 25● In other kernel extensions, call OSMalloc and OSFree and pass a tag type whose flags are set to OSMT_DEFAULT. ● In user space code, allocate page-sized quantities with your choice of API, and then call mlock(2) to wire them. ● Inside the kernel itself (not in kernel extensions), you can also use kmem_alloc and related functions. For more information on wired memory, see “Memory Mapping and Block Copying” (page 125). Buffer Overflows and Invalid Input Buffer overflows are one of the more common bugs in both application and kernel programming. The most common cause is failing to allocate space for the NULL character that terminates a string in C or C++. However, user input can also cause buffer overflows if fixed-size input buffers are used and appropriate care is not taken to prevent overflowing these buffers. The most obvious protection, in this case, is the best one. Either don’t use fixed-length buffers or add code to reject or truncate input that overflows the buffer. The implementation details in either case depend on the type of code you are writing. For example, if you are working with strings and truncation is acceptable, instead of using strcpy, you should use strlcpy to limit the amount of data to copy. OS X provides length-limited versions of a number of string functions, including strlcpy, strlcat, strncmp, snprintf, and vsnprintf. If truncation of data is not acceptable, you must explicitly call strlen to determine the length of the input string and return an error if it exceeds the maximum length (one less than the buffer size). Other types of invalid input can be somewhat harder to handle, however. As a general rule, you should be certain that switch statements have a default case unless you have listed every legal value for the width of the type. A common mistake is assuming that listing every possible value of an enum type provides protection. An enum is generally implemented as either a char or an int internally. A careless or malicious programmer could easily pass any value to a kernel function, including those not explicitly listed in the type, simply by using a different prototype that defines the parameter as, for example, an int. Another common mistake is to assume that you can dereference a pointer passed to your function by another function. You should always check for null pointers before dereferencing them. Starting a function with int do_something(bufptr *bp, int flags) { Security Considerations Buffer Overflows and Invalid Input 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 26char *token = bp->b_data; isthe surest way to guarantee thatsomeone else will passin a null buffer pointer, either maliciously or because of programmer error. In a user program, this is annoying. In a file system, it is devastating. Security is particularly important for kernel code that draws input from a network. Assumptions about packet size are frequently the cause of security problems. Always watch for packets that are too big and handle them in a reasonable way. Likewise, always verify checksums on packets. This can help you determine if a packet was modified, damaged, or truncated in transit, though it is far from foolproof. If the validity of data from a network is of vital importance, you should use remote authentication, signing, and encryption mechanisms such as those described in “Remote Authentication” (page 29) and “Key-based Authentication and Encryption” (page 32). User Credentials As described in the introduction to this chapter, OS X has two different means of authenticating users. The user-levelsecurity model (including the Keychain Manager and the Security Server) is beyond the scope of this document. The kernel security model, however, is of greater interest to kernel developers, and is much more straightforward than the user-level model. The kernel security model is based on two mechanisms: basic user credentials and ACL permissions. The first, basic user credentials, are passed around within the kernel to identify the current user and group of the calling process. The second authentication mechanism, access control lists (ACLs), provides access control at a finer level of granularity. One of the most important things to remember when working with credentials is that they are per process, not per context. This is important because a process may not be running as the console user. Two examples of this are processes started from an ssh session (since ssh runs in the startup context) and setuid programs (which run as a different user in the same login context). It is crucial to be aware of these issues. If you are communicating with a setuid root GUI application in a user’s login context, and if you are executing another application or are reading sensitive data, you probably want to treat it as if it had the same authority as the console user, not the authority of the effective user ID caused by running setuid. This is particularly problematic when dealing with programs that run as setuid root if the console user is not in the admin group. Failure to perform reasonable checks can lead to major security holes down the road. However, this is not a hard and fast rule. Sometimes it is not obvious whether to use the credentials of the running process or those of the console user. In such cases, it is often reasonable to have a helper application show a dialog box on the console to require interaction from the console user. If this is not possible, a good Security Considerations User Credentials 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 27rule of thumb is to assume the lesser of the privileges of the current and console users, as it is almost always better to have kernel code occasionally fail to provide a needed service than to provide that service unintentionally to an unauthorized user or process. It is generally easier to determine the console user from a user space application than from kernel space code. Thus, you should generally do such checks from user space. If that is not possible, however, the variable console_user (maintained by the VFS subsystem) will give you the uid of the last owner of /dev/console (maintained by a bit of code in the chown system call). Thisis certainly not an idealsolution, but it does provide the most likely identity of the console user. Since this is only a “best guess,” however, you should use this only if you cannot do appropriate checking in user space. Basic User Credentials Basic user credentials used in the kernel are stored in a variable of type struct ucred. These are mostly used in specialized parts of the kernel—generally in places where the determining factor in permissions is whether or not the caller is running as the root user. This structure has four fields: ● cr_ref—reference count (used internally) ● cr_uid—user ID ● cr_ngroups—number of groups in cr_groups ● cr_groups[NGROUPS]—list of groups to which the user belongs Thisstructure has an internal reference counter to prevent unintentionally freeing the memory associated with it while it is still in use. For this reason, you should not indiscriminately copy this object but should instead either use crdup to duplicate it or use crcopy to duplicate it and (potentially) free the original. You should be sure to crfree any copies you might make. You can also create a new, empty ucred structure with crget. The prototypes for these functions follow: ● struct ucred *crdup(struct ucred *cr) ● struct ucred *crcopy(struct ucred *cr) ● struct ucred *crget(void) ● void crfree(struct ucred *cr) Security Considerations User Credentials 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 28Note: Functions for working with basic user credential are not exported outside of the kernel, and thus are not generally available to kernel extensions. Access Control Lists Access control lists are a new feature in OS X v10.4. Access control lists are primarily used in the file system portion of the OS X kernel, and are supported through the use of the kauth API. The kauth API is described in the header file /System/Library/Frameworks/Kernel.framework/Headers/sys/kauth.h. Because this API is still evolving, detailed documentation is not yet available. Remote Authentication This is one of the more difficult problems in computer security: the ability to identify someone connecting to a computer remotely. One of the mostsecure methodsisthe use of public key cryptography, which is described in more detail in “Key-based Authentication and Encryption” (page 32). However, many other means of authentication are possible, with varying degrees of security. Some other authentication schemes include: ● blind trust ● IP-only authentication ● password (shared secret) authentication ● combination of IP and password authentication ● one-time pads (challenge-response) ● time-based authentication Most of these are obvious, and require no further explanation. However, one-time pads and time-based authentication may be unfamiliar to many people outside security circles, and are thus worth mentioning in more detail. Security Considerations Remote Authentication 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 29One-Time Pads Based on the concept of “challenge-response” pairs, one-time pad (OTP) authentication requires that both parties have an identical list of pairs of numbers, words, symbols, or whatever, sorted by the first item. When trying to access a remote system, the remote system prompts the user with a challenge. The user finds the challenge in the first column, then sends back the matching response. Alternatively, this could be an automated exchange between two pieces of software. For maximum security, no challenge should ever be issued twice. For this reason, and because these systems were initially implemented with a paper pad containing challenge-response, or CR pairs, such systems are often called one-time pads. The one-time nature of OTP authentication makesit impossible forsomeone to guessthe appropriate response to any one particular challenge by a brute force attack (by responding to that challenge repeatedly with different answers). Basically, the only way to break such a system, short of a lucky guess, is to actually know some portion of the contents of the list of pairs. For this reason, one-time pads can be used over insecure communication channels. If someone snoops the communication, they can obtain that challenge-response pair. However, that information is of no use to them, since that particular challenge will never be issued again. (It does not even reduce the potential sample space for responses, since only the challenges must be unique.) Time-based authentication Thisis probably the least understood means of authentication, though it is commonly used by such technologies as SecurID. The concept isrelatively straightforward. You begin with a mathematical function that takes a small number of parameters (two, for example) and returns a new parameter. A good example of such a function is the function that generates the set of Fibonacci numbers (possibly truncated after a certain number of bits, with arbitrary initial seed values). Take this function, and add a third parameter, t, representing time in units of k seconds. Make the function be a generating function on t, with two seed values, a and b, where f(x,y) = (x + y) MOD (2 32 ) g(t) = a, 0 t k g(t) = b, k t 2k g(t) = f (g( log k t -2),g( log k t -1)) Security Considerations Remote Authentication 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 30In other words, every k seconds, you calculate a new value based on the previous two and some equation. Then discard the oldest value, replacing it with the second oldest value, and replace the second oldest value with the value that you just generated. As long as both ends have the same notion of the current time and the original two numbers, they can then calculate the most recently generated number and use this as a shared secret. Of course, if you are writing code that does this, you should use a closed form of this equation, since calculating Fibonacci numbers recursively without additional storage grows at O(2^(t/k)), which is not practical when t is measured in years and k is a small constant measured in seconds. The security ofsuch a scheme depends on various properties of the generator function, and the details ofsuch a function are beyond the scope of this document. For more information, you should obtain an introductory text on cryptography,. such as Bruce Schneier’s Applied Cryptography . Temporary Files Temporary files are a major source of security headaches. If a program does not set permissions correctly and in the right order, this can provide a means for an attacker to arbitrarily modify or read these files. The security impact of such modifications depends on the contents of the files. Temporary files are of much less concern to kernel programmers,since most kernel code does not use temporary files. Indeed, kernel code should generally not use files at all. However, many people programming in the kernel are doing so to facilitate the use of applicationsthat may use temporary files. Assuch, thisissue is worth noting. The most common problem with temporary files is that it is often possible for a malicious third party to delete the temporary file and substitute a different one with relaxed permissions in its place. Depending on the contents of the file, this could range from being a minor inconvenience to being a relatively large security hole, particularly if the file contains a shell script that is about to be executed with the permissions of the program’s user. /dev/mem and /dev/kmem One particularly painfulsurprise to people doing security programming in most UNIX or UNIX-like environments is the existence of /dev/mem and /dev/kmem. These device files allow the root user to arbitrarily access the contents of physical memory and kernel memory, respectively. There is absolutely nothing you can do to prevent this. From a kernel perspective, root is omnipresent and omniscient. If this is a security concern for your program, then you should consider whether your program should be used on a system controlled by someone else and take the necessary precautions. Security Considerations Temporary Files 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 31Note: Support for /dev/kmem is being phased out. It is not available on Intel-based Macintosh computers in OS X v10.4. In the future, it will be removed entirely. It is not possible to write device drivers that access PCI device memory through /dev/mem in OS X. If you need to support such a driver, you must write a kernel stub driver that matches against the device and mapsits memory space into the addressspace of the user process. For more information, read about user clients in I/O Kit Fundamentals. Key-based Authentication and Encryption Key-based authentication and encryption are ostensibly some of the more secure means of authentication and encryption, and can exist in many forms. The most common forms are based upon a shared secret. The DES, 3DES (triple-DES), IDEA, twofish, and blowfish ciphers are examples of encryption schemes based on a shared secret. Passwords are an example of an authentication scheme based on a shared secret. The idea behind most key-based encryption is that you have an encryption key of some arbitrary length that is used to encode the data, and that same key is used in the opposite manner (or in some cases, in the same manner) to decode the data. The problem with shared secret security is that the initial key exchange must occur in a secure fashion. If the integrity of the key is compromised during transmission, the data integrity is lost. This is not a concern if the key can be generated ahead of time and placed at both transport endpoints in a secure fashion. However, in many cases, this is not possible or practical because the two endpoints (be they physical devices or system tasks) are controlled by different people or entities. Fortunately, an alternative exists, known as zero-knowledge proofs. The concept of a zero-knowledge proof is that two seemingly arbitrary key values, x and y, are created, and that these values are related by some mathematical function ƒ in such a way that ƒ(ƒ(a,k1),k2) = a That is, applying a well-known function to the original cleartext using the first key results in ciphertext which, when that same function is applied to the ciphertext using the second key returns the original data. This is also reversible, meaning that ƒ(ƒ(a,k2),k1) = a Security Considerations Key-based Authentication and Encryption 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 32If the function f is chosen correctly, it is extremely difficult to derive x from y and vice-versa, which would mean that there is no function that can easily transform the ciphertext back into the cleartext based upon the key used to encode it. An example of this is to choose the mathematical function to be f(a,k)=((a*k) MOD 256) + ((a*k)/256) where a is a byte of cleartext, and k is some key 8 bits in length. This is an extraordinarily weak cipher, since the function f allows you to easily determine one key from the other, but it is illustrative of the basic concept. Pick k1 to be 8 and k2 to be 32. So for a=73, (a * 8)=584. This takes two bytes, so add the bits in the high byte to the bits of the low byte, and you get 74. Repeat this process with 32. This gives you 2368. Again, add the bits from the high byte to the bits of the low byte, and you have 73 again. This mathematical concept (with very different functions), when put to practical use, is known as public key (PK) cryptography, and forms the basis for RSA and DSA encryption. Public Key Weaknesses Public key encryption can be very powerful when used properly. However, it has a number of inherent weaknesses. A complete explanation of these weaknesses is beyond the scope of this document. However, it is important that you understand these weaknesses at a high level to avoid falling into some common traps. Some commonly mentioned weakness of public key cryptography include: ● Trust model for key exchange ● Pattern sensitivity ● Short data weakness Trust Models The most commonly discussed weakness of public key cryptography is the initial key exchange process itself. If someone manages to intercept a key during the initial exchange, he or she could instead give you his or her own public key and intercept messages going to the intended party. This is known as a man-in-the-middle attack. For such services as ssh, most people either manually copy the keys from one server to another or simply assume that the initial key exchange was successful. For most purposes, this is sufficient. In particularly sensitive situations, however, this is not good enough. For this reason, there is a procedure known as key signing. There are two basic models for key signing: the central authority model and the web of trust model. Security Considerations Key-based Authentication and Encryption 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 33The central authority model is straightforward. A central certifying agency signs a given key, and says that they believe the owner of the key is who he or she claims to be. If you trust that authority, then by association, you trust keys that the authority claims are valid. The web of trust model is somewhat different. Instead of a central authority, individuals sign keys belonging to other individuals. By signing someone’s key, you are saying that you trust that the person is really who he or she claims to be and that you believe that the key really belongs to him or her. The methods you use for determining that trust will ultimately impact whether others trust your signatures to be valid. There are many different ways of determining trust, and thus many groups have their own rulesfor who should and should not sign someone else’s key. Those rules are intended to make the trust level of a key depend on the trust level of the keys that have signed it. The line between central authorities and web of trust models is not quite as clear-cut as you might think, however. Many central authorities are hierarchies of authorities, and in some cases, they are actually webs of trust among multiple authorities. Likewise, many webs of trust may include centralized repositories for keys. While those repositories don’t provide any certification of the keys, they do provide centralized access. Finally, centralized authorities can easily sign keys as part of a web of trust. There are many websites that describe webs of trust and centralized certification schemes. A good general description of several such models can be found at http://world.std.com/~cme/html/web.html. Sensitivity to Patterns and Short Messages Existing public key encryption algorithms do a good job at encrypting semi-random data. They fallshort when encrypting data with certain patterns, as these patterns can inadvertently reveal information about the keys. The particular patterns depend on the encryption scheme. Inadvertently hitting such a pattern does not allow you to determine the private key. However, they can reduce the search space needed to decode a given message. Short data weakness is closely related to pattern sensitivity. If the information you are encrypting consists of a single number, for example the number 1, you basically get a value that is closely related mathematically to the public key. If the intent is to make sure that only someone with the private key can get the original value, you have a problem. In other words, public key encryption schemes generally do not encrypt all patterns equally well. For thisreason (and because public key cryptography tendsto be slower than single key cryptography), public keys are almost never used to encrypt end-user data. Instead, they are used to encrypt a session key. This session key is then used to encrypt the actual data using a shared secret mechanism such as 3DES, AES, blowfish, and so on. Security Considerations Key-based Authentication and Encryption 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 34Using Public Keys for Message Exchange Public key cryptography can be used in many ways. When both keys are private, it can be used to send data back and forth. However this use is no more useful than a shared secret mechanism. In fact, it is frequently weaker, for the reasons mentioned earlier in the chapter. Public key cryptography becomes powerful when one key is made public. Assume that Ernie and Bert want to send coded messages. Ernie gives Bert his public key. Assuming that the key was not intercepted and replaced with someone else’s key, Bert can now send data to Ernie securely, because data encrypted with the public key can only be decrypted with the private key (which only Ernie has). Bert uses this mechanism to send a shared secret. Bert and Ernie can now communicate with each other using a shared secret mechanism, confident in the knowledge that no third party has intercepted that secret. Alternately, Bert could give Ernie his public key, and they could both encrypt data using each other’s public keys, or more commonly by using those public keys to encrypt a session key and encrypting the data with that session key. Using Public Keys for Identity Verification Public key cryptography can also be used for verification of identity. Kyle wants to know if someone on the Internet who claims to be Stan is really Stan. A few months earlier, Stan handed Kyle his public key on a floppy disk. Thus, since Kyle already has Stan’s public key (and trusts the source of that key), he can now easily verify Stan’s identity. To achieve this, Kyle sends a cleartext message and asks Stan to encrypt it. Stan encrypts it with his private key. Kyle then uses Stan’s public key to decode the ciphertext. If the resulting cleartext matches, then the person on the other end must be Stan (unless someone else has Stan’s private key). Using Public Keys for Data Integrity Checking Finally, public key cryptography can be used for signing. Ahmed is in charge of meetings of a secret society called the Stupid Acronym Preventionists club. Abraham is a member of the club and gets a TIFF file containing a notice of their next meeting, passed on by way of a fellow member of the science club, Albert. Abraham is concerned, however, that the notice might have come from Bubba, who is trying to infiltrate the SAPs. Ahmed, however, was one step ahead, and took a checksum of the original message and encrypted the checksum with his private key, and sent the encrypted checksum as an attachment. Abraham used Ahmed’s public key to decrypt the checksum, and found that the checksum did not match that of the actual document. He wisely avoided the meeting. Isaac, however, was tricked into revealing himself as a SAP because he didn’t remember to check the signature on the message. Security Considerations Key-based Authentication and Encryption 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 35The moral of thisstory? One should always beware of geekssharing TIFFs—that is, if the security ofsome piece of data isimportant and if you do not have a direct,secure means of communication between two applications, computers, people, and so on, you must verify the authenticity of any communication using signatures, keys, or some other similar method. This may save your data and also save face. Encryption Summary Encryption is a powerful technique for keeping data secure if the initial key exchange occursin a secure fashion. One meansfor thisisto have a public key,stored in a well-known (and trusted) location. This allowsfor one-way encrypted communication through which a shared secret can be transferred for later two-way encrypted communication. You can use encryption not only for protecting data, but also for verifying the authenticity of data by encrypting a checksum. You can also use it to verify the identity of a client by requiring that the client encrypt some random piece of data as proof that the client holds the appropriate encryption key. Encryption, however, is not the final word in computer security. Because it depends on having some form of trusted key exchange, additional infrastructure is needed in order to achieve total security in environments where communication can be intercepted and modified. Console Debugging Warning: Failure to follow this advice can unintentionally expose security-critical information. In traditional UNIX and UNIX-like systems, the console is owned by root. Only root sees console messages. For this reason, print statements in the kernel are relatively secure. In OS X, any user can run the Console application. This represents a major departure from other UNIX-like systems. While it is never a good idea to include sensitive information in kernel debugging statements, it is particularly important not to do so in OS X. You must assume that any information displayed to the console could potentially be read by any user on the system (since the console is virtualized in the form of a user-viewable window). Printing any information involving sensitive data, including its location on disk or in memory, represents a security hole, however slight, and you should write your code accordingly. Obviously this is of less concern if that information is only printed when the user sets a debugging flag somewhere, but for normal use, printing potentially private information to the console is strongly discouraged. Security Considerations Console Debugging 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 36You must also be careful not to inadvertently print information that you use for generating password hashes or encryption keys, such as seed values passed to a random number generator. This is, by necessity, not a complete list of information to avoid printing to the console. You must use your own judgement when deciding whether a piece of information could be valuable if seen by a third party, and then decide if it is appropriate to print it to the console. Code Passing There are many ways of passing executable code into the kernel from user space. For the purposes of this section, executable code is not limited to compiled object code. It includes any instructions passed into the kernel that significantly affect control flow. Examples of passed-in executable code range from simple rules such as the filtering code uploaded in many firewall designs to bytecode uploads for a SCSI card. If it is possible to execute your code in user space, you should not even contemplate pushing code into the kernel. For the rare occasion where no other reasonable solution exists, however, you may need to pass some form of executable code into the kernel. This section explains some of the security ramifications of pushing code into the kernel and the level of verification needed to ensure consistent operation. Here are some guidelines to minimize the potential for security holes: 1. No raw object code. Direct execution of code passed in from user space is very dangerous. Interpreted languages are the only reasonable solution for this sort of problem, and even this is fraught with difficulty. Traditional machine code can’t be checked sufficiently to ensure security compliance. 2. Bounds checking. Since you are in the kernel, you are responsible for making sure that any uploaded code does not randomly access memory and does not attempt to do direct hardware access. You would normally make this a feature of the language itself, restricting access to the data element on which the bytecode is operating. 3. Termination checking. With very, very few exceptions, the language chosen should be limited to code that can be verified to terminate, and you should verify accordingly. If your driver is stuck in a tightly rolled loop, it is probably unable to do its job, and may impact overall system performance in the process. A language that does not allow (unbounded) loops (for example, allowing for but not while or goto could be one way to ensure termination. 4. Validity checking. Security Considerations Code Passing 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 37Your bytecode interpreter would be responsible for checking ahead for any potentially invalid operations and taking appropriate punitive actions against the uploaded code. For example, if uploaded code is allowed to do math, then proper protection must be in place to handle divide by zero errors. 5. Sanity checking. You should verify that the output is something remotely reasonable, if possible. It is not always possible to verify that the output is correct, but it is generally possible to create rules that prevent egregiously invalid output. For example, a network filter rule should output something resembling packets. If the checksums are bad, or if other information is missing or corrupt, clearly the uploaded code is faulty, and appropriate actions should be taken. It would be highly inappropriate for OS X to send out bad network traffic. In general, the more restrictive the language set, the lower the security risk. For example, interpreting simple network routing policies is less likely to be a security problem than interpreting packet rewriting rules, which is less likely to be an issue than running Java bytecode in the kernel. As with anything else, you must carefully weigh the potential benefits against the potential drawbacks and make the best decision given the information available. Security Considerations Code Passing 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 38Performance is a key aspect of any software system. Nowhere is this more true than in the kernel, where small performance problems tend to be magnified by repeated execution. For this reason, it is extremely important that your code be as efficient as possible. This chapter discusses the importance of low interrupt latency and fine-grained locking and tells you how to determine what portions of your code would benefit most from more efficient design. Interrupt Latency In OS X, you will probably never need to write code that runs in an interrupt context. In general, only motherboard hardware requires this. However, in the unlikely event that you do need to write code in an interrupt context, interrupt latency should be a primary concern. Interrupt latency refers to the delay between an interrupt being generated and an interrupt handler actually beginning to service that interrupt. In practice, the worst case interrupt latency is closely tied to the amount of time spent in supervisor mode (also called kernel mode) with interrupts off while handling some other interrupt. Low interrupt latency is necessary for reasonable overall performance, particularly when working with audio and video. In order to have reasonable soft real-time performance (for example, performance of multimedia applications), the interrupt latency caused by every device driver must be both small and bounded. OS X takes great care to bound and minimize interrupt latency for built-in drivers. It doesthis primarily through the use of interrupt service threads (also known as I/O service threads). When OS X takes an interrupt, the low-level trap handlers call up to a generic interrupt handling routine that clears the pending interrupt bit in the interrupt controller and calls a device-specific interrupt handler. That device-specific handler, in turn, sends a message to an interrupt service thread to notify it that an interrupt has occurred, and then the handler returns. When no further interrupts are pending, control returns to the currently executing thread. The next time the interrupt service thread is scheduled, it checks to see if an interrupt has occurred, then services the interrupt. As the name suggests, this actually is happening in a thread context, not an interrupt context. This design causes two major differences from traditional operating system design: ● Interrupt latency is near zero, since the code executing in an interrupt context is very small. 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 39 Performance Considerations● It is possible for an interrupt to occur while a device driver is executing. This means that traditional (threaded) device drivers can be preempted and must use locking or other similar methods to protect any shared data (although they need to do so anyway to work on computers with multiple processors). This model is crucial to the performance of OS X. You should not attempt to circumvent this design by doing large amounts of work in an interrupt context. Doing so will be detrimental to the overall performance of the system. Locking Bottlenecks It is difficult to communicate data between multiple threads or between thread and interrupt contexts without using locking or other synchronization. This locking protects your data from getting clobbered by another thread. However, it also has the unfortunate side effect of being a potential bottleneck. In some types of communication (particularly n-way), locking can dramatically hinder performance by allowing only one thing to happen at a time. Read-write locks, discussed in “Synchronization Primitives” (page 128), can help alleviate this problem in the most common situation where multiple clients need to be able to read information but only rarely need to modify that data. However, there are many cases where read-write locks are not helpful. This section discusses some possible problems and ways of improving performance within those constraints. Working With Highly Contended Locks When many threads need to obtain a lock (or a small number of threads need to obtain a lock frequently), this lock is considered highly contended. Highly contended locks frequently represent faulty code design, but they are sometimes unavoidable. In those cases, the lock tends to become a major performance bottleneck. Take, for example, the issue of many-to-many communication that must be synchronized through a common buffer. While some improvement can be gained by using read-write locks instead of an ordinary mutex, the issue of multiple writers means that read-write locks still perform badly. One possible solution for this many-to-many communication problem is to break the lock up into multiple locks. Instead of sharing a single buffer for the communication itself, make a shared buffer that contains accounting information for the communication (for example, a list of buffers available for reading). Then assign each individual buffer its own lock. The readers might then need to check several locations to find the right data, but this still frequently yields better performance, since writers must only contend for a write lock while modifying the accounting information. Performance Considerations Locking Bottlenecks 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 40Anothersolution for many-to-many communicationsisto eliminate the buffer entirely and communicate using message passing, sockets, IPC, RPC, or other methods. Yet another solution is to restructure your code in a way that the locking is unnecessary. This is often much more difficult. One method that is often helpful isto take advantage of flags and atomic increments, as outlined in the next paragraph. For simplicity, a single-writer, single-reader example is presented, but it is possible to extend this idea to more complicated designs. Take a buffer with some number of slots. Keep a read index and a write index into that buffer. When the write index and read index are the same, there is no data in the buffer. When writing, clear the next location. Then do an atomic increment on the pointer. Write the data. End by setting a flag at that new location that says that the data is valid. Note that this solution becomes much more difficult when dealing with multiple readers and multiple writers, and as such, is beyond the scope of this section. Reducing Contention by Decreasing Granularity One of the fundamental properties of locksis granularity. The granularity of a lock refersto the amount of code or data that it protects. A lock that protects a large block of code or a large amount of data is referred to as a coarse-grained lock, while a lock that protects only a small amount of code or data isreferred to as a fine-grained lock. A coarse-grained lock is much more likely to be contended (needed by one thread while being held by another) than a more finely grained lock. There are two basic ways of decreasing granularity. The first is to minimize the amount of code executed while a lock is held. For example, if you have code that calculates a value and stores it into a table, don’t take the lock before calling the function and release it after the function returns. Instead, take the lock in that piece of code right before you write the data, and release it as soon as you no longer need it. Of course, reducing the amount of protected code is not always possible or practical if the code needs to guarantee consistency where the value it is writing depends on other values in the table, since those values could change before you obtain the lock, requiring you to go back and redo the work. It is also possible to reduce granularity by locking the data in smaller units. In the above example, you could have a lock on each cell of the table. When updating cells in the table, you would start by determining the cells on which the destination cell depends, then lock those cells and the destination cell in some fixed order. (To avoid deadlock, you must always either lock cells in the same order or use an appropriate try function and release all locks on failure.) Once you have locked all the cells involved, you can then perform your calculation and release the locks, confident that no other thread has corrupted your calculations. However, by locking on a smaller unit of data, you have also reduced the likelihood of two threads needing to access the same cell. Performance Considerations Locking Bottlenecks 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 41A slightly more radical version of this is to use read-write locks on a per-cell basis and always upgrade in a particular order. This is, however, rather extreme, and difficult to do correctly. Code Profiling Code profiling means determining how often certain pieces of code are executed. By knowing how frequently a piece of code is used, you can more accurately gauge the importance of optimizing that piece of code. There are a number of good tools for profiling user space applications. However, code profiling in the kernel is a very different beast, since it isn’t reasonable to attach to it like you would a running process. (It is possible by using a second computer, but even then, it is not a trivial task.) This section describes two useful ways of profiling your kernel code: counters and lock profiling. Any changes you make to allow code profiling should be done only during development. These are not the sort of changes that you want to release to end users. Using Counters for Code Profiling The first method of code profiling is with counters. To profile a section of code with a counter, you must first create a global variable whose name describesthat piece of code and initialize it to zero. You then add something like #ifdef PROFILING foo_counter++; #endif in the appropriate piece of code. If you then define PROFILING, that counter is created and initialized to zero, then incremented each time the code in question is executed. One small snag with this sort of profiling is the problem of obtaining the data. This can be done in several ways. The simplest is probably to install a sysctl, using the address of foo_counter as an argument. Then, you could simply issue the sysctl command from the command line and read or clear the variable. Adding a sysctl is described in more detail in “BSD sysctl API ” (page 117). In addition to using sysctl, you could also obtain the data by printing its value when unloading the module (in the case of a KEXT) or by using a remote debugger to attach to the kernel and directly inspecting the variable. However, a sysctl provides the most flexibility. With a sysctl, you can sample the value at any time, not just when the module is unloaded. The ability to arbitrarily sample the value makes it easier to determine the importance of a piece of code to one particular action. Performance Considerations Code Profiling 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 42If you are developing code for use in the I/O Kit, you should probably use your driver’s setProperties call instead of a sysctl. Lock Profiling Lock profiling is another useful way to find the cause of code inefficiency. Lock profiling can give you the following information: ● how many times a lock was taken ● how long the lock was held on average ● how often the lock was unavailable Put another way, this allows you to determine the contention of a lock, and in so doing, can help you to minimize contention by code restructuring. There are many different ways to do lock profiling. The most common way is to create your own lock calls that increment a counter and then call the real locking functions. When you move from debugging into a testing cycle before release, you can then replace the functions with defines to cause the actual functions to be called directly. For example, you might write something like this: extern struct timeval time; boolean_t mymutex_try(mymutex_t *lock) { int ret; ret=mutex_try(lock->mutex); if (ret) { lock->tryfailcount++; } return ret; } void mymutex_lock(mymutex_t *lock) { if (!(mymutex_try(lock))) { mutex_lock(lock->mutex); } lock->starttime = time.tv_sec; } void mymutex_unlock(mymutex_t *lock) { Performance Considerations Code Profiling 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 43lock->lockheldtime += (time.tv_sec - lock->starttime); lock->heldcount++; mutex_unlock(lock->mutex); } This routine has accuracy only to the nearest second, which is not particularly accurate. Ideally, you want to keep track of both time.tv_sec and time.tv_usec and roll the microseconds into seconds as the number gets large. From this information, you can obtain the average time the lock was held by dividing the total time held by the number of times it was held. It also tells you the number of times a lock was taken immediately instead of waiting, which is a valuable piece of data when analyzing contention. As with counter-based profiling, after you have written code to record lock use and contention, you must find a way to obtain that information. A sysctl is a good way of doing this, since it is relatively easy to implement and can provide a “snapshot” view of the data structure at any point in time. For more information on adding a sysctl, see “BSD sysctl API ” (page 117). Another way to do lock profiling isto use the built-in ETAP (Event Trace Analysis Package). This package consists of additional code designed for lock profiling. However, since this requires a kernel recompile, it is generally not recommended. Performance Considerations Code Profiling 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 44As described in “Keep Out” (page 13), programming in the kernel is fraught with hazards that can cause instability, crashes, or security holes. In addition to these issues, programming in the kernel has the potential for compatibility problems. If you program only to the interfaces discussed in this document or other Apple documents, you will avoid the majority of these. However, even limiting yourself to documented interfaces does not protect you from a handful of pitfalls. The biggest potential problem that you face is namespace collision, which occurs when your function, variable, or class name is the same as someone else’s. Since this makes one kernel extension or the other fail to load correctly (in a non-deterministic fashion), Apple has established function naming conventions for C and C++ code within the kernel. These are described in “Standard C Naming Conventions” (page 47) and “C++ Naming Conventions” (page 45), respectively. In addition to compatibility problems, kernel extensions that misbehave can also dramatically decrease the system’s overall performance or cause crashes. Some of these issues are described in “Performance and Stability Tips” (page 50). For more thorough coverage of performance and stability, you should also read the chapters “Security Considerations” (page 24) and “Performance Considerations” (page 39). C++ Naming Conventions Basic I/O Kit C++ naming conventions are defined in the document I/O Kit Device Driver Design Guidelines. This section refines those conventions in ways that should make them more useful to you as a programmer. Basic Conventions The primary conventions are as follows: ● Use the Java-style reverse DNS naming convention, substituting underscores for periods. For example, com_apple_foo. ● Avoid the following reserved prefixes: ● OS ● os ● IO ● io 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 45 Kernel Programming Style● Apple ● apple ● AAPL ● aapl This ensures that you will not collide with classes created by other companies or with future classes added to the operating system by Apple. It does not protect you from other projects created within your company, however, and for this reason, some additional guidelines are suggested. Additional Guidelines These additional guidelines are intended to minimize the chance of accidentally breaking your own software and to improve readability of code by developers. ● To avoid namespace collisions, you should prefix the names of classes and families with project names or other reasonably unique prefix codes. For example, if you are working on a video capture driver, and one of its classes is called capture, you will probably encounter a name collision eventually. Instead, you should name the class something like com_mycompany_driver_myproduct_capture. Similarly, names like To maximize readability, you should use macros to rename classes and families at compile time. For example: #define captureClass com_mycompany_driver_myproduct_capture #define captureFamily com_mycompany_iokit_myproduct_capture ● Use prefixes in function and method names to make it easier to see relationships between them. For example, Apple uses NS, CF, IO, and other prefixesto indicate that functions belong to specific frameworks. This might be as simple as prefixing a function with the name of the enclosing or related class, or it might be some other scheme that makes sense for your project. These are only suggested guidelines. Your company or organization should adopt its own set of guidelines within the constraints of the basic conventions described in the previous section. These guidelines should provide a good starting point. Kernel Programming Style C++ Naming Conventions 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 46Standard C Naming Conventions The naming conventionsfor C++ have been defined forsome time in the document I/O Kit Device Driver Design Guidelines. However, no conventions have been given for standard C code. Because standard C has an even greater chance of namespace collision than C++, it is essential that you follow these guidelines when writing C code for use in the kernel. Because C does not have the benefit of classes, it is much easier to run into a naming conflict between two functions. For this reason, the following conventions are suggested: ● Declare all functions and (global) variables static where possible to prevent them from being seen in the global namespace. If you need to share these across files within your KEXT, you can achieve a similar effect by declaring them __private_extern__. ● Each function name should use Java-style reverse DNS naming. For example, if your company is apple.com, you should begin each function with com_apple_. ● Follow the reverse DNS name with the name of your project. For example, if you work at Apple and were working on project Schlassen, you would start each function name (in drivers) with com_apple_driver_schlassen_. Note: The term driver is reserved for actual device drivers. For families, you should instead use iokit. For example, if project Schlassen is an I/O Kit family, function namesshould all begin with com_apple_iokit_schlassen_. ● Use hierarchical names if you anticipate multiple projects with similar names coming from different parts of your company or organization. ● Use macro expansion to save typing, for example PROJECT_eat could expand to com_apple_driver_schlassen_pickle_eat. ● If you anticipate that the last part of a function name may be the same as the last part of another function name (for example, PROJECT1_eat and PROJECT2_eat), you should change the namesto avoid confusion (for example, PROJECT1_eatpickle and PROJECT2_eatburger). ● Avoid the following reserved prefixes: ● OS ● os ● IO ● io ● Apple ● apple Kernel Programming Style Standard C Naming Conventions 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 47● AAPL ● aapl ● Avoid conflicting with any names already in the kernel, and do not use prefixes similar to those of existing kernel functions that you may be working with. ● Never begin a function name with an underscore (_). ● Under no circumstances should you use common names for your functions without prefixing them with the name of your project in some form. These are some examples of unacceptable names: ● getuseridentity ● get_user_info ● print ● find ● search ● sort ● quicksort ● merge ● console_log In short, picking any name that you would normally pick for a function is generally a bad idea, because every other developer writing code is likely to pick the same name for his or her function. Occasional conflicts are a fact of life. However, by following these few simple rules, you should be able to avoid the majority of common namespace pitfalls. Commonly Used Functions One of the most common problems faced when programming in the kernel is use of “standard” functions—things like printf or bcopy. Many commonly used standard C library functions are implemented in the kernel. In order to use them, however, you need to include the appropriate prototypes, which may be different from the user space prototypes for those functions, and which generally have different names when included from kernel code. In general, any non–I/O Kit header that you can safely include in the kernel is located in xnu/bsd/sys or xnu/osfmk/mach, although there are a few specialized headers in other places like libkern and libsa. Normal headers (those in /usr/include) cannot be used in the kernel. Kernel Programming Style Commonly Used Functions 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 48Important: If you are writing an I/O Kit KEXT, most of these functions are not what you are looking for. The I/O Kit providesits own APIsfor these features, including IOLog, IOMemoryDescriptor, and IOLock. While using the lower-level functionality is not expressly forbidden, it is generally discouraged (though printf is always fine). For more information about APIs available to I/O Kit KEXTs, see Kernel Framework Reference . Table 7-1 (page 49) lists some commonly used C functions, variables, and types, and gives the location of their prototypes. Table 7-1 Commonly used C functions Function name Header path printf Buffer cache functions (bread, bwrite, and brelse) Directory entries Error numbers Kernel special variables Spinlocks malloc Queues Random number generator bzero, bcopy, copyin, and copyout timeout and untimeout Various time functions Standard type declarations User credentials OS and system information If the standard C function you are trying to use is not in one of these files, chances are the function is not supported for use within the kernel, and you need to implement your code in another way. Kernel Programming Style Commonly Used Functions 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 49The symbols in these header files are divided among multiple symbol sets, depending on the technology area where they were designed to be used. To use these, you may have to declare dependencies on any of the following: ● com.apple.kernel—You should generally avoid this. ● com.apple.kernel.bsd—BSD portions of the kernel. ● com.apple.kernel.iokit—The I/O Kit. ● com.apple.kernel.libkern—General-purpose functions. ● com.apple.kernel.mach—Mach-specific APIs. ● com.apple.kpi.bsd—BSD portions of the kernel (v10.4 and later). ● com.apple.kernel.iokit—The I/O Kit (v10.4 and later). ● com.apple.kernel.libkern—General-purpose functions (v10.4 and later). ● com.apple.kernel.mach—Mach-specific APIs (v10.4 and later). ● com.apple.kpi.unsupported—Unsupported legacy functionality (v10.4 and later). Where possible, you should specify a dependency on the KPI version of these symbols. However, these symbols are only available in v10.4 and later. For the I/O Kit and libkern, this should make little difference. For other areas, such as network kernel extensions or file system KEXTs, you must use the KPI versions if you want your extension to load in OS X v10.4 and later. For a complete list of symbols in any of these dependencies, run nm on the binaries in /System/Library/Extensions/System.kext/PlugIns. Performance and Stability Tips This section includes some basic tips on performance and stability. You should read the sections on security and performance for additional information. These tips cover only style issues, not general performance or stability issues. Performance and Stability Tips Programming in the kernel is subject to a number of restrictions that do not exist in application programming. The first and most important is the stack size. The kernel has a limited amount of space allocated for thread stacks, which can cause problems if you aren’t aware of the limitation. This means the following: ● Recursion must be bounded (to no more than a few levels). ● Recursion should be rewritten as iterative routines where possible. Kernel Programming Style Performance and Stability Tips 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 50● Large stack variables(function local) are dangerous. Do not use them. This also appliesto large local arrays. ● Dynamically allocated variables are preferred (using malloc or equivalent) over local variables for objects more than a few bytes in size. ● Functions should have as few arguments as possible. ● Pass pointers to structures, not the broken out elements. ● Don’t use arguments to avoid using global or class variables. ● Do name global variables in a way that protects you from collision. ● C++ functions should be declared static. ● Functions not obeying these rules can cause a kernel panic, or in extreme cases, do not even compile. In addition to issues of stack size, you should also avoid doing anything that would generate unnecessary load such as polling a device or address. A good example is the use of mutexes rather than spinlocks. You should also structure your locks in such a way to minimize contention and to minimize hold times on the most highly contended locks. Also, since unused memory (and particularly wired memory) can cause performance degradation, you should be careful to deallocate memory when it is no longer in use, and you should never allocate large regions of wired memory. This may be unavoidable in some applications, but should be avoided whenever possible and disposed of at the earliest possible opportunity. Allocating large contiguous blocks of memory at boot time is almost never acceptable, because it cannot be released. There are a number of issues that you should consider when deciding whether to use floating point math or AltiVec vector math in the kernel. First, the kernel takes a speed penalty whenever floating-point math or AltiVec instructions are used in a system call context (or other similar mechanisms where a user thread executes in a kernel context), as floating-point and AltiVec registers are only maintained when they are in use. Note: In cases where altivec or floating point has already been used in user space in the calling thread, there is no additional penalty for using them in the kernel. Thus, for things like audio drivers, the above does not apply. In general, you should avoid doing using floating-point math or AltiVec instructions in the kernel unless doing so will result in a significant speedup. It is not forbidden, but is strongly discouraged. Second, AltiVec was not supported in the kernel prior to OS X v10.3. It was not possible to detect this support from within the kernel until a later 10.3 software update. If you must deploy your KEXT on earlier versions of OS X, you must either provide a non-AltiVec version of your code or perform the AltiVec instructions in user space. Kernel Programming Style Performance and Stability Tips 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 51Finally, AltiVec data stream instructions (dst, dstt, dstst, dss, and dssall) are not supported in the kernel, even for processors that support them in user space. Do not attempt to use them. If you decide to use AltiVec in the kernel, your code can determine whether the CPU supports AltiVec using the sysctlbyname call to get the hw.optional.altivec property. For more information, see “The sysctlbyname System Call” (page 123). Stability Tips ● Don’tsleep while holding resources(locks, for example). While thisis not forbidden, it isstrongly discouraged to avoid deadlock. ● Be careful to allocate and free memory with matching calls. For example, do not use allocation routines from the I/O Kit and deallocation routines from BSD. Likewise, do not use IOMallocContiguous with IOFreePageable. ● Use reference counts to avoid freeing memory that is still in use elsewhere. Be sure to deallocate memory when its reference count reaches zero, but not before. ● Lock objects before operating on them, even to change reference counts. ● Never dereference pointers without verifying that they are not NULL. In particular, never do this: int foo = *argptr; unless you have already verified that argptr cannot possibly be NULL. ● Test code in sections and try to think up likely edge cases for calculations. ● Never assume that your code will be run only on big endian processors. ● Never assume that the size of an instance of a type will never change. Always use sizeof if you need this information. ● Never assume that a pointer will always be the same size as an int or long. Style Summary Kernel programming style is very much a matter of personal preference, and it is not practical to programmatically enforce the guidelines in this chapter. However, we strongly encourage you to follow these guidelines to the maximum extent possible. These guidelines were created based on frequent problems reported by developers writing code in the kernel. No one can force you to use good style in your programming, but if you do not, you do so at your own peril. Kernel Programming Style Style Summary 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 52The fundamental services and primitives of the OS X kernel are based on Mach 3.0. Apple has modified and extended Mach to better meet OS X functional and performance goals. Mach 3.0 was originally conceived as a simple, extensible, communications microkernel. It is capable of running as a stand–alone kernel, with other traditional operating-system servicessuch asI/O, file systems, and networking stacks running as user-mode servers. However, in OS X, Mach is linked with other kernel components into a single kernel address space. This is primarily for performance; it is much faster to make a direct call between linked components than it is to send messages or do remote procedure calls (RPC) between separate tasks. This modular structure results in a more robust and extensible system than a monolithic kernel would allow, without the performance penalty of a pure microkernel. Thusin OS X, Mach is not primarily a communication hub between clients and servers. Instead, its value consists of its abstractions, its extensibility, and its flexibility. In particular, Mach provides ● object-based APIs with communication channels (for example, ports) as object references ● highly parallel execution, including preemptively scheduled threads and support for SMP ● a flexible scheduling framework, with support for real-time usage ● a complete set of IPC primitives, including messaging, RPC, synchronization, and notification ● support for large virtual addressspaces,shared memory regions, and memory objects backed by persistent store ● proven extensibility and portability, for example across instruction set architectures and in distributed environments ● security and resource management as a fundamental principle of design; all resources are virtualized Mach Kernel Abstractions Mach provides a small set of abstractions that have been designed to be both simple and powerful. These are the main kernel abstractions: ● Tasks. The units of resource ownership; each task consists of a virtual addressspace, a portright namespace, and one or more threads. (Similar to a process.) 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 53 Mach Overview● Threads. The units of CPU execution within a task. ● Address space. In conjunction with memory managers, Mach implements the notion of a sparse virtual address space and shared memory. ● Memory objects. The internal units of memory management. Memory objectsinclude named entries and regions; they are representations of potentially persistent data that may be mapped into address spaces. ● Ports. Secure, simplex communication channels, accessible only via send and receive capabilities (known as port rights). ● IPC. Message queues, remote procedure calls, notifications, semaphores, and lock sets. ● Time. Clocks, timers, and waiting. At the trap level, the interface to most Mach abstractions consists of messages sent to and from kernel ports representing those objects. The trap-level interfaces (such as mach_msg_overwrite_trap) and message formats are themselves abstracted in normal usage by the Mach Interface Generator (MIG). MIG is used to compile procedural interfaces to the message-based APIs, based on descriptions of those APIs. Tasks and Threads OS X processes and POSIX threads (pthreads) are implemented on top of Mach tasks and threads, respectively. A thread is a point of control flow in a task. A task exists to provide resources for the threads it contains. This split is made to provide for parallelism and resource sharing. A thread ● is a point of control flow in a task. ● has access to all of the elements of the containing task. ● executes (potentially) in parallel with other threads, even threads within the same task. ● has minimal state information for low overhead. A task ● is a collection ofsystem resources. These resources, with the exception of the addressspace, are referenced by ports. These resources may be shared with other tasks if rights to the ports are so distributed. ● provides a large, potentially sparse address space, referenced by virtual address. Portions of this space may be shared through inheritance or external memory management. ● contains some number of threads. Mach Overview Tasks and Threads 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 54Note that a task has no life of its own—only threads execute instructions. When it is said that “task Y does X,” what is really meant is that “a thread contained within task Y does X.” A task is a fairly expensive entity. It exists to be a collection of resources. All of the threads in a task share everything. Two tasks share nothing without an explicit action (although the action is often simple) and some resources (such as port receive rights) cannot be shared between two tasks at all. A thread is a fairly lightweight entity. It is fairly cheap to create and has low overhead to operate. This is true because a thread has little state information (mostly its register state). Its owning task bears the burden of resource management. On a multiprocessor computer, it is possible for multiple threads in a task to execute in parallel. Even when parallelism is not the goal, multiple threads have an advantage in that each thread can use a synchronous programming style, instead of attempting asynchronous programming with a single thread attempting to provide multiple services. A thread is the basic computational entity. A thread belongs to one and only one task that defines its virtual address space. To affect the structure of the address space or to reference any resource other than the address space, the thread must execute a special trap instruction that causesthe kernel to perform operations on behalf of the thread or to send a message to some agent on behalf of the thread. In general, these traps manipulate resources associated with the task containing the thread. Requests can be made of the kernel to manipulate these entities: to create them, delete them, and affect their state. Mach provides a flexible framework for thread–scheduling policies. Early versions of OS X support both time-sharing and fixed-priority policies. A time-sharing thread’s priority is raised and lowered to balance its resource consumption against other time-sharing threads. Fixed-priority threads execute for a certain quantum of time, and then are put at the end of the queue of threads of equal priority. Setting a fixed priority thread’s quantum level to infinity allows the thread to run until it blocks, or until it is preempted by a thread of higher priority. High priority real-time threads are usually fixed priority. OS X also provides time constraint scheduling for real-time performance. This scheduling allows you to specify that your thread must get a certain time quantum within a certain period of time. Mach scheduling is described further in “Mach Scheduling and Thread Interfaces” (page 77). Ports, Port Rights, Port Sets, and Port Namespaces With the exception of the task’s virtual address space, all other Mach resources are accessed through a level of indirection known as a port. A port is an endpoint of a unidirectional communication channel between a client who requests a service and a server who providesthe service. If a reply isto be provided to such a service request, a second port must be used. This is comparable to a (unidirectional) pipe in UNIX parlance. Mach Overview Ports, Port Rights, Port Sets, and Port Namespaces 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 55In most cases, the resource that is accessed by the port (that is, named by it) is referred to as an object. Most objects named by a port have a single receiver and (potentially) multiple senders. That is, there is exactly one receive port, and at least one sending port, for a typical object such as a message queue. The service to be provided by an object is determined by the manager that receives the request sent to the object. It follows that the kernel is the receiver for ports associated with kernel-provided objects and that the receiver for ports associated with task-provided objects is the task providing those objects. For ports that name task-provided objects, it is possible to change the receiver of requests for that port to a different task, for example by passing the port to that task in a message. A single task may have multiple ports that refer to resources it supports. For that matter, any given entity can have multiple ports that represent it, each implying different sets of permissible operations. For example, many objects have a name port and a control port (sometimes called the privileged port). Access to the control port allows the object to be manipulated; access to the name port simply names the object so that you can obtain information about it or perform other non-privileged operations against it. Tasks have permissions to access ports in certain ways (send, receive, send-once); these are called port rights. A port can be accessed only via a right. Ports are often used to grant clients access to objects within Mach. Having the right to send to the object’sIPC port denotesthe right to manipulate the object in prescribed ways. As such, port right ownership is the fundamental security mechanism within Mach. Having a right to an object is to have a capability to access or manipulate that object. Port rights can be copied and moved between tasks via IPC. Doing so, in effect, passes capabilities to some object or server. One type of object referred to by a port is a port set. As the name suggests, a port set is a set of port rights that can be treated as a single unit when receiving a message or event from any of the members of the set. Port sets permit one thread to wait on a number of message and event sources, for example in work loops. Traditionally in Mach, the communication channel denoted by a port was always a queue of messages. However, OS X supports additional types of communication channels, and these new types of IPC object are also represented by ports and port rights. See the section “Interprocess Communication (IPC)” (page 58), for more details about messages and other IPC types. Ports and port rights do not have systemwide names that allow arbitrary ports or rights to be manipulated directly. Ports can be manipulated by a task only if the task has a port right in its port namespace. A port right is specified by a port name, an integer index into a 32-bit port namespace. Each task has associated with it a single port namespace. Tasks acquire port rights when another task explicitly insertsthem into its namespace, when they receive rights in messages, by creating objects that return a right to the object, and via Mach calls for certain special ports (mach_thread_self, mach_task_self, and mach_reply_port.) Mach Overview Ports, Port Rights, Port Sets, and Port Namespaces 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 56Memory Management As with most modern operating systems, Mach provides addressing to large, sparse, virtual address spaces. Runtime access is made via virtual addresses that may not correspond to locations in physical memory at the initial time of the attempted access. Mach is responsible for taking a requested virtual address and assigning it a corresponding location in physical memory. It does so through demand paging. A range of a virtual address space is populated with data when a memory object is mapped into that range. All data in an addressspace is ultimately provided through memory objects. Mach asksthe owner of a memory object (a pager) for the contents of a page when establishing it in physical memory and returns the possibly modified data to the pager before reclaiming the page. OS X includes two built-in pagers—the default pager and the vnode pager. The default pager handles nonpersistent memory, known as anonymous memory. Anonymous memory is zero-initialized, and it exists only during the life of a task. The vnode pager maps files into memory objects. Mach exports an interface to memory objects to allow their contents to be contributed by user-mode tasks. This interface is known as the External Memory Management Interface, or EMMI. The memory management subsystem exports virtual memory handles known as named entries or named memory entries. Like most kernel resources, these are denoted by ports. Having a named memory entry handle allows the owner to map the underlying virtual memory object or to pass the right to map the underlying object to others. Mapping a named entry in two different tasks results in a shared memory window between the two tasks, thus providing a flexible method for establishing shared memory. Beginning in OS X v10.1, the EMMI system was enhanced to support “portless” EMMI. In traditional EMMI, two Mach ports were created for each memory region, and likewise two ports for each cached vnode. Portless EMMI, in its initial implementation, replaces this with direct memory references (basically pointers). In a future release, ports will be used for communication with pagers outside the kernel, while using direct references for communication with pagers that reside in kernel space. The net result of these changes is that early versions of portless EMMI do not support pagers running outside of kernel space. This support is expected to be reinstated in a future release. Addressranges of virtual memory space may also be populated through direct allocation (using vm_allocate). The underlying virtual memory object is anonymous and backed by the default pager. Shared ranges of an address space may also be set up via inheritance. When new tasks are created, they are cloned from a parent. This cloning pertains to the underlying memory address space as well. Mapped portions of objects may be inherited as a copy, or asshared, or not at all, based on attributes associated with the mappings. Mach practices a form of delayed copy known as copy-on-write to optimize the performance of inherited copies on task creation. Mach Overview Memory Management 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 57Rather than directly copying the range, a copy-on-write optimization is accomplished by protected sharing. The two tasks share the memory to be copied, but with read-only access. When either task attempts to modify a portion of the range, that portion is copied at that time. Thislazy evaluation of memory copiesis an important optimization that permits simplifications in several areas, notably the messaging APIs. One other form of sharing is provided by Mach, through the export of named regions. A named region is a form of a named entry, but instead of being backed by a virtual memory object, it is backed by a virtual map fragment. This fragment may hold mappings to numerous virtual memory objects. It is mappable into other virtual maps, providing a way of inheriting not only a group of virtual memory objects but also their existing mapping relationships. This feature offers significant optimization in task setup, for example when sharing a complex region of the address space used for shared libraries. Interprocess Communication (IPC) Communication between tasksis an important element of the Mach philosophy. Mach supports a client/server system structure in which tasks(clients) accessservices by making requests of other tasks(servers) via messages sent over a communication channel. The endpoints of these communication channels in Mach are called ports, while port rights denote permission to use the channel. The forms of IPC provided by Mach include ● message queues ● semaphores ● notifications ● lock sets ● remote procedure calls (RPCs) The type of IPC object denoted by the port determines the operations permissible on that port, and how (and whether) data transfer occurs. Important: The IPC facilities in OS X are in a state of transition. In early versions of the system, not all of these IPC types may be implemented. There are two fundamentally different Mach APIs for raw manipulation of ports—the mach_ipc family and the mach_msg family. Within reason, both families may be used with any IPC object; however, the mach_ipc calls are preferred in new code. The mach_ipc calls maintain state information where appropriate in order to support the notion of a transaction. The mach_msg calls are supported for legacy code but deprecated; they are stateless. Mach Overview Interprocess Communication (IPC) 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 58IPC Transactions and Event Dispatching When a thread calls mach_ipc_dispatch, it repeatedly processes events coming in on the registered port set. These events could be an argument block from an RPC object (as the results of a client’s call), a lock object being taken (as a result of some other thread’s releasing the lock), a notification or semaphore being posted, or a message coming in from a traditional message queue. These events are handled via callouts from mach_msg_dispatch. Some events imply a transaction during the lifetime of the callout. In the case of a lock, the state is the ownership of the lock. When the callout returns, the lock is released. In the case of remote procedure calls, the state is the client’s identity, the argument block, and the reply port. When the callout returns, the reply is sent. When the callout returns, the transaction (if any) is completed, and the thread waits for the next event. The mach_ipc_dispatch facility is intended to support work loops. Message Queues Originally, the sole style of interprocess communication in Mach was the message queue. Only one task can hold the receive right for a port denoting a message queue. This one task is allowed to receive (read) messages from the port queue. Multiple tasks can hold rights to the port that allow them to send (write) messages into the queue. A task communicates with another task by building a data structure that contains a set of data elements and then performing a message-send operation on a port for which it holds send rights. At some later time, the task with receive rights to that port will perform a message-receive operation. A message may consist of some or all of the following: ● pure data ● copies of memory ranges ● port rights ● kernel implicit attributes, such as the sender’s security token The message transfer is an asynchronous operation. The message is logically copied into the receiving task, possibly with copy-on-write optimizations. Multiple threads within the receiving task can be attempting to receive messages from a given port, but only one thread can receive any given message. Semaphores Semaphore IPC objects support wait, post, and post all operations. These are counting semaphores, in that posts are saved (counted) if there are no threads currently waiting in that semaphore’s wait queue. A post all operation wakes up all currently waiting threads. Mach Overview Interprocess Communication (IPC) 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 59Notifications Like semaphores, notification objects also support post and wait operations, but with the addition of a state field. The state is a fixed-size, fixed-format field that is defined when the notification object is created. Each post updates the state field; there is a single state that is overwritten by each post. Locks A lock is an object that provides mutually exclusive access to a critical section. The primary interfaces to locks are transaction oriented (see “IPC Transactions and Event Dispatching” (page 59)). During the transaction, the thread holds the lock. When it returns from the transaction, the lock is released. Remote Procedure Call (RPC) Objects As the name implies, an RPC object is designed to facilitate and optimize remote procedure calls. The primary interfaces to RPC objects are transaction oriented (see “IPC Transactions and Event Dispatching” (page 59)) When an RPC object is created, a set of argument block formats is defined. When an RPC (a send on the object) is made by a client, it causes a message in one of the predefined formats to be created and queued on the object, then eventually passed to the server (the receiver). When the server returns from the transaction, the reply isreturned to the sender. Mach triesto optimize the transaction by executing the server using the client’s resources; this is called thread migration. Time Management The traditional abstraction of time in Mach is the clock, which provides a set of asynchronous alarm services based on mach_timespec_t. There are one or more clock objects, each defining a monotonically increasing time value expressed in nanoseconds. The real-time clock is built in, and is the most important, but there may be other clocksfor other notions of time in the system. Clockssupport operationsto get the current time,sleep for a given period, set an alarm (a notification that is sent at a given time), and so forth. The mach_timespec_t API is deprecated in OS X. The newer and preferred API is based on timer objects that in turn use AbsoluteTime as the basic data type. AbsoluteTime is a machine-dependent type, typically based on the platform-native time base. Routines are provided to convert AbsoluteTime values to and from other data types,such as nanoseconds. Timer objectssupport asynchronous, drift-free notification, cancellation, and premature alarms. They are more efficient and permit higher resolution than clocks. Mach Overview Time Management 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 60This chapter describes allocating memory and the low-level routinesfor modifying memory mapsin the kernel. It also describes a number of commonly used interfaces to the virtual memory system. It does not describe how to make changes in paging policy or add additional pagers. OS X does not support external pagers, although much of the functionality can be achieved in other ways, some of which are covered at a high level in this chapter. The implementation details of these interfaces are subject to change, however, and are thus left undocumented. With the exception of the section “Allocating Memory in the Kernel” (page 73), this chapter is of interest only if you are writing file systems or are modifying the virtual memory system itself. OS X VM Overview The VM system used in OS X is a descendent of Mach VM, which was created at Carnegie Mellon University in the 1980s. To a large extent, the fundamental design is the same, although some of the details are different, particularly when enhancing the VM system. It does, however, support the ability to request certain paging behavior through the use of universal page lists (UPLs). See “Universal Page Lists (UPLs)” (page 65) for more information. The design of Mach VM centers around the concept of physical memory being a cache for virtual memory. At its highest level, Mach VM consists of address spaces and ways to manipulate the contents of those address spaces from outside the space. These address spaces are sparse and have a notion of protections to limit what tasks can access their contents. At a lower level, the object level, virtual memory is seen as a collection of VM objects and memory objects, each with a particular owner and protections. These objects can be modified with object callsthat are available both to the task and (via the back end of the VM) to the pagers. 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 61 Memory and Virtual MemoryNote: While memory objects and VM objects are closely related, the terms are not equivalent and should not be confused. .A VM object can be backed by one or more memory objects, which are, in turn, managed by a pager. A VM object may also be partially backed by other VM objects, as occurs in the case of shadow chains (described later in this section). The VM object is internal to the virtual memory system, and includes basic information about accessing the memory. The memory object, by contrast, is provided by the pager. The contents of the memory associated with that memory object can be retrieved from disk or some other backing store by exchanging messages with the memory object. Implicitly, each VM object is associated with a given pager through its memory object. VM objects are cached with system pages (RAM), which can be any power of two multiple of the hardware page size. In the OS X kernel,system pages are the same size as hardware pages. Each system page isrepresented in a given address space by a map entry. Each map entry has its own protection and inheritance. A given map entry can have an inheritance of shared, copy, or none. If a page is marked shared in a given map, child tasks share this page for reading and writing. If a page is marked copy, child tasks get a copy of this page (using copy-on-write). If a page is marked none, the child’s page is left unallocated. VM objects are managed by the machine-independent VM system, with the underlying virtual to physical mappings handled by the machine-dependent pmap system. The pmap system actually handles page tables, translation lookaside buffers, segments, and so on, depending on the design of the underlying hardware. When a VM object is duplicated (for example, the data pages from a process that has just called fork), a shadow object is created. A shadow object isinitially empty, and contains a reference to another object. When the contents of a page are modified, the page is copied from the parent object into the shadow object and then modified. When reading data from a page, if that page exists in the shadow object, the page listed in the shadow object is used. If the shadow object has no copy of that page, the original object is consulted. A series of shadow objects pointing to shadow objects or original objects is known as a shadow chain. Shadow chains can become arbitrarily long if an object is heavily reused in a copy-on-write fashion. However, since fork is frequently followed by exec, which replaces all of the material being shadowed, long chains are rare. Further, Mach automatically garbage collectsshadow objects, removing any intermediate shadow objects whose pages are no longer referenced by any (nondefunct) shadow object. It is even possible for the original object to be released if it no longer contains pages that are relevant to the chain. The VM calls available to an application include vm_map and vm_allocate, which can be used to map file data or anonymous memory into the address space. This is possible only because the address space is initially sparse. In general, an application can either map a file into its address space (through file mapping primitives, abstracted by BSD) or it can map an object (after being passed a handle to that object). In addition, a task can change the protections of the objects in its address space and can share those objects with other tasks. Memory and Virtual Memory OS X VM Overview 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 62In addition to the mapping and allocation aspects of virtual memory, the VM system contains a number of other subsystems. These include the back end (pagers) and the shared memory subsystem. There are also other subsystems closely tied to VM, including the VM shared memory server. These are described in “Other VM and VM-Related Subsystems” (page 68). Memory Maps Explained Each Mach task has its own memory map. In Mach, this memory map takes the form of an ordered doubly linked list. As described in “OS X VM Overview” (page 61), each of these objects contains a list of pages and shadow references to other objects. In general, you should never need to access a memory map directly unless you are modifying something deep within the VM system. The vm_map_entry structure contains task-specific information about an individual mapping along with a reference to the backing object. In essence, it is the glue between an VM object and a VM map. While the details of this data structure are beyond the scope of this document, a few fields are of particular importance. The field is_submap is a Boolean value that tells whether this map entry is a normal VM object or a submap. A submap is a collection of mappings that is part of a larger map. Submaps are often used to group mappings together for the purpose ofsharing them among multiple Mach tasks, but they may be used for many purposes. What makes a submap particularly powerful is that when several tasks have mapped a submap into their address space, they can see each other’s changes, not only to the contents of the objects in the map, but to the objects themselves. This means that as additional objects are added to or deleted from the submap, they appear in or disappear from the address spaces of all tasks that share that submap. The field behavior controls the paging reference behavior of a specified range in a given map. This value changes how pageins are clustered. Possible values are VM_BEHAVIOR_DEFAULT, VM_BEHAVIOR_RANDOM, VM_BEHAVIOR_SEQUENTIAL, and VM_BEHAVIOR_RSEQNTL, for default,random,sequential, orreverse-sequential pagein ordering. The protection and max_protection fields control the permissions on the object. The protection field indicates what rights the task currently has for the object, while the max_protection field contains the maximum access that the current task can obtain for the object. You might use the protection field when debugging shared memory. By setting the protection to be read-only, any inadvertent writes to the shared memory would cause an exception. However, when the task actually needsto write to thatshared region, it could increase its permissionsin the protection field to allow writes. Memory and Virtual Memory Memory Maps Explained 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 63It would be a security hole if a task could increase its own permissions on a memory object arbitrarily, however. In order to preserve a reasonable security model, the task that owns a memory object must be able to limit the rights granted to a subordinate task. For this reason, a task is not allowed to increase its protection beyond the permissions granted in max_protection. Possible valuesfor protection and max_protection are described in detail in xnu/osfmk/mach/vm_prot.h. Finally, the use_pmap field indicates whether a submap’s low-level mappings should be shared among all tasksinto which the submap is mapped. If the mappings are notshared, then the structure of the map isshared among all tasks, but the actual contents of the pages are not. For example,shared libraries are handled with two submaps. The read-only shared code section has use_pmap set to true. The read-write (nonshared) section has use_pmap set to false, forcing a clean copy of the library’s DATA segment to be mapped in from disk for each new task. Named Entries The OS X VM system provides an abstraction known as a named entry. A named entry is nothing more than a handle to a shared object or a submap. Shared memory support in OS X is achieved by sharing objects between the memory maps of various tasks. Shared memory objects must be created from existing VM objects by calling vm_allocate to allocate memory in your address space and then calling mach_make_memory_entry_64 to get a handle to the underlying VM object. The handle returned by mach_make_memory_entry_64 can be passed to vm_map to map that object into a given task’s address space. The handle can also be passed via IPC or other means to other tasks so that they can map it into their address spaces. This provides the ability to share objects with tasks that are not in your direct lineage, and also allows you to share additional memory with tasks in your direct lineage after those tasks are created. The other form of named entry, the submap, is used to group a set of mappings. The most common use of a submap is to share mappings among multiple Mach tasks. A submap can be created with vm_region_object_create. What makes a submap particularly powerful is that when several tasks have mapped a submap into their address space, they can see each other’s changes to both the data and the structure of the map. This means that one task can map or unmap a VM object in another task’s addressspace simply by mapping or unmapping that object in the submap. Memory and Virtual Memory Named Entries 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 64Universal Page Lists (UPLs) A universal page list, or UPL, is a data structure used when communicating with the virtual memory system. UPLs can be used to change the behavior of pages with respect to caching, permissions, mapping, and so on. UPLs can also be used to push data into and pull data from VM objects. The term is also often used to refer to the family of routines that operate on UPLs. The flags used when dealing with UPLs are described in osfmk/mach/memory_object_types.h. The life cycle of a UPL looks like this: 1. A UPL is created based on the contents of a VM object. This UPL includes information about the pages within that object. 2. That UPL is modified in some way. 3. The changes to the UPL are either committed (pushed back to the VM system) or aborted, with ubc_upl_commit or ubc_upl_abort, respectively. If you have a control handle for a given VM object (which generally means that you are inside a pager), you can use vm_object_upl_request to get a UPL for that object. Otherwise, you must use the vm_map_get_upl call. In either case, you are left with a handle to the UPL. When a pagein is requested, the pager receives a list of pages that are locked against the object, with certain pages set to not valid. The pager must either write data into those pages or must abort the transaction to prevent invalid data in the kernel. Similarly in pageout, the kernel must write the data to a backing store or abort the transaction to prevent data loss. The pager may also elect to bring additional pages into memory or throw additional pages out of memory at its discretion. Because pagers can be used both for virtual memory and for memory mapping of file data, when a pageout is requested, the data may need to be freed from memory, or it may be desirable to keep it there and simply flush the changes to disk. For this reason, the flag UPL_CLEAN_IN_PLACE exists to allow a page to be flushed to disk but not removed from memory. When a pager decides to page in or out additional pages, it must determine which pages to move. A pager can request all of the dirty pages by setting the RETURN_ONLY_DIRTY flag. It can also request all pages that are not in memory using the RETURN_ONLY_ABSENT flag. There is a slight problem, however. If a given page is marked as BUSY in the UPL, a request for information on that page would normally block. If the pager is doing prefetching or preflushing, this is not desirable, since it might be blocking on itself or on some other pager that is blocked waiting for the current transaction to complete. To avoid such deadlock, the UPL mechanism provides the UPL_NOBLOCK flag. This is frequently used in the anonymous pager for requesting free memory. Memory and Virtual Memory Universal Page Lists (UPLs) 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 65The flag QUERY_OBJECT_TYPE can be used to determine if an object is physically contiguous and to get other properties of the underlying object. The flag UPL_PRECIOUS means that there should be only one copy of the data. This prevents having a copy both in memory and in the backing store. However, this breaks the adjacency of adjacent pages in the backing store, and is thus generally not used to avoid a performance hit. The flag SET_INTERNAL is used by the BSD subsystem to cause all information about a UPL to be contained in a single memory object so that it can be passed around more easily. It can only be used if your code is running in the kernel’s address space. Since this handle can be used for multiple small transactions (for example, when mapping a file into memory block-by-block), the UPL API includes functions for committing and aborting changes to only a portion of the UPL. These functions are upl_commit_range and upl_abort_range, respectively. To aid in the use of UPLsfor handling multi-part transactions, the upl_commit_range and upl_abort_range calls have a flag that causes the UPL to be freed when there are no unmodified pages in the UPL. If you use this flag, you must be very careful not to use the UPL after all ranges have been committed or aborted. Finally, the function vm_map_get_upl is frequently used in file systems. It gets the underlying VM object associated with a given range within an address space. Since this returns only the first object in that range, it is your responsibility to determine whether the entire range is covered by the resulting UPL and, if not, to make additional calls to get UPLs for other objects. Note that while the vm_map_get_upl call is against an address space range, most UPL calls are against a vm_object. Using Mach Memory Maps Warning: Thissection describesthe low-level API for dealing with Mach VM maps. These maps cannot be modified in this way from a kernel extension. These functions are not available for use in a KEXT. They are presented strictly for use within the VM system and other parts of Mach. If you are not doing in-kernel development, you should be using the methods described in the chapter “Boundary Crossings” (page 109). From the context of the kernel (not from a KEXT), there are two maps that you will probably need to deal with. The first is the kernel map. Since your code is executing in the kernel’s address space, no additional effort is needed to use memory referenced in the kernel map. However, you may need to add additional mappings into the kernel map and remove them when they are no longer needed. Memory and Virtual Memory Using Mach Memory Maps 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 66The second map of interest is the memory map for a given task. This is of most interest for code that accepts input from user programs, for example a sysctl or a Mach RPC handler. In nearly all cases, convenient wrappers provide the needed functionality, however. Most of these functions are based around the vm_offset_t type, which is a pointer-sized integer. In effect, you can think of them as pointers, with the caveat that they are not necessarily pointers to data in the kernel’s address space, depending on usage. The low-level VM map API includes the following functions: kern_return_t vm_map_copyin(vm_map_t src_map, vm_offset_t src_addr, vm_size_t len, boolean_t src_destroy, vm_map_copy_t *copy_result); kern_return_t vm_map_copyout(vm_map_t map, vm_offset_t *addr, /* Out */ register vm_map_copy_t copy); kern_return_t vm_map_copy_overwrite(vm_map_t dst_map, vm_offset_t dst_address,vm_map_copy_t copy, boolean_t interruptible, pmap_t pmap); void vm_map_copy_discard(vm_map_copy_t copy); void vm_map_wire(vm_map_t map, vm_offset_t start, vm_offset_t end, vm_prot_t access_type, boolean_t user_wire); void vm_map_unwire(vm_map_t map, vm_offset_t start, vm_offset_t end, boolean_t user_wire); The function vm_map_copyin copies data from an arbitrary (potentially non–kernel) memory map into a copy list and returns the copy list pointer in copy_result. If something goes wrong and you need to throw away this intermediate object, it should be freed with vm_map_copy_discard. In order to actually get the data from the copy list, you need to overwrite a memory object in the kernel’s address space with vm_map_copy_overwrite. This overwrites an object with the contents of a copy list. For most purposes, the value passed for interruptible should be FALSE, and pmap should be NULL. Memory and Virtual Memory Using Mach Memory Maps 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 67Copying data from the kernel to user space is exactly the same as copying data from user space, except that you pass kernel_map to vm_map_copyin and pass the user map to vm_map_copy_overwrite. In general, however, you should avoid doing this, since you could end up with a task’s memory being fragmented into lots of tiny objects, which is undesirable. Do not use vm_map_copyout when copying data into an existing user task’s address map. The function vm_map_copyout is used for filling an unused region in an address map. If the region is allocated, then vm_map_copyout does nothing. Because it requires knowledge of the current state of the map, it is primarily used when creating a new address map (for example, if you are manually creating a new process). For most purposes, you do not need to use vm_map_copyout. The functions vm_map_wire and vm_map_unwire can be used to wire and unwire portions of an address map. If you set the argument user_wire to TRUE, then the page can be unwired from user space. This should be set to FALSE if you are about to use the memory for I/O or for some other operation that cannot tolerate paging. In vm_map_wire, the argument access_type indicates the types of accesses that should not be allowed to generate a page fault. In general, however, you should be using vm_wire to wire memory. As mentioned earlier, this information is presented strictly for use in the heart of the kernel. You cannot use anything in this section from a kernel extension. Other VM and VM-Related Subsystems There are two additional VM subsystems: pagers and the working set detection subsystem. In addition, the VM shared memory server subsystem is closely tied to (but is not part of) the VM subsystem. This section describes these three VM and VM-related subsystems. Pagers OS X has three basic pagers: the vnode pager, the default pager (or anonymous pager), and the device pager. These are used by the VM system to actually get data into the VM objects that underlie named entries. Pagers are linked into the VM system through a combination of a subset of the old Mach pager interface and UPLs. The default pager is what most people think of when they think of a VM system. It is responsible for moving normal data into and out of the backing store. In addition, there is a facility known as the dynamic pager that sits on top of the default pager and handles the creation and deletion of backing store files. These pager files are filled with data in clusters (groups of pages). When the total fullness of the paging file pool reaches a high–water mark, the default pager asks the dynamic pager to allocate a new store file. When the pool drops below its low water mark, the VM system selects a pager file, moves its contents into other pager files, and deletes it from disk. Memory and Virtual Memory Other VM and VM-Related Subsystems 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 68The vnode pager has a 1:1 (onto) mapping between objects in VM space and open files (vnodes). It is used for memory mapped file I/O. The vnode pager is generally hidden behind calls to BSD file APIs. The device pager allows you to map non–general-purpose memory with the cache characteristics required for that memory (WIMG). Non–general–purpose memory includes physical addresses that are mapped onto hardware other than main memory—for example, PCI memory, frame buffer memory, and so on. The device pager is generally hidden behind calls to various I/O Kit functions. Working Set Detection Subsystem To improve performance, OS X has a subsystem known asthe working set detection subsystem. Thissubsystem is called on a VM fault; it keeps a profile of the fault behavior of each task from the time of its inception. In addition, just before a page request, the fault code asksthissubsystem which adjacent pagesshould be brought in, and then makes a single large request to the pager. Since files on disk tend to have fairly good locality, and since address space locality is largely preserved in the backing store, this provides a substantial performance boost. Also, since it is based upon the application’s previous behavior, it tends to pull in pages that would probably have otherwise been needed later. This occurs for all pagers. The working set code works well once it is established. However, without help, its performance would be the baseline performance until a profile for a given application has been developed. To overcome this, the first time that an application is launched in a given user context, the initial working set required to start the application is captured and stored in a file. From then on, when the application is started, that file is used to seed the working set. These working set files are established on a per-user basis. They are stored in /var/vm/app_profile and are only accessible by the super-user (and the kernel). VM Shared Memory Server Subsystem The VM shared memory server subsystem is a BSD service that is closely tied to VM, but is not part of VM. This server provides two submaps that are used for shared library support in OS X. Because shared libraries contain both read-only portions (text segment) and read-write portions (data segment), the two portions are treated separately to maximize efficiency. The read-only portions are completely shared between tasks, including the underlying pmap entries. The read-write portions share a common submap, but have different underlying data objects (achieved through copy-on-write). The three functions exported by the VM shared memory server subsystem should only be called by dyld. Do not use them in your programs. Memory and Virtual Memory Other VM and VM-Related Subsystems 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 69The function load_shared_file is used to load a new shared library into the system. Once such a file is loaded, other tasks can then depend on it, so a shared library cannot be unshared. However, a new set of shared regions can be created with new_system_shared_regions so that no new tasks will use old libraries. The function reset_shared_file can be used to reset any changes that your task may have made to its private copy of the data section for a file. Finally, the function new_system_shared_regions can be used to create a new set of shared regions for future tasks. New regions can be used when updating prebinding with new shared libraries to cause new tasks to see the latest libraries at their new locations in memory. (Users of old shared libraries will still work, but they will fall off the pre-bound path and will perform less efficiently.) It can also be used when dealing with private libraries that you want to share only with your task’s descendents. Address Spaces This section explains issues that some developers may see when using their drivers in Panther or later. These changes were necessitated by a combination of hardware and underlying OS changes; however, you may see problems resulting from the changes even on existing hardware. There are three basic areas of change in OS X v10.3. These are: ● IOMemoryDescriptor changes ● VM system (pmap) changes ● Kernel dependency changes These are described in detail in the sections that follow. Background Info on PCI Address Translation To allow existing device drivers to work with upcoming 64-bit system architectures, a number of changes were required. To explain these, a brief introduction to PCI bus bridges is needed. When a PCI device needs to perform a data transaction to or from main memory, the device driver calls a series of functions intended to prepare this memory for I/O. In an architecture where both the device drivers and the memory subsystem use 32-bit addressing, everything just works, so long as the memory doesn't get paged out during the I/O operation. As kernel memory is generally not pageable, the preparation islargely superfluous. On a system whose memory subsystem uses 64-bit addressing, however, this becomes a bit of a problem. Because the hardware devices on the PCI bus can only handle 32-bit addresses, the device can only “see” a 4 gigabyte aperture into the (potentially much larger) main memory at any given time. Memory and Virtual Memory Address Spaces 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 70There are two possible solutionsfor this problem. The easy (butslow)solution would be to use “bounce buffers”. In such a design, device drivers would copy data into memory specifically allocated within the bottom 4 gigs of memory. However, this incurs a performance penalty and also puts additional constraints on the lower 4 gigs of memory, causing numerous problems for the VM system. The other solution, the one chosen in Apple's 64-bit implementation, is to use address translation to “map” blocks of memory into the 32-bit address space of the PCI devices. While the PCI device can still only see a 4 gig aperture, that aperture can then be non-contiguous, and thus bounce buffers and other restrictions are unnecessary. This address translation is done using a part of the memory controller known as DART, which stands for Device Address Resolution Table. This introduces a number of potential problems, however. First, physical addresses as seen by the processor no longer map 1:1 onto the addresses as seen by PCI devices. Thus, a new term, I/O addresses, is introduced to describe this new view. Because I/O addresses and physical addresses are no longer the same, the DART must keep a table of translations to use when mapping between them. Fortunately, if your driver is written according to Apple guidelines (using only documented APIs), this process is handled transparently. Note: This additional addressing mode has an impact when debugging I/O Kit device drivers. For more information, see “When Things Go Wrong: Debugging the Kernel” (page 161). IOMemoryDescriptor Changes When your driver calls IOMemoryDescriptor::prepare, a mapping is automatically injected into the DART. When it calls IOMemoryDescriptor::release , the mapping is removed. If you fail to do this, your driver could experience random data corruption or panics. Because the DART requires different caching for reads and writes, the DMA direction is important on hardware that includes a DART. While you may receive random failuresif the direction is wrong in general (on any system), if you attempt to call WriteBytes on a memory region whose DMA direction is set up for reading, you will cause a kernel panic on 64-bit hardware. If you attempt to perform a DMA transaction to unwired (user) memory, on previous systems, you would only get random crashes, panics, and data corruption. On machines with a DART, you will likely get no data whatsoever. As a side-effect of changes in the memory subsystem, OS X is much more likely to return physically contiguous page ranges in memory regions. Historically, OS X returned multi-page memory regions in reverse order, starting with the last page and moving towards the first page. The result of this was that multi-page memory regions essentially never had a contiguous range of physical pages. Memory and Virtual Memory Address Spaces 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 71Because of the increased probability of seeing physically contiguous blocks of memory in a memory region, this change may expose latent bugs in some drivers that only show up when handling contiguous ranges of physical pages, which could result in incorrect behavior or panics. Note that the problems mentioned above are caused by bugs in the drivers, and could result in problems on older hardware prior to Panther. These issues are more likely to occur in Panther and later versions of OS X, however, because of the new hardware designs and the OS changes that were made to support those designs. VM System and pmap Changes: In Panther, as a result of the changes described in detail in the section on PCI address translation, physical addresses obtained directly from the pmap layer have no useful purpose outside the VM system itself. To prevent their inadvertent use in device drivers, the pmap calls are no longer available from kernel extensions. A few drivers written prior to the addition of the IOMemoryDescriptor class still use pmap calls to get the physical pages associated with a virtual address. Also, a few developers have looked at the IOMemoryDescriptor implementation and chosen to obtain addresses directly from the pmap layer to remove what was perceived as an unnecessary abstraction layer. Even without removing access to the pmap calls, these drivers would not function on systems with a DART (see the PCI section above for info on DARTs). To better emphasize this upcoming failure, Panther will cause these drivers to fail to load with an undefined symbol error (generally for pmap_extract ) even on systems without a DART. Kernel Dependency Changes Beginning in Panther, device drivers that declare a dependency on version 7 (the Panther version) of the I/O Kit will no longer automatically get symbols from Mach and BSD. This change was made to discourage I/O Kit developers from relying on symbols that are not explicitly approved for use in the I/O Kit. Existing drivers are unaffected by this change. This change only affects you if you explicitly modify your device driver to declare a dependency on version 7 of the I/O Kit to take advantage of new I/O Kit features. Summary As described above, some device drivers may require minor modifications to support Panther and higher. Apple has made every effort to ensure compatibility with existing device driversto the greatest extent possible, but a few drivers may break. If your driver breaks, you should first check to see if your driver includes any of the bugs described in the previous sections. If it does not, contact Apple Developer Technical Support for additional debugging suggestions. Memory and Virtual Memory Address Spaces 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 72Allocating Memory in the Kernel As with most things in the OS X kernel, there are a number of ways to allocate memory. The choice of routines depends both on the location of the calling routine and on the reason for allocating memory. In general, you should use Mach routines for allocating memory unless you are writing code for use in the I/O Kit, in which case you should use I/O Kit routines. Allocating Memory From a Non-I/O-Kit Kernel Extension The header defines the following routines for kernel memory allocation: ● OSMalloc—allocates a block of memory. ● OSMalloc_noblock—allocates a block of memory, but immediately returns NULL if the request would block. ● OSMalloc_nowait—same as OSMalloc_noblock. ● OSFree—releases memory allocated with any of the OSMalloc variants. ● OSMalloc_Tagalloc—allows you to create a unique tag for your memory allocations. You must create at least one tag before you can use any of the OSMalloc functions. ● OSMalloc_Tagfree—releases a tag allocated with OSMalloc_Tagalloc. (You must release all allocations associated with that tag before you call this function.) For example, to allocate and free a page of wired memory, you might write code like this: #include #define MYTAGNAME "com.apple.mytag" ... OSMallocTag mytag = OSMalloc_Tagalloc(MYTAGNAME, OSMT_DEFAULT); void *datablock = OSMalloc(PAGE_SIZE_64, mytag); ... OSFree(datablock, PAGE_SIZE_64, mytag); To allocate a page of pageable memory, pass OSMT_PAGEABLE instead of OSMT_DEFAULT in your call to OSMalloc_Tagalloc. Memory and Virtual Memory Allocating Memory in the Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 73Allocating Memory From the I/O Kit Although the I/O Kit is generally beyond the scope of this document, the I/O Kit memory management routines are presented here for completeness. In general, I/O Kit routinesshould not be used outside the I/O Kit. Similarly, Mach allocation routines should not be directly used from the I/O Kit because the I/O Kit has abstractions for those routines that fit the I/O Kit development model more closely. The I/O Kit includes the following routines for kernel memory allocation: void *IOMalloc(vm_size_t size); void *IOMallocAligned(vm_size_t size, vm_size_t alignment); void *IOMallocContiguous(vm_size_t size, vm_size_t alignment, IOPhysicalAddress *physicalAddress); void *IOMallocPageable(vm_size_t size, vm_size_t alignment); void IOFree(void *address, vm_size_t size); void IOFreeAligned(void *address, vm_size_t size); void IOFreeContiguous(void *address, vm_size_t size); void IOFreePageable(void *address, vm_size_t size); Most of these routines are relatively transparent wrappers around the Mach allocation functions. There are two major differences, however. First, the caller does not need to know which memory map is being modified. Second, they have a separate free call for each allocation call for internal bookkeeping reasons. The functions IOMallocContiguous and IOMallocAligned differsomewhat fromtheir Mach underpinnings. IOMallocAligned uses calls directly to Mach VM to add support for arbitrary (power of 2) data alignment, rather than aligning based on the size of the object. IOMallocContiguous adds an additional parameter, PhysicalAddress. If this pointer is not NULL, the physical address is returned through this pointer. Using Mach functions, obtaining the physical address requires a separate function call. Memory and Virtual Memory Allocating Memory in the Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 74Important: If your KEXT allocates memory that will be shared, you should create a buffer of type IOMemoryDescriptor or IOBufferMemoryDescriptor and specify that the buffer should be sharable. If you are allocating memory in a user application that will be shared with the kernel, you should use valloc or vm_allocate instead of malloc and then call mach_make_memory_entry_64. Allocating Memory In the Kernel Itself In addition to the routines available to kernel extensions, there are a number of other functions you can call to allocate memory when you are modifying the Mach kernel itself. Mach routines provide a relatively straightforward interface for allocating and releasing memory. They are the preferred mechanism for allocating memory outside of the I/O Kit. BSD also offers _MALLOC and _FREE, which may be used in BSD parts of the kernel. These routines do not provide for forced mapping of a given physical address to a virtual address. However, if you need such a mapping, you are probably writing a device driver, in which case you should be using I/O Kit routines instead of Mach routines. Most of these functions are based around the vm_offset_t type, which is a pointer-sized integer. In effect, you can think of them as pointers, with the caveat that they are not necessarily pointers to data in the kernel’s address space, depending on usage. These are some of the commonly used Mach routines for allocating memory: kern_return_t kmem_alloc(vm_map_t map, vm_offset_t *addrp, vm_size_t size); void kmem_free(vm_map_t map, vm_offset_t addr, vm_size_t size); kern_return_t mem_alloc_aligned(vm_map_t map, vm_offset_t *addrp, vm_size_t size); kern_return_t kmem_alloc_wired(vm_map_t map, vm_offset_t *addrp, vm_size_t size); kern_return_t kmem_alloc_pageable(vm_map_t map, vm_offset_t *addrp, vm_size_t size); kern_return_t kmem_alloc_contig(vm_map_t map, vm_offset_t *addrp, vm_size_t size, vm_offset_t mask, int flags); These functions all take a map as the first argument. Unless you need to allocate memory in a different map, you should pass kernel_map for this argument. Memory and Virtual Memory Allocating Memory in the Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 75All of the kmem_alloc functions except kmem_alloc_pageable allocate wired memory. The function kmem_alloc_pageable creates the appropriate VM structures but does not back the region with physical memory. This function could be combined with vm_map_copyout when creating a new address map, for example. In practice, it is rarely used. The function kmem_alloc_aligned allocates memory aligned according to the value of the size argument, which must be a power of 2. The function kmem_alloc_wired is synonymous with kmem_alloc and is appropriate for data structures that cannot be paged out. It is not strictly necessary; however, if you explicitly need certain pieces of data to be wired, using kmem_alloc_wired makes it easier to find those portions of your code. The function kmem_alloc_contig attempts to allocate a block of physically contiguous memory. This is not always possible, and requires a full sort of the system free list even for short allocations. After startup, this sort can cause long delays, particularly on systems with lots of RAM. You should generally not use this function. The function kmem_free is used to free an object allocated with one of the kmem_alloc functions. Unlike the standard C free function, kmem_free requires the length of the object. If you are not allocating fixed-size objects (for example, sizeof struct foo), you may have to do some additional bookkeeping, since you must free an entire object, not just a portion of one. Memory and Virtual Memory Allocating Memory in the Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 76OS X is based on Mach and BSD. Like Mach and most BSD UNIX systems, it contains an advanced scheduler based on the CMU Mach 3 scheduler. This chapter describes the scheduler from the perspective of both a kernel programmer and an application developer attempting to set scheduling parameters. This chapter begins with the “Overview of Scheduling” (page 77), which describes the basic concepts behind Mach scheduling at a high level, including real-time priority support. The second section, “Using Mach Scheduling From User Applications” (page 79), describes how to access certain key Mach scheduler routines from user applications and from other parts of the kernel outside the scheduler. The third section, “Kernel Thread APIs” (page 85), explains scheduler-related topics including how to create and terminate kernel threads and describes the BSD spl macros and their limited usefulness in OS X. Overview of Scheduling The OS X scheduler is derived from the scheduler used in OSFMK 7.3. In general, much documentation about prior implementations applies to the scheduler in OS X, although you will find numerous differences. The details of those differences are beyond the scope of this overview. Mach scheduling is based on a system of run queues at various priorities that are handled in different ways. The priority levels are divided into four bands according to their characteristics, as described in Table 10-1 (page 77). Table 10-1 Thread priority bands Priority Band Characteristics Normal normal application thread priorities System high priority threads whose priority has been raised above normal threads reserved for threads created inside the kernel that need to run at a higher priority than all user space threads (I/O Kit workloops, for example) Kernel mode only threads whose priority is based on getting a well-defined fraction of total clock cycles, regardless of other activity (in an audio player application, for example). Real-time threads 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 77 Mach Scheduling and Thread InterfacesThreads can migrate between priority levels for a number of reasons, largely as an artifact of the time sharing algorithm used. However, this migration is within a given band. Threads marked as being real-time priority are also special in the eyes of the scheduler. A real-time thread tells the scheduler that it needs to run for A cycles out of the next B cycles. For example, it might need to run for 3000 out of the next 7000 clock cyclesin order to keep up. It also tellsthe scheduler whether those cycles must be contiguous. Using long contiguous quanta is generally frowned upon but is occasionally necessary for specialized real-time applications. The kernel will make every effort to honor the request, but since this is soft real-time, it cannot be guaranteed. In particular, if the real-time thread requests something relatively reasonable, its priority will remain in the real-time band, but if it lies blatantly about its requirements and behaves in a compute-bound fashion, it may be demoted to the priority of a normal thread. Changing a thread’s priority to turn it into a real-time priority thread using Mach calls is described in more detail in “Using Mach Scheduling From User Applications” (page 79). In addition to the raw Mach RPC interfaces, some aspects of a thread’s priority can be controlled from user space using the POSIX thread priority API. The POSIX thread API is able to set thread priority only within the lowest priority band (0–63). For more information on the POSIX thread priority API, see “Using the pthreads API to Influence Scheduling” (page 79). Why Did My Thread Priority Change? There are many reasons that a thread’s priority can change. This section attempts to explain the root cause of these thread priority changes. A real-time thread, as mentioned previously, is penalized (and may even be knocked down to normal thread priority) if it exceeds its time quantum without blocking repeatedly. For this reason, it is very important to make a reasonable guess about your thread’s workload if it needs to run in the real-time band. Threadsthat are heavily compute-bound are given lower priority to help minimize response time for interactive tasksso that high–priority compute–bound threads cannot monopolize the system and prevent lower–priority I/O-bound threads from running. Even at a lower priority, the compute–bound threads still run frequently, since the higher–priority I/O-bound threads do only a short amount of processing, block on I/O again, then allow the compute-bound threads to execute. All of these mechanisms are operating continually in the Mach scheduler. This meansthat threads are frequently moving up or down in priority based upon their behavior and the behavior of other threads in the system. Mach Scheduling and Thread Interfaces Why Did My Thread Priority Change? 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 78Using Mach Scheduling From User Applications There are three basic ways to change how a user thread is scheduled. You can use the BSD pthreads API to change basic policy and importance. You can also use Mach RPC calls to change a task’s importance. Finally, you can use RPC calls to change the scheduling policy to move a thread into a different scheduling band. This is commonly used when interacting with CoreAudio. The pthreads API is a user space API, and has limited relevance for kernel programmers. The Mach thread and task APIs are more general and can be used from anywhere in the kernel. The Mach thread and task calls can also be called from user applications. Using the pthreads API to Influence Scheduling OS X supports a number of policies at the POSIX threads API level. If you need real-time behavior, you must use the Mach thread_policy_set call. This is described in “Using the Mach Thread API to Influence Scheduling” (page 80). The pthreads API adjuststhe priority of threads within a given task. It does not necessarily impact performance relative to threads in other tasks. To increase the priority of a task, you can use nice or renice from the command line or call getpriority and setpriority from your application. The API providestwo functions: pthread_getschedparam and pthread_setschedparam. Their prototypes look like this: pthread_setschedparam(pthread_t thread, int policy, struct sched_param *param); pthread_getschedparam(pthread_t thread, int *policy, struct sched_param *param) The arguments for pthread_getschedparam are straightforward. The first argument is a thread ID, and the others are pointers to memory where the results will be stored. The argumentsto pthread_setschedparam are not as obvious, however. As with pthread_getschedparam, the first argument is a thread ID. The second argument to pthread_setschedparam is the desired policy, which can currently be one of SCHED_FIFO (first in, first out), SCHED_RR (round-robin), or SCHED_OTHER. The SCHED_OTHER policy is generally used for extra policies that are specific to a given operating system, and should thus be avoided when writing portable code. The third argument is a structure that contains various scheduling parameters. Mach Scheduling and Thread Interfaces Using Mach Scheduling From User Applications 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 79Here is a basic example of using pthreads functions to set a thread’s scheduling policy and priority. int set_my_thread_priority(int priority) { struct sched_param sp; memset(&sp, 0, sizeof(struct sched_param)); sp.sched_priority=priority; if (pthread_setschedparam(pthread_self(), SCHED_RR, &sp) == -1) { printf("Failed to change priority.\n"); return -1; } return 0; } This code snippet sets the scheduling policy for the current thread to round-robin scheduling, and sets the thread’s relative importance within the task to the value passed in through the priority argument. For more information, see the manual page for pthread. Using the Mach Thread API to Influence Scheduling This API is frequently used in multimedia applications to obtain real-time priority. It is also useful in other situations when the pthread scheduling API cannot be used or does not provide the needed functionality. The API consists of two functions, thread_policy_set and thread_policy_get. kern_return_t thread_policy_set( thread_act_t thread, thread_policy_flavor_t flavor, thread_policy_t policy_info, mach_msg_type_number_t count); kern_return_t thread_policy_get( thread_act_t thread, thread_policy_flavor_t flavor, thread_policy_t policy_info, mach_msg_type_number_t *count, Mach Scheduling and Thread Interfaces Using Mach Scheduling From User Applications 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 80boolean_t *get_default); The parameters of these functions are roughly the same, except that the thread_policy_get function takes pointers for the count and the get_default arguments. The count is an inout parameter, meaning that it is interpreted as the maximum amount of storage (in units of int32_t) that the calling task has allocated for the return, but it is also overwritten by the scheduler to indicate the amount of data that was actually returned. These functions get and set several parameters, according to the thread policy chosen. The possible thread policies are listed in Table 10-2 (page 81). Table 10-2 Thread policies Policy Meaning THREAD_STANDARD_POLICY Default value THREAD_TIME_CONSTRAINT_POLICY Used to specify real-time behavior. Used to indicate the importance of computation relative to other threads in a given task. THREAD_PRECEDENCE_POLICY The following code snippet shows how to set the priority of a task to tell the scheduler that it needs real-time performance. The example values provided in comments are based on the estimated needs of esd (the Esound daemon). #include #include #include #include int set_realtime(int period, int computation, int constraint) { struct thread_time_constraint_policy ttcpolicy; int ret; thread_port_t threadport = pthread_mach_thread_np(pthread_self()); ttcpolicy.period=period; // HZ/160 ttcpolicy.computation=computation; // HZ/3300; ttcpolicy.constraint=constraint; // HZ/2200; ttcpolicy.preemptible=1; Mach Scheduling and Thread Interfaces Using Mach Scheduling From User Applications 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 81if ((ret=thread_policy_set(threadport, THREAD_TIME_CONSTRAINT_POLICY, (thread_policy_t)&ttcpolicy, THREAD_TIME_CONSTRAINT_POLICY_COUNT)) != KERN_SUCCESS) { fprintf(stderr, "set_realtime() failed.\n"); return 0; } return 1; } The time values are in terms of Mach absolute time units. Since these values differ on different CPUs, you should generally use numbers relative to HZ (a global variable in the kernel that contains the current number of ticks per second). You can either handle this conversion yourself by dividing this value by an appropriate quantity or use the conversion routines described in “Using Kernel Time Abstractions ” (page 142). Say your computer reports 133 million for the value of HZ. If you pass the example values given as arguments to this function, your thread tells the scheduler that it needs approximately 40,000 (HZ/3300) out of the next 833,333 (HZ/160) bus cycles. The preemptible value (1) indicates that those 40,000 bus cycles need not be contiguous. However, the constraint value (HZ/2200) tells the scheduler that there can be no more than 60,000 bus cycles between the start of computation and the end of computation. Note: Because the constraint sets a maximum bound for computation, it must be larger than the value for computation. A straightforward example using this API is code that displays video directly to the framebuffer hardware. It needs to run for a certain number of cycles every frame to get the new data into the frame buffer. It can be interrupted without worry, but if it isinterrupted for too long, the video hardware starts displaying an outdated frame before the software writes the updated data, resulting in a nasty glitch. Audio has similar behavior, but since it is usually buffered along the way (in hardware and in software), there is greater tolerance for variations in timing, to a point. Another policy call is THREAD_PRECEDENCE_POLICY. This is used for setting the relative importance of non-real-time threads. Its calling convention issimilar, except that itsstructure is thread_precedence_policy, and contains only one field, an integer_t called importance. While thisis a signed 32-bit value, the minimum legal value is zero (IDLE_PRI). threads set to IDLE_PRI will only execute when no other thread is scheduled to execute. Mach Scheduling and Thread Interfaces Using Mach Scheduling From User Applications 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 82In general, larger values indicate higher priority. The maximum limit is subject to change, as are the priority bands, some of which have special purposes (such as real-time threads). Thus, in general, you should use pthreads APIs to achieve this functionality rather than using this policy directly unless you are setting up an idle thread. Using the Mach Task API to Influence Scheduling This relatively simple API is not particularly useful for most developers. However, it may be beneficial if you are developing a graphical user interface for Darwin. It also provides some insight into the prioritization of tasks in OS X. It is presented here for completeness. The API consists of two functions, task_policy_set and task_policy_get. kern_return_t task_policy_set( task_t task, task_policy_flavor_t flavor, task_policy_t policy_info, mach_msg_type_number_t count); kern_return_t task_policy_get( task_t task, task_policy_flavor_t flavor, task_policy_t policy_info, mach_msg_type_number_t *count, boolean_t *get_default); As with thread_policy_set and thread_policy_get, the parameters are similar, except that the task_policy_get function takes pointers for the count and the get_default arguments. The count argument is an inout parameter. It is interpreted as the maximum amount of storage that the calling task has allocated for the return, but it is also overwritten by the scheduler to indicate the amount of data that was actually returned. These functions get and set a single parameter, that of the role of a given task, which changes the way the task’s priority gets altered over time. The possible roles of a task are listed in Table 10-3 (page 83). Table 10-3 Task roles Role Meaning TASK_UNSPECIFIED Default value Mach Scheduling and Thread Interfaces Using Mach Scheduling From User Applications 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 83Role Meaning This is set when a process is executed with nice or is modified by renice. TASK_RENICED GUI application in the foreground. There can be more than one foreground application. TASK_FOREGROUND_APPLICATION TASK_BACKGROUND_APPLICATION GUI application in the background. TASK_CONTROL_APPLICATION Reserved for the dock or equivalent (assigned FCFS). TASK_GRAPHICS_SERVER Reserved for WindowServer or equivalent (assigned FCFS). The following code snippet shows how to set the priority of a task to tell the scheduler that it is a foreground application (regardless of whether it really is). #include #include #include int set_my_task_policy(void) { int ret; struct task_category_policy tcatpolicy; tcatpolicy.role = TASK_FOREGROUND_APPLICATION; if ((ret=task_policy_set(mach_task_self(), TASK_CATEGORY_POLICY, (thread_policy_t)&tcatpolicy, TASK_CATEGORY_POLICY_COUNT)) != KERN_SUCCESS) { fprintf(stderr, "set_my_task_policy() failed.\n"); return 0; } return 1; } Mach Scheduling and Thread Interfaces Using Mach Scheduling From User Applications 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 84Kernel Thread APIs The OS X scheduler provides a number of public APIs. While many of these APIs should not be used, the APIs to create, destroy, and alter kernel threads are of particular importance. While not technically part of the scheduler itself, they are inextricably tied to it. The scheduler directly provides certain services that are commonly associated with the use of kernel threads, without which kernel threads would be of limited utility. For example, the scheduler provides support for wait queues, which are used in various synchronization primitives such as mutex locks and semaphores. Creating and Destroying Kernel Threads The recommended interface for creating threads within the kernel is through the I/O Kit. It provides IOCreateThread, IOThreadSelf, and IOExitThread functions that make it relatively painless to create threads in the kernel. The basic functions for creating and terminating kernel threads are: IOThread IOCreateThread(IOThreadFunc function, void *argument); IOThread IOThreadSelf(void); void IOExitThread(void); With the exception of IOCreateThread (which is a bit more complex), the I/O Kit functions are fairly thin wrappers around Mach thread functions. The types involved are also very thin abstractions. IOThread is really the same as thread_t. The IOCreateThread function creates a new thread that immediately begins executing the function that you specify. It passes a single argument to that function. If you need to pass more than one argument, you should dynamically allocate a data structure and pass a pointer to that structure. For example, the following code creates a kernel thread and executes the function myfunc in that thread: #include #include #include struct mydata { int three; char *string; }; Mach Scheduling and Thread Interfaces Kernel Thread APIs 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 85static void myfunc(void *myarg) { struct mydata *md = (struct mydata *)myarg; IOLog("Passed %d = %s\n", md->three, md->string); IOExitThread(); } void start_threads() { IOThread mythread; struct mydata *md = (struct mydata *)malloc(sizeof(*md)); md->three = 3; md->string = (char *)malloc(2 * sizeof(char)); md->string[0] = '3'; md->string[1] = '\0'; // Start a thread using IOCreateThread mythread = IOCreateThread(&myfunc, (void *)md); } One other useful function is thread_terminate. This can be used to destroy an arbitrary thread (except, of course, the currently running thread). This can be extremely dangerous if not done correctly. Before tearing down a thread with thread_terminate, you should lock the thread and disable any outstanding timers against it. If you fail to deactivate a timer, a kernel panic will occur when the timer expires. With that in mind, you may be able to terminate a thread as follows: thread_terminate(getact_thread(thread)); There thread is of type thread_t. In general, you can only be assured that you can kill yourself, not other threads in the system. The function thread_terminate takes a single parameter of type thread_act_t (a thread activation). The function getact_thread takes a thread shuttle (thread_shuttle_t) or thread_t and returns the thread activation associated with it. SPL and Friends BSD–based and Mach–based operating systems contain legacy functions designed for basic single-processor synchronization. These include functions such as splhigh, splbio, splx, and other similar functions. Since these functions are not particularly useful for synchronization in an SMP situation, they are not particularly useful as synchronization tools in OS X. Mach Scheduling and Thread Interfaces Kernel Thread APIs 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 86If you are porting legacy code from earlier Mach–based or BSD–based operating systems, you must find an alternate means of providing synchronization. In many cases, this is as simple as taking the kernel or network funnel. In parts of the kernel, the use of spl functions does nothing, but causes no harm if you are holding a funnel (and results in a panic if you are not). In other parts of the kernel, spl macros are actually used. Because spl cannot necessarily be used for itsintended purpose, itshould not be used in general unless you are writing code it a part of the kernel that already uses it. You should instead use alternate synchronization primitives such as those described in “Synchronization Primitives” (page 128). Wait Queues and Wait Primitives The wait queue API is used extensively by the scheduler and is closely tied to the scheduler in itsimplementation. It is also used extensively in locks, semaphores, and other synchronization primitives. The wait queue API is both powerful and flexible, and as a result issomewhat large. Not all of the API is exported outside the scheduler, and parts are not useful outside the context of the wait queue functions themselves. This section documents only the public API. The wait queue API includes the following functions: void wait_queue_init(wait_queue_t wq, int policy); extern wait_queue_t wait_queue_t wait_queue_alloc(int policy); void wait_queue_free(wait_queue_t wq); void wait_queue_lock(wait_queue_t wq); void wait_queue_lock_try(wait_queue_t wq); void wait_queue_unlock(wait_queue_t wq); boolean_t wait_queue_member(wait_queue_t wq, wait_queue_sub_t wq_sub); boolean_t wait_queue_member_locked(wait_queue_t wq, wait_queue_sub_t wq_sub); kern_return_t wait_queue_link(wait_queue_t wq, wait_queue_sub_t wq_sub); kern_return_t wait_queue_unlink(wait_queue_t wq, wait_queue_sub_t wq_sub); kern_return_t wait_queue_unlink_one(wait_queue_t wq, wait_queue_sub_t *wq_subp); void wait_queue_assert_wait(wait_queue_t wq, event_t event, int interruptible); void wait_queue_assert_wait_locked(wait_queue_t wq, event_t event, int interruptible, boolean_t unlocked); kern_return_t wait_queue_wakeup_all(wait_queue_t wq, event_t event, int result); kern_return_t wait_queue_peek_locked(wait_queue_t wq, event_t event, thread_t *tp, wait_queue_t *wqp); Mach Scheduling and Thread Interfaces Kernel Thread APIs 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 87void wait_queue_pull_thread_locked(wait_queue_t wq, thread_t thread, boolean_t unlock); thread_t wait_queue_wakeup_identity_locked(wait_queue_t wq, event_t event, int result, boolean_t unlock); kern_return_t wait_queue_wakeup_one(wait_queue_t wq, event_t event, int result); kern_return_t wait_queue_wakeup_one_locked(wait_queue_t wq, event_t event, int result, boolean_t unlock); kern_return_t wait_queue_wakeup_thread(wait_queue_t wq, event_t event, thread_t thread, int result); kern_return_t wait_queue_wakeup_thread_locked(wait_queue_t wq, event_t event, thread_t thread, int result, boolean_t unlock); kern_return_t wait_queue_remove(thread_t thread); Most of the functions and their arguments are straightforward and are not presented in detail. However, a few require special attention. Most of the functions take an event_t as an argument. These can be arbitrary 32-bit values, which leads to the potential for conflicting events on certain wait queues. The traditional way to avoid this problem is to use the address of a data object that is somehow related to the code in question as that 32-bit integer value. For example, if you are waiting for an event that indicates that a new block of data has been added to a ring buffer, and if that ring buffer’s head pointer was called rb_head, you might pass the value &rb_head as the event ID. Because wait queue usage does not generally cross address space boundaries, this is generally sufficient to avoid any event ID conflicts. Notice the functions ending in _locked. These functions require that your thread be holding a lock on the wait queue before they are called. Functions ending in _locked are equivalent to their nonlocked counterparts (where applicable) except that they do not lock the queue on entry and may not unlock the queue on exit (depending on the value of unlock). The remainder of this section does not differentiate between locked and unlocked functions. The wait_queue_alloc and wait_queue_init functions take a policy parameter, which can be one of the following: ● SYNC_POLICY_FIFO—first-in, first-out ● SYNC_POLICY_FIXED_PRIORITY—policy based on thread priority Mach Scheduling and Thread Interfaces Kernel Thread APIs 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 88● SYNC_POLICY_PREPOST—keep track of number of wakeups where no thread was waiting and allow threadsto immediately continue executing without waiting until that count reaches zero. Thisisfrequently used when implementing semaphores. You should not use the wait_queue_init function outside the scheduler. Because a wait queue is an opaque object outside that context, you cannot determine the appropriate size for allocation. Thus, because the size could change in the future, you should always use wait_queue_alloc and wait_queue_free unless you are writing code within the scheduler itself. Similarly, the functions wait_queue_member, wait_queue_member_locked, wait_queue_link, wait_queue_unlink, and wait_queue_unlink_one are operations on subordinate queues, which are not exported outside the scheduler. The function wait_queue_member determines whether a subordinate queue is a member of a queue. The functions wait_queue_link and wait_queue_unlink link and unlink a given subordinate queue from its parent queue, respectively. The function wait_queue_unlink_one unlinks the first subordinate queue in a given parent and returns it. The function wait_queue_assert_wait causes the calling thread to wait on the wait queue until it is either interrupted (by a thread timer, for example) or explicitly awakened by another thread. The interruptible flag indicates whether this function should allow an asynchronous event to interrupt waiting. The function wait_queue_wakeup_all wakes up all threads waiting on a given queue for a particular event. The function wait_queue_peek_locked returns the first thread from a given wait queue that is waiting on a given event. It does not remove the thread from the queue, nor does it wake the thread. It also returns the wait queue where the thread was found. If the thread is found in a subordinate queue, other subordinate queues are unlocked, as is the parent queue. Only the queue where the thread was found remains locked. The function wait_queue_pull_thread_locked pulls a thread from the wait queue and optionally unlocks the queue. This is generally used with the result of a previous call to wait_queue_peek_locked. The function wait_queue_wakeup_identity_locked wakes up the first thread that is waiting for a given event on a given wait queue and starts it running but leaves the thread locked. It then returns a pointer to the thread. This can be used to wake the first thread in a queue and then modify unrelated structures based on which thread was actually awakened before allowing the thread to execute. The function wait_queue_wakeup_one wakes up the first thread that is waiting for a given event on a given wait queue. The function wait_queue_wakeup_thread wakes up a given thread if and only if it is waiting on the specified event and wait queue (or one of its subordinates). Mach Scheduling and Thread Interfaces Kernel Thread APIs 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 89The function wait_queue_remove wakes a given thread without regard to the wait queue or event on which it is waiting. Mach Scheduling and Thread Interfaces Kernel Thread APIs 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 90In OS X kernel programming, the term context has several meanings that appear similar on the surface, but differ subtly. First, the term context can refer to a BSD process or Mach task. Switching from one process to another is often referred to as a context switch. Second, context can refer to the part of the operating system in which your code resides. Examples of this include thread contexts, the interrupt context, the kernel context, an application’s context, a Carbon File Manager context, and so on. Even for this use of the term, the exact meaning depends, ironically, on the context in which the term is used. Finally, context can refer to a bootstrap context. In Mach, the bootstrap task is assigned responsibility for looking up requests for Mach ports. As part of this effort, each Mach task is registered in one of two groups—either in the startup context or a user’s login context. (In theory, Mach can support any number of independent contexts, however the use of additional contexts is beyond the scope of this document.) For the purposes of this chapter, the term context refers to a bootstrap context. When OS X first boots, there is only the top-level context, which is generally referred to as the startup context. All other contexts are subsets of this context. Basic system services that rely on Mach ports must be started in this context in order to work properly. When a user logs in, the bootstrap task creates a new context called the login context. Programs run by the user are started in the login context. This allows the user to run a program that provides an alternate port lookup mechanism if desired, causing that user’s tasks to get a different port when the tasks look up a basic service. This has the effect of replacing that service with a user-defined version in a way that changes what the user’s tasks see, but does not affect any of the rest of the system. To avoid wasting memory, currently the login context is destroyed when the user logs out (orshortly thereafter). This behavior may change in the future, however. In the current implementation, programs started by the user will no longer be able to look up Mach ports after logout. If a program does not need to do any port lookup, it will not be affected. Other programs will terminate, hang, or behave erratically. For example, in Mac OS 10.1 and earlier, sshd continuesto function when started from a user context. However, since it is unable to communicate with lookupd or netinfo, it stops accepting passwords. This is not a particularly useful behavior. 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 91 Bootstrap ContextsOther programs such as esound, however, continue to work correctly after logout when started from a user context. Other programs behave correctly in their default configuration but fail in other configurations—for example, when authentication support is enabled. There are no hard and fast rules for which programs will continue to operate after their bootstrap context is destroyed. Only thorough testing can tell you whether any given program will misbehave if started from a user context, since even programs that do not appear to directly use Mach communication may still do so indirectly. In OS X v10.2, a great deal of effort has gone into making sure that programs that use only standard BSD services and functions do not use Mach lookups in a way that would fail if started from a user context. If you find an application that breaks when started from a Terminal.app window, please file a bug report. How Contexts Affect Users From the perspective of a user, contexts are generally unimportant as long as they do not want a program to survive past the end of their login session. Contexts do become a problem for the administrator, however. For example, if the administrator upgrades sshd by killing the old version, starting the new one, and logging out, strange things could happen since the context in which sshd was running no longer exists. Contexts also pose an issue for usersrunning background jobs with nohup or users detaching terminalsessions using screen. There are times when it is perfectly reasonable for a program to survive past logout, but by default, this does not occur. There are three basic ways that a user can get around this. In the case of daemons, they can modify the startup scripts to start the application. On restart, the application will be started in the startup context. This is not very practical if the computer in question isin heavy use, however. Fortunately, there are other waysto startservices in a startup context. The second way to run a service in the startup context is to use ssh to connect to the computer. Since sshd is running in the startup context, programs started from an ssh session also register themselves in the startup context. (Note that a user can safely kill the main sshd process without being logged out. The user just needs to be careful to kill the right one.) The third way isto log in asthe console user (>console), which causes LoginWindow to exit and causes init to spawn a getty process on the console. Since init spawns getty, which spawns login, which spawns the user’s shell, any programs started from the text console will be in the startup context. Bootstrap Contexts How Contexts Affect Users 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 92More generally, any process that is the child of a process in the startup context (other than those inherited by init because their parent process exited) is automatically in the startup context. Any process that is the child of a process in the login context is, itself, in the login context. This means that daemons can safely fork children at any time and those children will be in the startup context, as will programs started from the console (not the Console application). This also meansthat any program started by a user in a terminal window, from Finder, from the Dock, and so on, will be in the currently logged in user’s login context, even if that user runs the application using su or sudo. How Contexts Affect Developers If you are writing only kernel code, contexts are largely irrelevant (unless you are creating a new context, of course). However, kernel developers frequently need to write a program that registers itself in the startup context in order to provide some level of driver communication. For example, you could write a user-space daemon that brokers configuration information for a sound driver based on which user is logged in at the time. In the most general case, the problem ofstarting an application in the startup context can be solved by creating a startup script for your daemon, which causesit to be run in the startup context after the next reboot. However, users generally do not appreciate having to reboot their computers to install a new driver. Asking the user to connect to his or her own computer with ssh to execute a script is probably not reasonable, either. The biggest problem with forcing a reboot, of course, is that users often install several programs at once. Rebooting between each install inconveniences the end user, and has no other benefit. For that reason, you should not force the user to restart. Instead, you should offer the user the option, noting that the software may not work correctly until the user restarts. While this does not solve the fundamental problem, it does at least minimize the most common source of complaints. There are a number of ways to force a program to start in the startup context without rebooting or using ssh. However, these are not robust solutions, and are not recommended. A standard API for starting daemons is under consideration. When an official API becomes available, this chapter will be updated to discuss it. Bootstrap Contexts How Contexts Affect Developers 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 93Those of you who are already familiar with writing device drivers for Mac OS 9 or for BSD will discover that writing driversfor OS X requiressome new ways of thinking. In creating OS X, Apple has completely redesigned the Macintosh I/O architecture, providing a framework for simplified driver development that supports many categories of devices. This framework is called the I/O Kit. From a programming perspective, the I/O Kit provides an abstract view of the system hardware to the upper layers of OS X. The I/O Kit uses an object-oriented programming model, implemented in a restricted subset of C++ to promote increased code reuse. By starting with properly designed base classes, you gain a head start in writing a new driver; with much of the driver code already written, you need only to fill in the specific code that makes your driver different. For example, all SCSI controllers deliver a fairly standard set of commands to a device, but do so via different low-level mechanisms. By properly using object-oriented programming methodology, a SCSI driver can implement those low-level transport portions without reimplementing the higher level SCSI protocol code. Similar opportunities for code reuse can be found in most types of drivers. Part of the philosophy of the I/O Kit is to make the design completely open. Rather than hiding parts of the API in an attempt to protect developers from themselves, all of the I/O Kit source is available as part of Darwin. You can use the source code as an aid to designing (and debugging) new drivers. Instead of hiding the interfaces, Apple’s designers have chosen to lead by example. Sample code and classes show the recommended (easy) way to write a driver. However, you are not prevented from doing things the hard way (or the wrong way). Instead, attention has been concentrated on making the “best” ways easy to follow. Redesigning the I/O Model You might ask why Apple chose to redesign the I/O model. At first glance, it mightseem that reusing the model from Mac OS 9 or FreeBSD would have been an easier choice. There are several reasons for the decision, however. 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 94 I/O Kit OverviewNeither the Mac OS 9 driver model nor the FreeBSD model offered a feature set rich enough to meet the needs of OS X. The underlying operating-system technology of OS X is very different from that of Mac OS 9. The OS X kernel is significantly more advanced than the previous Mac OS system architecture; OS X needs to handle memory protection, preemption, multiprocessing, and other features not present (orsubstantially less pervasive) in previous versions of the Mac OS. Although FreeBSD supports these features, the BSD driver model did not offer the automatic configuration, stacking, power management, or dynamic device-loading features required in a modern, consumer-oriented operating system. By redesigning the I/O architecture, Apple’s engineers can take best advantage of the operating-system features in OS X. For example, virtual memory (VM) is not a fundamental part of the operating system in Mac OS 9. Thus, every driver writer must know about (and write for) VM. This has presented certain complications for developers. In contrast, OS X has simplified driver interaction with VM. VM capability is inherent in the OS X operating system and cannot be turned off by the user. Thus, VM capabilities can be abstracted into the I/O Kit, and the code for handling VM need not be written for every driver. OS X offers an unprecedented opportunity to reuse code. In Mac OS 9, for example, all software development kits (SDKs) were independent of each other, duplicating functionality between them. In OS X, the I/O Kit is delivered as part of the basic developer tools, and code is shared among its various parts. In contrast with traditional I/O models, the reusable code model provided by the I/O Kit can decrease your development work substantially. In porting drivers from Mac OS 9, for example, the OS X counterparts have been up to 75% smaller. In general, all hardware support is provided directly by I/O Kit entities. One exception to this rule is imaging devicessuch as printers,scanners, and digital cameras(although these do make some use of I/O Kit functionality). Specifically, although communication with these devices is handled by the I/O Kit (for instance, under the FireWire or USB families), support for particular device characteristics is handled by user-space code (see “For More Information” (page 100) for further discussion). If you need to support imaging devices, you should employ the appropriate imaging software development kit (SDK). The I/O Kit attempts to represent, in software, the same hierarchy that exists in hardware. Some things are difficult to abstract, however. When the hardware hierarchy is difficult to represent (for example, if layering violations occur), then the I/O Kit abstractions provide less help for writing drivers. In addition, all drivers exist to drive hardware; all hardware is different. Even with the reusable model provided by the I/O Kit, you still need to be aware of any hardware quirks that may impact a higher-level view of the device. The code to support those quirks still needs to be unique from driver to driver. I/O Kit Overview Redesigning the I/O Model 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 95Although most developers should be able to take full advantage of I/O Kit device families (see “Families” (page 96)), there will occasionally be some who cannot. Even those developers should be able to make use of parts of the I/O Kit, however. In any case, the source code is always available. You can replace functionality and modify the classes yourself if you need to do so. In designing the I/O Kit, one goal has been to make developers’ lives easier. Unfortunately, it is not possible to make all developers’ lives uniformly easy. Therefore, a second goal of the I/O Kit design is to meet the needs of the majority of developers, without getting in the way of the minority who need lower level access to the hardware. I/O Kit Architecture The I/O Kit provides a model of system hardware in an object-oriented framework. Each type of service or device is represented by a C++ class; each discrete service or device is represented by an instance (object) of that class. There are three major conceptual elements of the I/O Kit architecture: ● “Families” (page 96) ● “Drivers” (page 97) ● “Nubs” (page 97) Families A family defines a collection of high-level abstractions common to all devices of a particular category that takes the form of C code and C++ classes. Families may include headers, libraries, sample code, test harnesses, and documentation. They provide the API, generic support code, and at least one example driver (in the documentation). Families provide services for many different categories of devices. For example, there are protocol families (such as SCSI, USB, and FireWire), storage families (disk), network families, and families to describe human interface devices (mouse and keyboard). When devices have features in common, the software that supports those features is most likely found in a family. Common abstractions are defined and implemented by the family, allowing all drivers in a family to share similar features easily. For example, all SCSI controllers have certain things they must do, such as scanning the SCSI bus. The SCSI family defines and implementsthe functionality that is common to SCSI controllers. Because thisfunctionality has been included in the SCSI family, you do not need to include scanning code (for example) in your new SCSI controller driver. I/O Kit Overview I/O Kit Architecture 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 96Instead, you can concentrate on device-specific details that make your driver different from other SCSI drivers. The use of families means there is less code for you to write. Families are dynamically loadable; they are loaded when needed and unloaded when no longer needed. Although some common families may be preloaded at system startup, all families should be considered to be dynamically loadable (and, therefore, potentially unloaded). See the “Connection Example” (page 98) for an illustration. Drivers A driver is an I/O Kit object that manages a specific device or bus, presenting a more abstract view of that device to other parts of the system. When a driver is loaded, its required families are also loaded to provide necessary, common functionality. The request to load a driver causes all of its dependent requirements (and their requirements) to be loaded first. After all requirements are met, the requested driver is loaded as well. See “Connection Example” (page 98) for an illustration. Note that families are loaded upon demand of the driver, not the other way around. Occasionally, a family may already be loaded when a driver demands it; however, you should never assume this. To ensure that all requirements are met, each device driver should list all of its requirements in its property list. Most drivers are in a client-provider relationship, wherein the driver must know about both the family from which it inherits and the family to which it connects. A SCSI controller driver, for example, must be able to communicate with both the SCSI family and the PCI family (as a client of PCI and provider of SCSI). A SCSI disk driver communicates with both the SCSI and storage families. Nubs A nub is an I/O Kit object that represents a point of connection for a driver. It represents a controllable entity such as a disk or a bus. A nub is loaded as part of the family that instantiates it. Each nub provides access to the device or service that it represents and provides services such as matching, arbitration, and power management. The concept of nubs can be more easily visualized by imagining a TV set. There is a wire attached to your wall that provides TV service from somewhere. For all practical purposes, it is permanently associated with that provider, the instantiating class (the cable company who installed the line). It can be attached to the TV to provide a service (cable TV). That wire is a nub. Each nub provides a bridge between two drivers (and, by extension, between two families). It is most common that a driver publishes one nub for each individual device or service it controls. (In this example, imagine one wire for every home serviced by the cable company.) I/O Kit Overview I/O Kit Architecture 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 97It is also possible for a driver that controls only a single device or service to act as its own nub. (Imagine the antenna on the back of your TV that has a built-in wire.) See the “Connection Example” (page 98) for an illustration of the relationship between nubs and drivers. Connection Example Figure 12-1 (page 98) illustrates the I/O Kit architecture, using several example drivers and their corresponding nubs. Note that many different driver combinations are possible; this diagram shows only one possibility. In this case, a SCSI stack is shown, with a PCI controller, a disk, and a SCSI scanner. The SCSI disk is controlled by a kernel-resident driver. The SCSI scanner is controlled by a driver that is part of a user application. Figure 12-1 I/O Kit architecture IOPCIBridge family PCI bus driver IOSCSIParallelController family SCSI card driver IOBlockStorageDriver family SCSI disk driver IOPCIDevice nubs IOSCSIParallelDevice nubs IOMedia nub Disk User application User space Kernel space Device interface User client This example illustrates how a SCSI disk driver (Storage family) is connected to the PCI bus. The connection is made in several steps. I/O Kit Overview I/O Kit Architecture 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 981. The PCI bus driver discovers a PCI device and announces its presence by creating a nub (IOPCIDevice). The nub’s class is defined by the PCI family. IOPCIBridge family PCI bus driver IOPCIDevice nubs Video card Main logic board ATA SCSI card 2. The bus driver identifies (matches) the correct device driver and requests that the driver be loaded. At the end of this matching process, a SCSI controller driver has been found and loaded. Loading the controller driver causes all required families to be loaded as well. In this case, the SCSI family is loaded; the PCI family (also required) is already present. The SCSI controller driver is given a reference to the IOPCIDevice nub. 3. The SCSI controller driver scans the SCSI bus for devices. Upon finding a device, it announces the presence of the device by creating a nub (IOSCSIDevice). The class of this nub is defined by the SCSI family. IOPCIBridge family PCI bus driver IOSCSIParallelController family SCSI card driver IOPCIDevice nubs IOSCSIParallelDevice nubs SCSI disk Unknown device SCSI scanner 1 5 6 I/O Kit Overview I/O Kit Architecture 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 994. The controller driver identifies (matches) the correct device driver and requests that the driver be loaded. At the end of this matching process, a disk driver has been found and loaded. Loading the disk driver causes all required families to be loaded as well. In this case, the Storage family is loaded; the SCSI family (also required) is already present. The disk driver is given a reference to the IOSCSIDevice nub. IOPCIBridge family PCI bus driver IOSCSIParallelController family SCSI card driver IOBlockStorageDriver family SCSI disk driver IOPCIDevice nubs IOSCSIParallelDevice nubs IOMedia nub Disk For More Information For more information on the I/O Kit, you should read the document I/O Kit Fundamentals, available from Apple’s developer documentation website, http://developer.apple.com/documentation. It provides a good general overview of the I/O Kit. In addition to I/O Kit Fundamentals, the website contains a number of HOWTO documents and topic-specific documents that describe issues specific to particular technology areas such as FireWire and USB. I/O Kit Overview For More Information 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 100The BSD portion of the OS X kernel is derived primarily from FreeBSD, a version of 4.4BSD that offers advanced networking, performance, security, and compatibility features. BSD variants in general are derived (sometimes indirectly) from 4.4BSD-Lite Release 2 from the Computer Systems Research Group (CSRG) at the University of California at Berkeley. BSD provides many advanced features, including the following: ● Preemptive multitasking with dynamic priority adjustment. Smooth and fair sharing of the computer between applications and users is ensured, even under the heaviest of loads. ● Multiuser access. Many people can use an OS X system simultaneously for a variety of things. This means, for example, thatsystem peripheralssuch as printers and disk drives are properly shared between all users on the system or the network and that individual resource limits can be placed on users or groups of users, protecting critical system resources from overuse. ● Strong TCP/IP networking with support for industry standards such as SLIP, PPP, and NFS. OS X can interoperate easily with other systems as well as act as an enterprise server, providing vital functions such as NFS (remote file access) and email services, or Internet services such as HTTP, FTP, routing, and firewall (security) services. ● Memory protection. Applications cannot interfere with each other. One application crashing does not affect others in any way. ● Virtual memory and dynamic memory allocation. Applications with large appetitesfor memory are satisfied while still maintaining interactive response to users. With the virtual memory system in OS X, each application has access to its own 4 GB memory address space; this should satisfy even the most memory-hungry applications. ● Support for kernel threads based on Mach threads. User-level threading packages are implemented on top of kernel threads. Each kernel thread is an independently scheduled entity. When a thread from a user process blocks in a system call, other threads from the same process can continue to execute on that or other processors. By default, a process in the conventional sense has one thread, the main thread. A user process can use the POSIX thread API to create other user threads. ● SMP support. Support is included for computers with multiple CPUs. ● Source code. Developers gain the greatest degree of control over the BSD programming environment because source is included. ● Many of the POSIX APIs. 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 101 BSD OverviewBSD Facilities The facilities that are available to a user process are logically divided into two parts: kernel facilities and system facilities implemented by or in cooperation with a server process. The facilities implemented in the kernel define the virtual machine in which each process runs. Like many real machines, this virtual machine has memory management, an interrupt facility, timers, and counters. The virtual machine also allows access to files and other objects through a set of descriptors. Each descriptor resembles a device controller and supports a set of operations. Like devices on real machines, some of which are internal to the machine and some of which are external, parts of the descriptor machinery are built into the operating system, while other parts are often implemented in server processes. The BSD component provides the following kernel facilities: ● processes and protection ● host and process identifiers ● process creation and termination ● user and group IDs ● process groups ● memory management ● text, data, stack, and dynamic shared libraries ● mapping pages ● page protection control ● POSIX synchronization primitives ● POSIX shared memory ● signals ● signal types ● signal handlers ● sending signals ● timing and statistics ● real time ● interval time ● descriptors ● files ● pipes BSD Overview BSD Facilities 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 102● sockets ● resource controls ● process priorities ● resource utilization and resource limits ● quotas ● system operation support ● bootstrap operations ● shut-down operations ● accounting BSD system facilities (facilities that may interact with user space) include ● generic input/output operations such as read and write, nonblocking, and asynchronous operations ● file-system operations ● interprocess communication ● handling of terminals and other devices ● process control ● networking operations Differences between OS X and BSD Although the BSD portion of OS X is primarily derived from FreeBSD, some changes have been made: ● The sbrk() system call for memory management is deprecated. Its use is not recommended in OS X. ● The OS X runtime model uses a different object file format for executables and shared objects, and a different mechanism for executing some of those executables. The primary native format is Mach-O. This format is supported by the dynamic link editor (dyld). The PEF binary file format is supported by the Code Fragment Manager (CFM). The kernel supports execve() with Mach-O binaries. Mapping and management of Mach-O dynamic shared libraries, as well as launching of PEF-based applications, are performed by user-space code. ● OS X does not support memory-mapped devices through the mmap() function. (Graphic device support and other subsystems provide similar functionality, but using different APIs.) In OS X, this interface should be done through user clients. See the Apple I/O Kit documents for additional information. ● The swapon() call is not supported; macx_swapon() is the equivalent call from the Mach pager. BSD Overview Differences between OS X and BSD 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 103● The Unified Buffer Cache implementation in OS X differs from that found in FreeBSD. ● Mach provides a number of IPC primitives that are not traditionally found in UNIX. See “Boundary Crossings” (page 109) for more information on Mach IPC. Some System V primitives are supported, but their use is discouraged in favor of POSIX equivalents. ● Several changes have been made to the BSD security model to support single-user and multiple-administrator configurations, including the ability to disable ownership and permissions on a volume-by-volume basis. ● The locking mechanism used throughout the kernel differs substantially from the mechanism used in FreeBSD. ● The kernel extension mechanism used by OS X is completely different. The OS X driver layer, the I/O Kit, is an object-oriented driver stack written in C++. The general kernel programming interfaces, or KPIs, are used to write non-driver kernel extensions. These mechanisms are described more in “I/O Kit Overview” (page 94) and KPI Reference , respectively. In addition, several new features have been added that are specific to the OS X (Darwin) implementation of BSD. These features are not found in FreeBSD. ● enhancements to file-system buffer cache and file I/O clustering ● adaptive and speculative read ahead ● user-process controlled read ahead ● time aging of the file-system buffer cache ● enhancements to file-system support ● implementation of Apple extensions for ISO-9660 file systems ● multithreaded asynchronous I/O for NFS ● addition of system calls to support semantics of Mac OS Extended (HFS+) file systems ● additions to naming conventions for pathnames, as required for accessing multiple forks in Mac OS Extended file systems For Further Reading The BSD component of the OS X kernel is complex. A complete description is beyond the scope of this document. However, many excellent references exist for this component. If you are interested in BSD, be sure to refer to the bibliography for further information. BSD Overview For Further Reading 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 104Although the BSD layer of OS X is derived from 4.4BSD, keep in mind that it is not identical to 4.4BSD. Some functionality of 4.4 BSD has not been included in OS X. Some new functionality has been added. The cited reference materials are recommended for additional reading. However, they should not be presumed as forming a definitive description of OS X. BSD Overview For Further Reading 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 105OS X provides“out-of-the-box”support forseveral different file systems. These include Mac OS Extended format (HFS+), the BSD standard file system format (UFS), NFS (an industry standard for networked file systems), ISO 9660 (used for CD-ROM), MS-DOS, SMB (Windows file sharing standard), AFP (Mac OS file sharing), and UDF. Support is also included for reading the older, Mac OS Standard format (HFS) file-system type; however, you should not plan to format new volumes using Mac OS Standard format. OS X cannot boot from these file systems, nor does the Mac OS Standard format provide some of the information required by OS X. The Mac OS Extended format provides many of the same characteristics as Mac OS Standard format but adds additional support for modern features such as file permissions, longer filenames, Unicode, both hard and symbolic links, and larger disk sizes. UFS provides case sensitivity and other characteristics that may be expected by BSD commands. In contrast, Mac OS Extended Format is not case-sensitive (but is case-preserving). OS X currently can boot and “root” from an HFS+, UFS, ISO, NFS, or UDF volume. That is, OS X can boot from and mount a volume of any of these types and use it as the primary, or root, file system. Other file systems can also be mounted, allowing usersto gain accessto additional volume formats and features. NFS provides access to network servers as if they were locally mounted file systems. The Carbon application environment mimics many expected behaviors of Mac OS Extended format on top of both UFS and NFS. These include such characteristics as Finder Info, file ID access, and aliases. By using the OS X Virtual File System (VFS) capability and writing kernel extensions, you can add support for other file systems. Examples of file systems that are not currently supported in OS X but that you may wish to add to the system include the Andrew file system (AFS) and the Reiser file system (ReiserFS). If you want to support a new volume format or networking protocol, you’ll need to write a file-system kernel extension. Working With the File System In OS X, the vnode structure providesthe internal representation of a file or directory (folder). There is a unique vnode allocated for each active file or folder, including the root. 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 106 File Systems OverviewWithin a file system, operations on specific files and directories are implemented via vnodes and VOP (vnode operation) calls. VOP calls are used for operations on individual files or directories (such as open, close, read, or write). Examples include VOP_OPEN to open a file and VOP_READ to read file contents. In contrast, file-system–wide operations are implemented using VFS calls. VFS calls are primarily used for operations on entire file systems; examples include VFS_MOUNT and VFS_UNMOUNT to mount or unmount a file system, respectively. File-system writers need to provide stubs for each of these sets of calls. VFS Transition The details of the VFS subsystem in OS X are in the process of changing in order to make the VFS interface sustainable. If you are writing a leaf file system, these changes will still affect you in many ways. please contact Apple Developer Support for more information. File Systems Overview VFS Transition 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 107OS X kernel extensions (KEXTs) provide mechanisms to extend and modify the networking infrastructure of OS X dynamically, without recompiling or relinking the kernel. The effect is immediate and does not require rebooting the system. Networking KEXTs can be used to ● monitor network traffic ● modify network traffic ● receive notification of asynchronous events from the driver layer In the last case, such events are received by the data link and network layers. Examples of these events include power management events and interface status changes. Specifically, KEXTs allow you to ● create protocol stacks that can be loaded and unloaded dynamically and configured automatically ● create modulesthat can be loaded and unloaded dynamically atspecific positionsin the network hierarchy. The Kernel Extension Manager dynamically adds KEXTs to the running OS X kernel inside the kernel’s address space. An installed and enabled network-related KEXT is invoked automatically, depending on its position in the sequence of protocol components, to process an incoming or outgoing packet. All KEXTs provide initialization and termination routines that the Kernel Extension Manager invokes when it loads or unloads the KEXT. The initialization routine handles any operations that are needed to complete the incorporation of the KEXT into the kernel, such as updating protosw and domain structures (through programmatic interfaces). Similarly, the termination routine must remove references to the NKE from these structures to unload itself successfully. NKEs must provide a mechanism, such as a reference count, to ensure that the NKE can terminate without leaving dangling pointers. For additional information on the networking portions of the OS X kernel, you should read the document Network Kernel Extensions Programming Guide . 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 108 Network ArchitectureTwo applications can communicate in a number of ways—for example, by using pipes or sockets. The applicationsthemselves are unaware of the underlying mechanismsthat provide this communication. However this communication occurs by sending data from one program into the kernel, which then sends the data to the second program. As a kernel programmer, it is your job to create the underlying mechanisms responsible for communication between your kernel code and applications. This communication is known as crossing the user-kernel boundary. This chapter explains various ways of crossing that boundary. In a protected memory environment, each process is given its own address space. This means that no program can modify another program’s data unless that data also resides in its own memory space (shared memory). The same applies to the kernel. It resides in its own address space. When a program communicates with the kernel, data cannot simply be passed from one address space to the other as you might between threads (or between programs in environments like Mac OS 9 and most real-time operating systems, which do not have protected memory). We refer to the kernel’s address space as kernel space, and collectively refer to applications’ address spaces as user space. For this reason, applications are also commonly referred to as user-space programs, or user programs for short. When the kernel needs a small amount of data from an application, the kernel cannot just dereference a pointer passed in from that application, since that pointer is relative to the application’s address space. Instead, the kernel generally copies that information into storage within its own address space. When a large region of data needs to be moved, it may map entire pages into kernel space for efficiency. The same behavior can be seen in reverse when moving data from the kernel to an application. Because it is difficult to move data back and forth between the kernel and an application, this separation is called a boundary. It isinherently time consuming to copy data, even if that data isjust the user-space address of a shared region. Thus, there is a performance penalty whenever a data exchange occurs. If this penalty is a serious problem, it may affect which method you choose for crossing the user-kernel boundary. Also, by trying to minimize the number of boundary crossings, you may find ways to improve the overall design of your code. This is particularly significant if your code is involved in communication between two applications, since the user-kernel boundary must be crossed twice in that case. There are a number of ways to cross the user-kernel boundary. Some of them are covered in this chapter in the following sections: 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 109 Boundary Crossings● “Mach Messaging and Mach Interprocess Communication (IPC)” (page 112) ● “BSD syscall API ” (page 116) ● “BSD ioctl API” (page 116) ● “BSD sysctl API ” (page 117) ● “Memory Mapping and Block Copying” (page 125) In addition, the I/O Kit uses the user-client/device-interface API for most communication. Because that API is specific to the I/O Kit, it is not covered in this chapter. The user client API is covered in I/O Kit Fundamentals, Accessing Hardware From Applications, and I/O Kit Device Driver Design Guidelines. The ioctl API is also specific to the construction of device drivers, and is largely beyond the scope of this document. However, since ioctl is a BSD API, it is covered at a glance for your convenience. This chapter covers one subset of Mach IPC—the Mach remote procedure call (RPC) API. It also covers the syscall, sysctl, memory mapping, and block copying APIs. Security Considerations Crossing the user-kernel boundary represents a security risk if the kernel code operates on the data in any substantial way (beyond writing it to disk or passing it to another application). You must carefully perform bounds checking on any data passed in, and you must also make sure your code does not dereference memory that no longer belongs to the client application. Also, under no circumstances should you run unverified program code passed in from user space within the kernel. See “Security Considerations” (page 24) for further information. Choosing a Boundary Crossing Method The first step in setting up user-kernel data exchange is choosing a means to do that exchange. First, you must consider the purpose for the communication. Some crucial factors are latency, bandwidth, and the kernel subsystem involved. Before choosing a method of communication, however, you should first understand at a high-level each of these forms of communication. Mach messaging and Mach interprocess communication (IPC) are relatively low-level ways of communicating between two Mach tasks (processes), as well as between a Mach task and the kernel. These form the basis for most communication outside of BSD and the I/O Kit. The Mach remote procedure call (RPC) API is a high level procedural abstraction built on top of Mach IPC. Mach RPC is the most common use of IPC. Boundary Crossings Security Considerations 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 110The BSD syscall API is an API for calling kernel functions from user space. It is used extensively when writing file systems and networking protocols, in ways that are very subsystem-dependent. Developers are strongly discouraged from using the syscall API outside of file-system and network extensions, as no plug-in API exists for registering a new system call with the syscall mechanism. The BSD sysctl API (in its revised form) supersedes the syscall API and also provides a relatively painless way to change individual kernel variablesfrom userspace. It has a straightforward plug-in architecture, making it a good choice where possible. Memory mapping and block copying are used in conjunction with one of the other APIs mentioned, and provide ways of moving large amounts of data (more than a few bytes) or variably sized data to and from kernel space. Kernel Subsystems The choice of boundary crossing methods depends largely on the part of the kernel into which you are adding code. In particular, the boundary crossing method preferred for the I/O Kit is different from that preferred for BSD, which is different from that preferred for Mach. If you are writing a device driver or other related code, you are probably dealing with the I/O Kit. In that case, you should instead read appropriate sections in I/O Kit Fundamentals, Accessing Hardware From Applications, and I/O Kit Device Driver Design Guidelines. If you are writing code that resides in the BSD subsystem (for example, a file system), you should generally use BSD APIs such as syscall or sysctl unless you require high bandwidth or exceptionally low latency. If you are writing code that resides anywhere else, you will probably have to use Mach messaging. Bandwidth and Latency The guidelines in the previous section apply to most communication between applications and kernel code. The methods mentioned, however, are somewhat lacking where high bandwidth or low latency are concerns. If you require high bandwidth, but latency is not an issue, you should probably consider doing memory-mapped communication. For large messagesthisis handled somewhat transparently by Mach RPC, making it a reasonable choice. For BSD portions of the kernel, however, you must explicitly pass pointers and use copyin and copyout to move large quantities of data. Thisis discussed in more detail in “Memory Mapping and Block Copying” (page 125). Boundary Crossings Choosing a Boundary Crossing Method 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 111If you require low latency but bandwidth is not an issue, sysctl and syscall are not good choices. Mach RPC, however, may be an acceptable solution. Another possibility is to actually wire a page of memory (see “Memory Mapping and Block Copying” (page 125) for details),start an asynchronous Mach RPC simpleroutine (to process the data), and use either locks or high/low water marks (buffer fullness) to determine when to read and write data. This can work for high-bandwidth communication as well. If you require both high bandwidth and low latency, you should also look at the user client/device interface model used in the I/O Kit, since that model has similar requirements. Mach Messaging and Mach Interprocess Communication (IPC) Mach IPC and Mach messaging are the basis for much of the communication in OS X. In many cases, however, these facilities are used indirectly by services implemented on top of one of them. Mach messaging and IPC are fundamentally similar except that Mach messaging is stateless, which prevents certain types of error recovery, as explained later. Except where explicitly stated, this section treats the two as equivalent. The fundamental unit of Mach IPC isthe port. The concept of Mach ports can be difficult to explain in isolation, so instead this section assumes a passing knowledge of a similar concept, that of ports in TCP/IP. In TCP/IP, a server listens for incoming connections over a network on a particular port. Multiple clients can connect to the port and send and receive data in word-sized or multiple-word–sized blocks. However, only one server process can be bound to the port at a time. In Mach IPC, the concept is the same, but the players are different. Instead of multiple hosts connecting to a TCP/IP port, you have multiple Mach tasks on the same computer connecting to a Mach port. Instead of firewall rules on a port, you have port rights that specify what tasks can send data to a particular Mach port. Also, TCP/IP ports are bidirectional, while Mach ports are unidirectional, much like UNIX pipes. This means that when a Mach task connects to a port, it generally allocates a reply port and sends a message containing send rights to that reply port so that the receiving task can send messages back to the sending task. As with TCP/IP, multiple client tasks can open connections to a Mach port, but only one task can be listening on that port at a time. Unlike TCP/IP, however, the IPC mechanism itself provides an easy means for one task to hand off the right to listen to an arbitrary task. The term receive rights refers to a task’s ability to listen on a given port. Receive rights can be sent from task to task in a Mach message. In the case of Mach IPC (but not Mach messaging), receive rights can even be configured to automatically return to the original task if the new task crashes or becomes unreachable (for example, if the new task isrunning on another computer and a router crashes). Boundary Crossings Mach Messaging and Mach Interprocess Communication (IPC) 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 112In addition to specifying receive rights, Mach ports can specify which tasks have the right to send data. A task with send rights may be able to send once, or may be able to arbitrarily send data to a given port, depending on the nature of the rights. Using Well-Defined Ports Before you can use Mach IPC for task communication, the sending task must be able to obtain send rights on the receiving task’s task port. Historically, there are several ways of doing this, not all of which are supported by OS X. For example, in OS X, unlike most other Mach derivatives, there is no service server or name server. Instead, the bootstrap task and mach_init subsume this functionality. When a task is created, it is given send rights to a bootstrap port for sending messages to the bootstrap task. Normally a task would use this port to send a message that gives the bootstrap task send rights on another port so that the bootstrap task can then return data to the calling task. Various routines exist in bootstrap.h that abstract this process. Indeed, most users of Mach IPC or Mach messaging actually use Mach remote procedure calls (RPC), which are implemented on top of Mach IPC. Since direct use of IPC is rarely desirable (because it is not easy to do correctly), and because the underlying IPC implementation has historically changed on a regular basis, the details are not covered here. You can find more information on using Mach IPC directly in the Mach 3 Server Writer’s Guide from Silicomp (formerly the Open Group, formerly the Open Software Foundation Research Institute), which can be obtained from the developer section of Apple’s website. While much of the information contained in that book is not fully up-to-date with respect to OS X, it should still be a relatively good resource on using Mach IPC. Remote Procedure Calls (RPC) Mach RPC is the most common use for Mach IPC. It is frequently used for user-kernel communication, but can also be used for task to task or even computer-to-computer communication. Programmers frequently use Mach RPC for setting certain kernel parameters such as a given thread’s scheduling policy. RPC is convenient because it is relatively transparent to the programmer. Instead of writing long, complex functionsthat handle ports directly, you have only to write the function to be called and a small RPC definition to describe how to export the function as an RPC interface. After that, any application with appropriate permissions can call those functions as if they were local functions, and the compiler will convert them to RPC calls. In the directory osfmk/mach (relative to your checkout of the xnu module from CVS), there are a number of files ending in .defs; these files contain the RPC definitions. When the kernel (or a kernel module) is compiled, the Mach Interface Generator(MIG) usesthese definitionsto create IPC code to support the functions exported via RPC. Normally, if you want to add a new remote procedure call, you should do so by adding a definition to one of these existing files. (See “Building and Debugging Kernels” (page 155) for more information on obtaining kernel sources.) Boundary Crossings Mach Messaging and Mach Interprocess Communication (IPC) 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 113What follows is an example of the definition for a routine, one of the more common uses of RPC. routine thread_policy_get( thread : thread_act_t; flavor : thread_policy_flavor_t; out policy_info : thread_policy_t, CountInOut; inout get_default : boolean_t); Notice the C-like syntax of the definition. Each parameter in the routine roughly maps onto a parameter in the C function. The C prototype for this function follows. kern_return_t thread_policy_get( thread_act_t act, thread_policy_flavor_t flavor, thread_policy_t policy_info, mach_msg_type_number_t *count, boolean_t get_default); The first two parameters are integers, and are passed as call-by-value. The third is a struct containing integers. It is an outgoing parameter, which means that the values stored in that variable will not be received by the function, but will be overwritten on return. Note: The parameters are all word-sized or multiples of the word size. Smaller data are impossible because of limitations inherent to the underlying Mach IPC mechanisms. From there it becomes more interesting. The fourth parameter in the C prototype is a representation of the size of the third. In the definition file, this is represented by an added option, CountInOut. The MIG option CountInOut specifies that there is to be an inout parameter called count. An inout parameter is one in which the original value can be read by the function being called, and its value is replaced on return from that function. Unlike a separate inout parameter, however, the value initially passed through this parameter is not directly set by the calling function. Instead, it is tied to the policy_info parameter so that the number of integers in policy_info is transparently passed in through this parameter. Boundary Crossings Mach Messaging and Mach Interprocess Communication (IPC) 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 114In the function itself, the function checks the count parameter to verify that the buffer size is at least the size of the data to be returned to prevent exceeding array bounds. The function changes the value stored in count to be the desired size and returns an error if the buffer is not large enough (unless the buffer pointer is null, in which case it returns success). Otherwise, it dereferences the various fields of the policy_info parameter and in so doing, stores appropriate values into it, then returns. Note: Since Mach RPC is done via message passing, inout parameters are technically call-by-value-return and not call-by-reference. For more realistic call-by-reference, you need to pass a pointer. The distinction is not particularly significant except when aliasing occurs. (Aliasing means having a single variable visible in the same scope under two or more different names.) In addition to the routine, Mach RPC also has a simpleroutine. A simpleroutine is a routine that is, by definition, asynchronous. It can have no out or inout parameters and no return value. The caller does not wait for the function to return. One possible use for this might be to tell an I/O device to send data as soon as it is ready. In that use, the simpleroutine might simply wait for data, then send a message to the calling task to indicate the availability of data. Another important feature of MIG is that of the subsystem. In MIG, a subsystem is a group of routines and simpleroutines that are related in some way. For example, the semaphore subsystem contains related routinesthat operate on semaphores. There are also subsystemsfor varioustimers, parts of the virtual memory (VM) system, and dozens of others in various places throughout the kernel. Most of the time, if you need to use RPC, you will be doing it within an existing subsystem. The details of creating a new subsystem are beyond the scope of this document. Developers needing to add a new Mach subsystem should consult the Mach 3 ServerWriter’s Guide from The Open Group (TOG), which can be obtained from various locations on the internet. Another feature of MIG is the type. A type in MIG is exactly the same thing as it is in programming languages. However, the construction of aggregate types differs somewhat. type clock_flavor_t = int; type clock_attr_t = array[*:1] of int; type mach_timespec_t = struct[2] of int; Data of type array is passed as the user-space address of what is assumed to be a contiguous array of the base type, while a struct is passed by copying all of the individual values of an array of the base type. Otherwise, these are treated similarly. A “struct” is not like a C struct, as elements of a MIG struct must all be of the same base type. Boundary Crossings Mach Messaging and Mach Interprocess Communication (IPC) 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 115The declaration syntax issimilar to Pascal, where *:1 and 2 representsizesfor the array orstructure, respectively. The *:1 construct indicates a variable-sized array, where the size can be up to 1, inclusive, but no larger. Calling RPC From User Applications RPC, as mentioned previously, is virtually transparent to the client. The procedure call looks like any other C function call, and no additional library linkage is needed. You need only to bring the appropriate headers in with a #include directive. The compiler automatically recognizes the call as a remote procedure call and handles the underlying MIG aspects for you. BSD syscall API The syscall API is the traditional UNIX way of calling kernel functions from user space. Its implementation variesfrom one part of the kernel to the next, however, and it is completely unsupported for loadable modules. For this reason, it is not a recommended way of getting data into or out of the kernel in OS X unless you are writing a file system. File systems have to support a number of standard system calls (for example, mount), but do so by means of generic file system routinesthat call the appropriate file-system functions. Thus, if you are writing a file system, you need to implement those functions, but you do not need to write the code that handles the system calls directly. For more information on implementing syscall support in file systems,see the chapter “File Systems Overview” (page 106). BSD ioctl API The ioctl interface provides a way for an application to send certain commands or information to a device driver. These can be used for parameter tuning (though this is more commonly done with sysctl), but can also be used for sending instructions for the driver to perform a particular task (for example, rewinding a tape drive). The use of the ioctl interface is essentially the same under OS X as it is in other BSD-derived operating systems, except in the way that device drivers register themselves with the system. In OS X, unlike most BSDs, the contents of the /dev directory are created dynamically by the kernel. This file system mounted on /dev is referred to as devfs. You can, of course, still manually create device nodes with mknod, because devfs is union mounted over the root file system. Boundary Crossings BSD syscall API 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 116The I/O Kit automatically registers some types of devices with devfs, creating a node in /dev. If your device family does not do that, you can manually register yourself in devfs using cdevsw_add or bdevsw_add (for character and block devices, respectively). When registering a device manually with devfs, you create a struct cdevsw or struct bdevsw yourself. In that device structure, one of the function pointers is to an ioctl function. You must define the particular values passed to the ioctl function in a header file accessible to the person compiling the application. A user application can also look up the device using the I/O Kit function call getMatchingServices and then use various I/O Kit calls to tune parameter instead. For more information on looking up a device driver from an application, see the document Accessing Hardware From Applications. You can also find additional information about writing an ioctl in The Design and Implementation of the 4.4 BSD Operating System. See the bibliography at the end of this document for more information. BSD sysctl API The system control (sysctl) API is specifically designed for kernel parameter tuning. This functionality supersedesthe syscall API, and also provides an easy way to tune simple kernel parameters without actually needing to write a handler routine in the kernel. The sysctl namespace is divided into several broad categories corresponding to the purpose of the parameters in it. Some of these areas include ● kern—general kernel parameters ● vm—virtual memory options ● fs—filesystem options ● machdep—machine dependent settings ● net—network stack settings ● debug—debugging settings ● hw—hardware parameters (generally read-only) ● user—parameters affecting user programs ● ddb—kernel debugger Most of the time, programs use the sysctl call to retrieve the current value of a kernel parameter. For example, in OS X, the hw sysctl group includesthe option ncpu, which returnsthe number of processorsin the current computer (or the maximum number of processors supported by the kernel on that particular computer, whichever is less). Boundary Crossings BSD sysctl API 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 117The sysctl API can also be used to modify parameters (though most parameters can only be changed by the root). For example, in the net hierarchy, net.inet.ip.forwarding can be set to 1 or 0, to indicate whether the computer should forward packets between multiple interfaces (basic routing). General Information on Adding a sysctl When adding a sysctl, you must do all of the following first: ● add the following includes: #include #include #include #include ● add -no-cpp-precomp to your compiler options in Project Builder (or to CFLAGS in your makefile if building by hand). Adding a sysctl Procedure Call Adding a system control (sysctl) was once a daunting task requiring changes to dozens of files. With the current implementation, a system control can be added simply by writing the appropriate handler functions and then registering the handler with the system at runtime. The old-style sysctl, which used fixed numbers for each control, is deprecated. Note: Because this is largely a construct of the BSD subsystem, all path names in this section can be assumed to be from /path/to/xnu-version/bsd/. Also, you may safely assume that all program code snippets should go into the main source file for your subsystem or module unless otherwise noted, and that in the case of modules, function calls should be made from your start or stop routines unless otherwise noted. The preferred way of adding a sysctl looks something like the following: SYSCTL_PROC(_hw, OID_AUTO, l2cr, CTLTYPE_INT|CTLFLAG_RW, &L2CR, 0, &sysctl_l2cr, "I", "L2 Cache Register"); Boundary Crossings BSD sysctl API 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 118The _PROC part indicates that you are registering a procedure to provide the value (as opposed to simply reading from a static address in kernel memory). _hw is the top level category (in this case, hardware), and OID_AUTO indicates that you should be assigned the next available control ID in that category (as opposed to the old-style, fixed ID controls). l2cr is the name of your control, which will be used by applications to look up the number of your control using sysctlbyname. Note: Not all top level categories will necessarily accept the addition of a user-specified new-style sysctl. If you run into problems, you should try a different top-level category. CTLTYPE_INT indicates that the value being changed is an integer. Other legal values are CTLTYPE_NODE, CTLTYPE_STRING, CTLTYPE_QUAD, and CTLTYPE_OPAQUE (also known as CTLTYPE_STRUCT). CTLTYPE_NODE isthe only one that isn’tsomewhat obvious. It refersto a node in the sysctl hierarchy that isn’t directly usable, but instead is a parent to other entries. Two examples of nodes are hw and kern. CTLFLAG_RW indicatesthat the value can be read and written.Other legal values are CTLFLAG_RD, CTLFLAG_WR, CTLFLAG_ANYBODY, and CTLFLAG_SECURE. CTLFLAG_ANYBODY means that the value should be modifiable by anybody. (The default is for variables to be changeable only by root.) CTLFLAG_SECURE means that the variable can be changed only when running at securelevel <= 0 (effectively, in single-user mode). L2CR is the location where the sysctl will store its data. Since the address is set at compile time, however, this must be a global variable or a static local variable. In this case, L2CR is a global of type unsigned int. The number 0 is a second argument that is passed to your function. This can be used, for example, to identify which sysctl was used to call your handler function if the same handler function is used for more than one control. In the case of strings, this is used to store the maximum allowable length for incoming values. sysctl_l2cr is the handler function for this sysctl. The prototype for these functions is of the form static int sysctl_l2cr SYSCTL_HANDLER_ARGS; If the sysctl is writable, the function may either use sysctl_handle_int to obtain the value passed in from user space and store it in the default location or use the SYSCTL_IN macro to store it into an alternate buffer. This function must also use the SYSCTL_OUT macro to return a value to user space. "I" indicates that the argument should refer to a variable of type integer (or a constant, pointer, or other piece of data of equivalent width), as opposed to "L" for a long, "A" for a string, "N" for a node (a sysctl that is the parent of a sysctl category or subcategory), or "S" for a struct. "L2 Cache Register" is a human-readable description of your sysctl. In order for a control to be accessible from an application, it must be registered. To do this, you do the following: Boundary Crossings BSD sysctl API 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 119sysctl_register_oid(&sysctl__hw_l2cr); You should generally do this in an init routine for a loadable module. If your code is not part of a loadable module, you should add your sysctl to the list of built-in OIDs in the file kern/sysctl_init.c. If you study the SYSCTL_PROC constructor macro, you will notice that sysctl__hw_l2cr is the name of a variable created by that macro. This meansthat the SYSCTL_PROC line must be before sysctl_register_oid in the file, and must be in the same (or broader) scope. This name is in the form of sysctl_ followed by the name of it’s parent node, followed by another underscore ( _ ) followed by the name of your sysctl. A similar function, sysctl_unregister_oid exists to remove a sysctl from the registry. If you are writing a loadable module, you should be certain to do this when your module is unloaded. In addition to registering your handler function, you also have to write the function. The following is a typical example static int myhandler SYSCTL_HANDLER_ARGS { int error, retval; error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req); if (!error && req->newptr) { /* We have a new value stored in the standard location.*/ /* Do with it as you see fit here. */ printf("sysctl_test: stored %d\n", SCTEST); } else if (req->newptr) { /* Something was wrong with the write request */ /* Do something here if you feel like it.... */ } else { /* Read request. Always return 763, just for grins. */ printf("sysctl_test: read %d\n", SCTEST); retval=763; error=SYSCTL_OUT(req, &retval, sizeof retval); } /* In any case, return success or return the reason for failure */ return error; Boundary Crossings BSD sysctl API 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 120} This demonstrates the use of SYSCTL_OUT to send an arbitrary value out to user space from the sysctl handler. The “phantom” req argument is part of the function prototype when the SYSCTL_HANDLER_ARGS macro is expanded, as is the oidp variable used elsewhere. The remaining arguments are a pointer (type indifferent) and the length of data to copy (in bytes). This code sample also introduces a new function, sysctl_handle_int, which takes the arguments passed to the sysctl, and writes the integer into the usual storage area (L2CR in the earlier example, SCTEST in this one). If you want to see the new value without storing it (to do a sanity check, for example), you should instead use the SYSCTL_IN macro, whose arguments are the same as SYSCTL_OUT. Registering a New Top Level sysctl In addition to adding new sysctl options, you can also add a new category or subcategory. The macro SYSCTL_DECL can be used to declare a node that can have children. This requires modifying one additional file to create the child list. For example, if your main C file does this: SYSCTL_DECL(_net_newcat); SYSCTL_NODE(_net, OID_AUTO, newcat, CTLFLAG_RW, handler, "new category"); then this is basically the same thing as declaring extern sysctl_oid_list sysctl__net_newcat_children in your program. In order for the kernel to compile, or the module to link, you must then add this line: struct sysctl_oid_list sysctl__net_newcat_children; If you are not writing a module, this should go in the file kern/kern_newsysctl.c. Otherwise, it should go in one of the files of your module. Once you have created this variable, you can use _net_newcat as the parent when creating a new control. As with any sysctl, the node (sysctl__net_newcat) must be registered with sysctl_register_oid and can be unregistered with sysctl_unregister_oid. Boundary Crossings BSD sysctl API 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 121Note: When creating a top level sysctl, parent is simply left blank, for example, SYSCTL_NODE( , OID_AUTO, _topname, flags, handler_fn, "desc"); Adding a Simple sysctl If your sysctl only needsto read a value out of a variable, then you do not need to write a function to provide access to that variable. Instead, you can use one of the following macros: ● SYSCTL_INT(parent, nbr, name, access, ptr, val, descr) ● SYSCTL_LONG(parent, nbr, name, access, ptr, descr) ● SYSCTL_STRING(parent, nbr, name, access, arg, len, descr) ● SYSCTL_OPAQUE(parent, nbr, name, access, ptr, len, descr) ● SYSCTL_STRUCT(parent, nbr, name, access, arg, type, descr) The first four parameters for each macro are the same as for SYSCTL_PROC (described in the previous section) as is the last parameter. The len parameter (where applicable) gives a length of the string or opaque object in bytes. The arg parameters are pointersjust like the ptr parameters. However, the parameters named ptr are explicitly described as pointers because you must explicitly use the “address of” (&) operator unless you are already working with a pointer. Parameters called arg either operate on base types that are implicitly pointers or add the & operator in the appropriate place during macro expansion. In both cases, the argument should refer to the integer, character, or other object that the sysctl will use to store the current value. The type parameter is the name of the type minus the “struct”. For example, if you have an object of type struct scsipi, then you would use scsipi as that argument. The SYSCTL_STRUCT macro is functionally equivalent to SYSCTL_OPAQUE, except that it hides the use of sizeof. Finally, the val parameter for SYSCTL_INT is a default value. If the value passed in ptr is NULL, this value is returned when the sysctl is used. You can use this, for example, when adding a sysctl that is specific to certain hardware or certain compile options. One possible example of this might be a special value for feature.version that means “not present.” If that feature became available (for example, if a module were loaded by some user action), it could then update that pointer. If that module were subsequently unloaded, it could set the pointer back to NULL. Boundary Crossings BSD sysctl API 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 122Calling a sysctl From User Space Unlike RPC, sysctl requires explicit intervention on the part of the programmer. To complicate thingsfurther, there are two different ways of calling sysctl functions, and neither one worksfor every control. The old-style sysctl call can only invoke a control if it is listed in a static OID table in the kernel. The new-style sysctlbyname call will work for any user-added sysctl, but not for those listed in the static table. Occasionally, you will even find a control that isregistered in both ways, and thus available to both calls. In order to understand the distinction, you must first consider the functions used. The sysctlbyname System Call If you are calling a sysctl that was added using the new sysctl method (including any sysctl that you may have added), then your sysctl does not have a fixed number that identifies it, since it was added dynamically to the system. Since there is no approved way to get this number from user space, and since the underlying implementation is not guaranteed to remain the same in future releases, you cannot call a dynamically added control using the sysctl function. Instead, you must use sysctlbyname. sysctlbyname(char *name, void *oldp, size_t *oldlenp, void *newp, u_int newlen) The parameter name is the name of the sysctl, encoded as a standard C string. The parameter oldp is a pointer to a buffer where the old value will be stored. The oldlenp parameter is a pointer to an integer-sized buffer that holds the current size of the oldp buffer. If the oldp buffer is not large enough to hold the returned data, the call will fail with errno set to ENOMEM, and the value pointed to by oldlenp will be changed to indicate the buffer size needed for a future call to succeed. Here is an example for reading an integer, in this case a buffer size. int get_debug_bufsize() { char *name="debug.bpf_bufsize"; int bufsize, retval; size_t len; len=4; retval=sysctlbyname(name, &bufsize, &len, NULL, 0); /* Check retval here */ return bufsize; } Boundary Crossings BSD sysctl API 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 123The sysctl System Call The sysctlbyname system call is the recommended way to call system calls. However, not every built-in system control is registered in the kernel in such a way that it can be called with sysctlbyname. For this reason, you should also be aware of the sysctl system call. Note: If you are adding a sysctl, it will be accessible using sysctlbyname. You should use this system call only if the sysctl you need cannot be retrieved using sysctlbyname. In particular, you should not assume that future versions of sysctl will be backed by traditional numeric OIDs except for the existing legacy OIDs, which will be retained for compatibility reasons. The sysctl system call is part of the original historical BSD implementation of system controls. You should not depend on its use for any control that you might add to the system. The classic usage of sysctl looks like the following sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, u_int newlen) System controls, in this form, are based on the MIB, or Management Information Base architecture. A MIB is a list of objects and identifiers for those objects. Each object identifier, or OID, is a list of integers that represent a tokenization of a path through the sysctl tree. For example, if the hw class of sysctl is number 3, the first integer in the OID would be the number 3. If the l2cr option is built into the system and assigned the number 75, then the second integer in the OID would be 75. To put it another way, each number in the OID is an index into a node’s list of children. Here is a short example of a call to get the bus speed of the current computer: int get_bus_speed() { int mib[2], busspeed, retval; unsigned int miblen; size_t len; mib[0]=CTL_HW; mib[1]=HW_BUS_FREQ; miblen=2; len=4; retval=sysctl(mib, miblen, &busspeed, &len, NULL, 0); Boundary Crossings BSD sysctl API 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 124/* Check retval here */ return busspeed; } For more information on the sysctl system call, see the manual page sysctl. Memory Mapping and Block Copying Memory mapping is one of the more common means of communicating between two applications or between an application and the kernel. While occasionally used by itself, it is usually used in conjunction with one of the other means of boundary crossing. One way of using memory mapping is known as shared memory. In this form, one or more pages of memory are mapped into the address space of two processes. Either process can then access or modify the data stored in those shared pages. This is useful when moving large quantities of data between processes, as it allows direct communication without multiple user-kernel boundary crossings. Thus, when moving large amounts of data between processes, this is preferable to traditional message passing. The same holds true with memory mapping between an application and the kernel. The BSD sysctl and syscall interfaces (and to an extent, Mach IPC) were designed to transfer small units of data of known size, such as an array of four integers. In this regard, they are much like a traditional C function call. If you need to pass a large amount of data to a function in C, you should pass a pointer. This is also true when passing data between an application and the kernel, with the addition of memory mapping or copying to allow that pointer to be dereferenced in the kernel. There are a number of limitations to the way that memory mapping can be used to exchange data between an application and the kernel. For one, memory allocated in the kernel cannot be written to by applications, including those running as root (unless the kernel is running in an insecure mode, such as single user mode). For this reason, if a buffer must be modified by an application, the buffer must be allocated by that program, not by the kernel. When you use memory mapping for passing data to the kernel, the application allocates a block of memory and fillsit with data. It then performs a system call that passesthe addressto the appropriate function in kernel space. It should be noted, however, that the address being passed is a virtual address, not a physical address, and more importantly, it is relative to the address space of the program, which is not the same as the address space of the kernel. Since the address is a user-space virtual address, the kernel must call special functions to copy the block of memory into a kernel buffer or to map the block of memory into the kernel’s address space. Boundary Crossings Memory Mapping and Block Copying 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 125In the OS X kernel, data is most easily copied into kernel space with the BSD copyin function, and back out to user space with the copyout function. For large blocks of data, entire pages will be memory mapped using copy-on-write. For this reason, it is generally not useful to do memory mapping by hand. Getting data from the kernel to an application can be done in a number of ways. The most common method is the reverse of the above, in which the application passes in a buffer pointer, the kernel scribbles on a chunk of data, uses copyout to copy the buffer data into the address space of the application, and returns KERN_SUCCESS. Note that this is really using the buffer allocated in the application, even though the physical memory may have actually been allocated by the kernel. Assuming the kernel frees its reference to the buffer, no memory is wasted. A special case of memory mapping occurs when doing I/O to a device from user space. Since I/O operations can, in some cases, be performed by DMA hardware that operates based on physical addressing, it is vital that the memory associated with I/O buffers not be paged out while the hardware is copying data to or from the buffer. For this reason, when a driver or other kernel entity needs a buffer for I/O, it must take steps to mark it as not pageable. This step is referred to as wiring the pages in memory. Wiring pages into memory can also be helpful where high bandwidth, low latency communication is desired, as it prevents shared buffers from being paged out to disk. In general, however, this sort of workaround should be unnecessary, and is considered to be bad programming practice. Pages can be wired in two ways. When a memory region is allocated, it may be allocated in a nonpageable fashion. The details of allocating memory for I/O differ, depending on what part of the kernel you are modifying. This is described in more detail in the appropriate sections of this document, or in the case of the I/O Kit, in the API reference documentation (available from the developer section of Apple’s web site). Alternately, individual pages may be wired after allocation. The recommended way to do this is through a call to vm_wire in BSD parts of the kernel, with mlock from applications (but only by processes running as root), or with IOMemoryDescriptor::prepare in the I/O Kit. Because this can fail for a number of reasons, it is particularly crucial to check return values when wiring memory. The vm_wire call and other virtual memory topics are discussed in more detail in “Memory and Virtual Memory” (page 61). The IOMemoryDescriptor class is described in more detail in the I/O Kit API reference available from the developer section of Apple’s web site. Boundary Crossings Memory Mapping and Block Copying 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 126Summary Crossing the user-kernel boundary is not a trivial task. Many mechanisms exist for this communication, and each one has specific advantages and disadvantages, depending on the environment and bandwidth requirements. Security is a constant concern to prevent inadvertently allowing one program to access data or files from another program or user. It is every kernel programmer’s personal responsibility to take security into account any time that data crosses the user-kernel boundary. Boundary Crossings Summary 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 127This chapter is not intended as an introduction to synchronization. It is assumed that you have some understanding of the basic concepts of locks and semaphores already. If you need additional background reading,synchronization is covered in most introductory operating systemstexts. However,since synchronization in the kernel is somewhat different from locking in an application this chapter does provide a brief overview to help ease the transition, or for experienced kernel developers, to refresh your memory. As an OS X kernel programmer, you have many choices of synchronization mechanisms at your disposal. The kernel itself provides two such mechanisms: locks and semaphores. A lock is used for basic protection of shared resources. Multiple threads can attempt to acquire a lock, but only one thread can actually hold it at any given time (at least for traditional locks—more on this later). While that thread holds the lock, the other threads must wait. There are several different types of locks, differing mainly in what threads do while waiting to acquire them. A semaphore is much like a lock, except that a finite number of threads can hold itsimultaneously. Semaphores can be thought of as being much like piles of tokens. Multiple threads can take these tokens, but when there are none left, a thread must wait until another thread returns one. It is important to note that semaphores can be implemented in many different ways,so Mach semaphores may not behave in the same way assemaphores on other platforms. In addition to locks and semaphores, certain low-level synchronization primitives like test and set are also available, along with a number of other atomic operations. These additional operations are described in libkern/gen/OSAtomicOperations.c in the kernelsources. Such atomic operations may be helpful if you do not need something asrobust as a full-fledged lock orsemaphore. Since they are not generalsynchronization mechanisms, however, they are beyond the scope of this chapter. Semaphores Semaphores and locks are similar, except that with semaphores, more than one thread can be doing a given operation at once. Semaphores are commonly used when protecting multiple indistinct resources. For example, you might use a semaphore to prevent a queue from overflowing its bounds. OS X uses traditional counting semaphores rather than binary semaphores (which are essentially locks). Mach semaphores obey Mesa semantics—that is, when a thread is awakened by a semaphore becoming available, it is not executed immediately. This presents the potential for starvation in multiprocessor situations when the 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 128 Synchronization Primitivessystem is under low overall load because other threads could keep downing the semaphore before the just-woken thread gets a chance to run. This is something that you should consider carefully when writing applications with semaphores. Semaphores can be used any place where mutexes can occur. This precludes their use in interrupt handlers or within the context of the scheduler, and makes it strongly discouraged in the VM system. The public API for semaphores is divided between the MIG–generated task.h file (located in your build output directory, included with #include ) and osfmk/mach/semaphore.h (included with #include ). The public semaphore API includes the following functions: kern_return_t semaphore_create(task_t task, semaphore_t *semaphore, int policy, int value) kern_return_t semaphore_signal(semaphore_t semaphore) kern_return_t semaphore_signal_all(semaphore_t semaphore) kern_return_t semaphore_wait(semaphore_t semaphore) kern_return_t semaphore_destroy(task_t task, semaphore_t semaphore) kern_return_t semaphore_signal_thread(semaphore_t semaphore, thread_act_t thread_act) which are described in or xnu/osfmk/mach/semaphore.h (except for create and destroy, which are described in . The use of these functions is relatively straightforward with the exception of the semaphore_create, semaphore_destroy, and semaphore_signal_thread calls. The value and semaphore parametersfor semaphore_create are exactly what you would expect—a pointer to the semaphore structure to be filled out and the initial value for the semaphore, respectively. The task parameter refers to the primary Mach task that will “own” the lock. This task should be the one that is ultimately responsible for the subsequent destruction of the semaphore. The task parameter used when calling semaphore_destroy must match the one used when it was created. For communication within the kernel, the task parameter should be the result of a call to current_task. For synchronization with a user process, you need to determine the underlying Mach task for that process by calling current_task on the kernel side and mach_task_self on the application side. task_t current_task(void); // returns the kernel task port task_t mach_task_self(void);// returns the task port of the current thread Synchronization Primitives Semaphores 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 129Note: In the kernel, be sure to always use current_task. In the kernel, mach_task_self returns a pointer to the kernel’s VM map, which is probably not what you want. The details of user-kernel synchronization are beyond the scope of this document. The policy parameter is passed asthe policy for the wait queue contained within the semaphore. The possible values are defined in osfmk/mach/sync_policy.h. Current possible values are: ● SYNC_POLICY_FIFO ● SYNC_POLICY_FIXED_PRIORITY ● SYNC_POLICY_PREPOST The FIFO policy is, asthe name suggests, first-in-first-out. The fixed priority policy causes wait queue reordering based on fixed thread priority policies. The prepost policy causes the semaphore_signal function to not increment the counter if no threads are waiting on the queue. This policy is needed for creating condition variables (where a thread is expected to always wait until signalled). See the section “Wait Queues and Wait Primitives” (page 87) for more information. The semaphore_signal_thread call takes a particular thread from the wait queue and places it back into one of the scheduler’s wait-queues, thus making that thread available to be scheduled for execution. If thread_act is NULL, the first thread in the queue is similarly made runnable. With the exception of semaphore_create and semaphore_destroy, these functions can also be called from user space via RPC. See “Calling RPC From User Applications” (page 116) for more information. Condition Variables The BSD portion of OS X provides msleep, wakeup, and wakeup_one, which are equivalent to condition variables with the addition of an optional time-out. You can find these functions in sys/proc.h in the Kernel framework headers. msleep(void *channel, lck_mtx_t *mtx, int priority, const char *wmesg, struct timespec *timeout); msleep0(vvoid *channel, lck_mtx_t *mtx, int priority, const char *wmesg, uint64_t deadline); wakeup(void *channel); wakeup_one(void *channel); Synchronization Primitives Condition Variables 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 130The msleep call is similar to a condition variable. It puts a thread to sleep until wakeup or wakeup_one is called on that channel. Unlike a condition variable, however, you can set a timeout measured in clock ticks. This means that it is both a synchronization call and a delay. The prototypes follow: msleep(void *channel, lck_mtx_t *mtx, int priority, const char *wmesg, struct timespec *timeout); msleep0(vvoid *channel, lck_mtx_t *mtx, int priority, const char *wmesg, uint64_t deadline); wakeup(void *channel); wakeup_one(void *channel); The three sleep calls are similar except in the mechanism used for timeouts. The function msleep0 is not recommended for general use. In these functions, channel is a unique identifier representing a single condition upon which you are waiting. Normally, when msleep is used, you are waiting for a change to occur in a data structure. In such cases, it is common to use the address of that data structure as the value for channel, as this ensures that no code elsewhere in the system will be using the same value. The priority argument has three effects. First, when wakeup is called, threads are inserted in the scheduling queue at this priority. Second, if the bit (priority & PCATCH) is set, msleep0 does not allow signals to interrupt the sleep. Third, if the bit (priority & PDROP) is zero, msleep0 drops the mutex on sleep and reacquires it upon waking. If (priority & PDROP) is one, msleep0 drops the mutex if it has to sleep, but does not reacquire it. The subsystem argument is a short text string that represents the subsystem that is waiting on this channel. This is used solely for debugging purposes. The timeout argument is used to set a maximum wait time. The thread may wake sooner, however, if wakeup or wakeup_one is called on the appropriate channel. It may also wake sooner if a signal isreceived, depending on the value of priority. In the case of msleep0, this is given as a mach abstime deadline. In the case of msleep, this is given in relative time (seconds and nanoseconds). Outside the BSD portion of the kernel, condition variables may be implemented using semaphores. Synchronization Primitives Condition Variables 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 131Locks OS X (and Mach in general) has three basic types of locks: spinlocks, mutexes, and read-write locks. Each of these has different uses and different problems. There are also many other types of locks that are not implemented in OS X, such as spin-sleep locks, some of which may be useful to implement for performance comparison purposes. Spinlocks A spinlock is the simplest type of lock. In a system with a test-and-set instruction or the equivalent, the code looks something like this: while (test_and_set(bit) != 0); In other words, until the lock is available, it simply “spins” in a tight loop that keeps checking the lock until the thread’s time quantum expires and the next thread begins to execute. Since the entire time quantum for the first thread must complete before the next thread can execute and (possibly) release the lock, a spinlock is very wasteful of CPU time, and should be used only in places where a mutex cannot be used, such as in a hardware exception handler or low-level interrupt handler. Note that a thread may not block while holding a spinlock, because that could cause deadlock. Further, preemption is disabled on a given processor while a spinlock is held. There are three basic types of spinlocks available in OS X: lck_spin_t (which supersedes simple_lock_t), usimple_lock_t, and hw_lock_t. You are strongly encouraged to not use hw_lock_t; it is only mentioned for the sake of completeness. Of these, only lck_spin_t is accessible from kernel extensions. The u in usimple stands for uniprocessor, because they are the only spinlocks that provide actual locking on uniprocessorsystems. Traditionalsimple locks, by contrast, disable preemption but do notspin on uniprocessor systems. Note that in most contexts, it is not useful to spin on a uniprocessor system, and thus you usually only need simple locks. Use of usimple locks is permissible for synchronization between thread context and interrupt context or between a uniprocessor and an intelligent device. However, in most cases, a mutex is a better choice. Important: Simple and usimple locks that could potentially be shared between interrupt context and thread context must have their use coordinated with spl (see glossary). The IPL (interrupt priority level) must always be the same when acquiring the lock, otherwise deadlock may result. (This is not an issue for kernel extensions, however, as the spl functions cannot be used there.) The spinlock functions accessible to kernel extensions consist of the following: Synchronization Primitives Locks 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 132extern lck_spin_t *lck_spin_alloc_init( lck_grp_t *grp, lck_attr_t *attr); extern void lck_spin_init( lck_spin_t *lck, lck_grp_t *grp, lck_attr_t *attr); extern void lck_spin_lock( lck_spin_t *lck); extern void lck_spin_unlock( lck_spin_t *lck); extern void lck_spin_destroy( lck_spin_t *lck, lck_grp_t *grp); extern void lck_spin_free( lck_spin_t *lck, lck_grp_t *grp); extern wait_result_t lck_spin_sleep( lck_spin_t *lck, lck_sleep_action_t lck_sleep_action, event_t event, wait_interrupt_t interruptible); extern wait_result_t lck_spin_sleep_deadline( lck_spin_t *lck, lck_sleep_action_t lck_sleep_action, event_t event, wait_interrupt_t interruptible, uint64_t deadline); Synchronization Primitives Locks 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 133Prototypes for these locks can be found in . The arguments to these functions are described in detail in “Using Lock Functions” (page 139). Mutexes A mutex, mutex lock, or sleep lock, is similar to a spinlock, except that instead of constantly polling, it places itself on a queue of threads waiting for the lock, then yields the remainder of its time quantum. It does not execute again until the thread holding the lock wakesit (or in some userspace variations, until an asynchronous signal arrives). Mutexes are more efficient than spinlocksfor most purposes. However, they are less efficient in multiprocessing environments where the expected lock-holding time is relatively short. If the average time is relatively short but occasionally long, spin/sleep locks may be a better choice. Although OS X does not support spin/sleep locksin the kernel, they can be easily implemented on top of existing locking primitives. If your code performance improves as a result of using such locks, however, you should probably look for ways to restructure your code, such as using more than one lock or moving to read-write locks, depending on the nature of the code in question. See “Spin/Sleep Locks” (page 138) for more information. Because mutexes are based on blocking, they can only be used in places where blocking is allowed. For this reason, mutexes cannot be used in the context of interrupt handlers. Interrupt handlers are not allowed to block because interrupts are disabled for the duration of an interrupt handler, and thus, if an interrupt handler blocked, it would prevent the scheduler from receiving timer interrupts, which would prevent any other thread from executing, resulting in deadlock. For a similar reason, it is not reasonable to block within the scheduler. Also, blocking within the VM system can easily lead to deadlock if the lock you are waiting for is held by a task that is paged out. However, unlike simple locks, it is permissible to block while holding a mutex. This would occur, for example, if you took one lock, then tried to take another, but the second lock was being held by another thread. However, this is generally not recommended unless you carefully scrutinize all uses of that mutex for possible circular waits, as it can result in deadlock. You can avoid this by always taking locks in a certain order. In general, blocking while holding a mutex specific to your code isfine aslong as you wrote your code correctly, but blocking while holding a more global mutex is probably not, since you may not be able to guarantee that other developers’ code obeys the same ordering rules. A Mach mutex is of type mutex_t. The functions that operate on mutexes include: lck_mtx_t *lck_mtx_alloc_init(lck_grp_t *grp, lck_attr_t *attr); extern void lck_mtx_init( lck_mtx_t *lck, Synchronization Primitives Locks 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 134lck_grp_t *grp, lck_attr_t *attr); extern void lck_mtx_lock( lck_mtx_t *lck); extern void lck_mtx_unlock( lck_mtx_t *lck); extern void lck_mtx_destroy(lck_mtx_t *lck, lck_grp_t *grp); extern void lck_mtx_free( lck_mtx_t *lck, lck_grp_t *grp); extern wait_result_tlck_mtx_sleep( lck_mtx_t *lck, lck_sleep_action_t lck_sleep_action, event_t event, wait_interrupt_t interruptible); extern wait_result_tlck_mtx_sleep_deadline( lck_mtx_t *lck, lck_sleep_action_t lck_sleep_action, event_t event, wait_interrupt_t interruptible, uint64_t deadline); extern void lck_mtx_assert( lck_mtx_t *lck, unsigned int type); as described in . The arguments to these functions are described in detail in “Using Lock Functions” (page 139). Synchronization Primitives Locks 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 135Read-Write Locks Read-write locks (also called shared-exclusive locks) are somewhat different from traditional locks in that they are not always exclusive locks. A read-write lock is useful when shared data can be reasonably read concurrently by multiple threads except while a thread is modifying the data. Read-write locks can dramatically improve performance if the majority of operations on the shared data are in the form of reads(since it allows concurrency), while having negligible impact in the case of multiple writes. A read-write lock allows this sharing by enforcing the following constraints: ● Multiple readers can hold the lock at any time. ● Only one writer can hold the lock at any given time. ● A writer must block until all readers have released the lock before obtaining the lock for writing. ● Readers arriving while a writer is waiting to acquire the lock will block until after the writer has obtained and released the lock. The first constraint allows read sharing. The second constraint prevents write sharing. The third prevents read-write sharing, and the fourth prevents starvation of the writer by a steady stream of incoming readers. Mach read-write locks also provide the ability for a reader to become a writer and vice-versa. In locking terminology, an upgrade is when a reader becomes a writer, and a downgrade is when a writer becomes a reader. To prevent deadlock, some additional constraints must be added for upgrades and downgrades: ● Upgrades are favored over writers. ● The second and subsequent concurrent upgrades will fail, causing that thread’s read lock to be released. The first constraint is necessary because the reader requesting an upgrade is holding a read lock, and the writer would not be able to obtain a write lock until the reader releases its read lock. In this case, the reader and writer would wait for each other forever. The second constraint is necessary to prevents the deadlock that would occur if two readers wait for the other to release its read lock so that an upgrade can occur. The functions that operate on read-write locks are: extern lck_rw_t *lck_rw_alloc_init( lck_grp_t *grp, lck_attr_t *attr); extern void lck_rw_init( lck_rw_t *lck, lck_grp_t *grp, Synchronization Primitives Locks 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 136lck_attr_t *attr); extern void lck_rw_lock( lck_rw_t *lck, lck_rw_type_t lck_rw_type); extern void lck_rw_unlock( lck_rw_t *lck, lck_rw_type_t lck_rw_type); extern void lck_rw_lock_shared( lck_rw_t *lck); extern void lck_rw_unlock_shared( lck_rw_t *lck); extern void lck_rw_lock_exclusive( lck_rw_t *lck); extern void lck_rw_unlock_exclusive( lck_rw_t *lck); extern void lck_rw_destroy( lck_rw_t *lck, lck_grp_t *grp); extern void lck_rw_free( lck_rw_t *lck, lck_grp_t *grp); extern wait_result_t lck_rw_sleep( lck_rw_t *lck, lck_sleep_action_t lck_sleep_action, Synchronization Primitives Locks 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 137event_t event, wait_interrupt_t interruptible); extern wait_result_t lck_rw_sleep_deadline( lck_rw_t *lck, lck_sleep_action_t lck_sleep_action, event_t event, wait_interrupt_t interruptible, uint64_t deadline); This is a more complex interface than that of the other locking mechanisms, and actually is the interface upon which the other locks are built. The functions lck_rw_lock and lck_rw_lock lock and unlock a lock as either shared (read) or exclusive (write), depending on the value of lck_rw_type., which can contain either LCK_RW_TYPE_SHARED or LCK_RW_TYPE_EXCLUSIVE. You should always be careful when using these functions, as unlocking a lock held in shared mode using an exclusive call or vice-versa will lead to undefined results. The arguments to these functions are described in detail in “Using Lock Functions” (page 139). Spin/Sleep Locks Spin/sleep locks are not implemented in the OS X kernel. However, they can be easily implemented on top of existing locks if desired. For short waits on multiprocessor systems, the amount of time spent in the context switch can be greater than the amount of time spent spinning. When the time spent spinning while waiting for the lock becomes greater than the context switch overhead, however, mutexes become more efficient. For this reason, if there is a large degree of variation in wait time on a highly contended lock, spin/sleep locks may be more efficient than traditional spinlocks or mutexes. Ideally, a program should be written in such a way that the time spent holding a lock is always about the same, and the choice of locking is clear. However, in some cases, this is not practical for a highly contended lock. In those cases, you may consider using spin/sleep locks. Synchronization Primitives Locks 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 138The basic principle ofspin/sleep locksissimple. A thread takesthe lock if it is available. If the lock is not available, the thread may enter a spin cycle. After a certain period of time (usually a fraction of a time quantum or a small number of time quanta), the spin routine’s time-out is reached, and it returns failure. At that point, the lock places the waiting thread on a queue and puts it to sleep. In other variations on this design, spin/sleep locks determine whether to spin or sleep according to whether the lock-holding thread is currently on another processor (or is about to be). For short wait periods on multiprocessor computers, the spin/sleep lock is more efficient than a mutex, and roughly as efficient as a standard spinlock. For longer wait periods, the spin/sleep lock is significantly more efficient than the spinlock and only slightly less efficient than a mutex. There is a period near the transition between spinning and sleeping in which the spin/sleep lock may behave significantly worse than either of the basic lock types, however. Thus, spin/sleep locks should not be used unless a lock is heavily contended and has widely varying hold times. When possible, you should rewrite the code to avoid such designs. Using Lock Functions While most of the locking functions are straightforward, there are a few detailsrelated to allocating, deallocating, and sleeping on locks that require additional explanation. As the syntax of these functions is identical across all of the lock types, this section explains only the usage for spinlocks. Extending this to other lock types is left as a (trivial) exercise for the reader. The first thing you must do when allocating locks is to allocate a lock group and a lock attribute set. Lock groups are used to name locks for debugging purposes and to group locks by function for general understandability. Lock attribute sets allow you to set flags that alter the behavior of a lock. The following code illustrates how to allocate an attribute structure and a lock group structure for a lock. In this case, a spinlock is used, but with the exception of the lock allocation itself, the process is the same for other lock types. Listing 17-1 Allocating lock attributes and groups (lifted liberally from kern_time.c) lck_grp_attr_t *tz_slock_grp_attr; lck_grp_t *tz_slock_grp; lck_attr_t *tz_slock_attr; lck_spin_t *tz_slock; /* allocate lock group attribute and group */ tz_slock_grp_attr = lck_grp_attr_alloc_init(); lck_grp_attr_setstat(tz_slock_grp_attr); Synchronization Primitives Locks 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 139tz_slock_grp = lck_grp_alloc_init("tzlock", tz_slock_grp_attr); /* Allocate lock attribute */ tz_slock_attr = lck_attr_alloc_init(); //lck_attr_setdebug(tz_slock_attr); // set the debug flag //lck_attr_setdefault(tz_slock_attr); // clear the debug flag /* Allocate the spin lock */ tz_slock = lck_spin_alloc_init(tz_slock_grp, tz_slock_attr); The first argument to the lock initializer, of type lck_grp_t, is a lock group. This is used for debugging purposes, including lock contention profiling. The details of lock tracing are beyond the scope of this document, however, every lock must belong to a group (even if that group contains only one lock). The second argument to the lock initializer, of type lck_attr_t, contains attributes for the lock. Currently, the only attribute available islock debugging. This attribute can be set using lck_attr_setdebug and cleared with lck_attr_setdefault. To dispose of a lock, you simply call the matching free functions. For example: lck_spin_free(tz_slock, tz_slock_grp); lck_attr_free(tz_slock_attr); lck_grp_free(tz_slock_grp); lck_grp_attr_free(tz_slock_grp_attr); Note: While you can safely dispose of the lock attribute and lock group attribute structures, it is important to keep track of the lock group associated with a lock as long as the lock exists, since you will need to pass the group to the lock's matching free function when you deallocate the lock (generally at unload time). The other two interesting functions are lck_spin_sleep and lck_spin_sleep_deadline. These functions release a spinlock and sleep until an event occurs, then wake. The latter includes a timeout, at which point it will wake even if the event has not occurred. extern wait_result_t lck_spin_sleep( lck_rspin_t *lck, Synchronization Primitives Locks 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 140lck_sleep_action_t lck_sleep_action, event_t event, wait_interrupt_t interruptible); extern wait_result_t lck_spin_sleep_deadline( lck_spin_t *lck, lck_sleep_action_t lck_sleep_action, event_t event, wait_interrupt_t interruptible, uint64_t deadline); The parameter lck_sleep_action controls whether the lock will be reclaimed after sleeping prior to this function returning. The valid options are: LCK_SLEEP_DEFAULT Release the lock while waiting for the event, then reclaim it. Read-write locks are held in the same mode as they were originally held. LCK_SLEEP_UNLOCK Release the lock and return with the lock unheld. LCK_SLEEP_SHARED Reclaim the lock in shared mode (read-write locks only). LCK_SLEEP_EXCLUSIVE Reclaim the lock in exclusive mode (read-write locks only). The event parameter can be any arbitrary integer, but it must be unique across the system. To ensure uniqueness, a common programming practice isto use the address of a global variable (often the one containing a lock) as the event value. For more information on these events, see “Event and Timer Waits” (page 143). The parameter interruptible indicates whether the scheduler should allow the wait to be interrupted by asynchronous signals. If this is false, any false wakes will result in the process going immediately back to sleep (with the exception of a timer expiration signal, which will still wake lck_spin_sleep_deadline). Synchronization Primitives Locks 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 141This chapter containsinformation about miscellaneousservices provided by the OS X kernel. For most projects, you will probably never need to use most of these services, but if you do, you will find it hard to do without them. This chapter containsthese sections:“Using Kernel Time Abstractions” (page 142),“Boot Option Handling” (page 146), “Queues” (page 147), and “Installing Shutdown Hooks” (page 148). Using Kernel Time Abstractions There are two basic groups of time abstractionsin the kernel. One group includesfunctionsthat provide delays and timed wake-ups. The other group includesfunctions and variablesthat provide the current wall clock time, the time used by a given process, and other similar information. This section describes both aspects of time from the perspective of the kernel. Obtaining Time Information There are a number of ways to get basic time information from within the kernel. The officially approved methods are those that Mach exports in kern/clock.h. These include the following: void clock_get_uptime(uint64_t *result); void clock_get_system_microtime( uint32_t *secs, uint32_t *microsecs); void clock_get_system_nanotime( uint32_t *secs, uint32_t *nanosecs); void clock_get_calendar_microtime( uint32_t *secs, uint32_t *microsecs); void clock_get_calendar_nanotime( uint32_t *secs, uint32_t *nanosecs); 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 142 Miscellaneous Kernel ServicesThe function clock_get_uptime returns a value in AbsoluteTime units. For more information on using AbsoluteTime, see “Using Mach Absolute Time Functions” (page 144). The functions clock_get_system_microtime and clock_get_system_nanotime return 32-bit integers containing seconds and microseconds or nanoseconds, respectively, representing the system uptime. The functions clock_get_calendar_microtime and clock_get_calendar_nanotime return 32-bit integers containing seconds and microseconds or nanoseconds, respectively, representing the current calendar date and time since the epoch (January 1, 1970). In some parts of the kernel, you may find other functions that return type mach_timespec_t. This type is similar to the traditional BSD struct timespec, except that fractions of a second are measured in nanoseconds instead of microseconds: struct mach_timespec { unsigned int tv_sec; clock_res_t tv_nsec; }; typedef struct mach_timespec *mach_timespec_t; In addition to the traditional Mach functions, if you are writing code in BSD portions of the kernel you can also get the current calendar (wall clock) time as a BSD timeval, as well as find out the calendar time when the system was booted by doing the following: #include struct timeval tv=time; /* calendar time */ struct timeval tv_boot=boottime; /* calendar time when booting occurred */ For other information, you should use the Mach functions listed previously. Event and Timer Waits Each part of the OS X kernel has a distinct API for waiting a certain period of time. In most cases, you can call these functions from other parts of the kernel. The I/O Kit provides IODelay and IOSleep. Mach provides functions based on AbsoluteTime, as well as a few based on microseconds. BSD provides msleep. Miscellaneous Kernel Services Using Kernel Time Abstractions 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 143Using IODelay and IOSleep IODelay, provided by the I/O Kit, abstracts a timed spin. If you are delaying for a short period of time, and if you need to be guaranteed that your wait will not be stopped prematurely by delivery of asynchronous events, this is probably the best choice. If you need to delay for several seconds, however, this is a bad choice, because the CPU that executes the wait will spin until the time has elapsed, unable to handle any other processing. IOSleep puts the currently executing thread to sleep for a certain period of time. There is no guarantee that your thread will execute after that period of time, nor isthere a guarantee that your thread will not be awakened by some other event before the time has expired. It is roughly equivalent to the sleep call from user space in this regard. The use of IODelay and IOSleep are straightforward. Their prototypes are: IODelay(unsigned microseconds); IOSleep(unsigned milliseconds); Note the differing units. It is not practical to put a thread to sleep for periods measured in microseconds, and spinning for several milliseconds is also inappropriate. Using Mach Absolute Time Functions The following Mach time functions are commonly used. Several others are described in osfmk/kern/clock.h. Note: These are not the same functions as those listed in kern/clock.h in the Kernel framework. These functions are not exposed to kernel extensions, and are only for use within the kernel itself. void delay(uint64_t microseconds); void clock_delay_until(uint64_t deadline); void clock_absolutetime_interval_to_deadline(uint64_t abstime, uint64_t *result); void nanoseconds_to_absolutetime(uint64_t nanoseconds, uint64_t *result); void absolutetime_to_nanoseconds(uint64_t abstime, uint64_t *result); These functions are generally straightforward. However, a few points deserve explanation. Unless specifically stated, all times, deadlines, and so on, are measured in abstime units. The abstime unit is equal to the length of one bus cycle,so the duration is dependent on the busspeed of the computer. For thisreason, Mach provides conversion routines between abstime units and nanoseconds. Miscellaneous Kernel Services Using Kernel Time Abstractions 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 144Many time functions, however, provide time in seconds with nanosecond remainder. In this case, some conversion is necessary. For example, to obtain the current time as a mach abstime value, you might do the following: uint32_t secpart; uint32_t nsecpart; uint64_t nsec, abstime; clock_get_calendar_nanotime(&secpart, &nsecpart); nsec = nsecpart + (1000000000ULL * secpart); //convert seconds to nanoseconds. nanoseconds_to_absolutetime(nsec, &abstime); The abstime value is now stored in the variable abstime. Using msleep In addition to Mach and I/O Kit routines, BSD provides msleep, which is the recommended way to delay in the BSD portions of the kernel. In other parts of the kernel, you should either use wait_queue functions or use assert_wait and thread_wakeup functions, both of which are closely tied to the Mach scheduler, and are described in “Kernel Thread APIs” (page 85). Because this function is more commonly used for waiting on events, it is described further in “Condition Variables” (page 130). Handling Version Dependencies Many time-related functions such as clock_get_uptime changed as a result of the transition to KPIs in OS X v.10.4. While these changes result in a cleaner interface, this can prove challenging if you need to make a kernel extension that needs to obtain time information across multiple versions of OS X in a kernel extension that would otherwise have no version dependencies (such as an I/O Kit KEXT). Here is a list of time-related functions that are available in both pre-KPI and KPI versions of OS X: uint64_t mach_absolute_time(void); Declared In: Dependency: com.apple.kernel.mach This function returns a Mach absolute time value for the current wall clock time in units of uint64_t. Miscellaneous Kernel Services Using Kernel Time Abstractions 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 145void microtime(struct timeval *tv); Declared In: Dependency: com.apple.kernel.bsd This function returns a timeval struct containing the current wall clock time. void microuptime(struct timeval *tv); Declared In: Dependency: com.apple.kernel.bsd This function returns a timeval struct containing the current uptime. void nanotime(struct timespec *ts); Declared In: Dependency: com.apple.kernel.bsd This function returns a timespec struct containing the current wall clock time. void nanouptime(struct timespec *ts); Declared In: Dependency: com.apple.kernel.bsd This function returns a timespec struct containing the current uptime. Note: The structure declarationsfor struct timeval and struct timespec differ between 10.3 and 10.4 in their use of int, int32_t, and long data types. However, because the structure packing for the underlying data types is identical in the 32-bit world, these structures are assignment compatible. In addition to these APIs, the functionality marked __APPLE_API_UNSTABLE in was adopted as-is in OS X v.10.4 and is no longer marked unstable. Boot Option Handling OS X provides a simple parse routine, PE_parse_boot_arg, for basic boot argument passing. It supports both flags and numerical value assignment. For obtaining values, you write code similar to the following: unsigned int argval; if (PE_parse_boot_arg("argflag", &argval)) { Miscellaneous Kernel Services Boot Option Handling 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 146/* check for reasonable value */ if (argval < 10 || argval > 37) argval = 37; } else { /* use default value */ argval = 37; } Since PE_parse_boot_arg returns a nonzero value if the flag exists, you can check for the presence of a flag by using a flag that starts with a dash (-) and ignoring the value stored in argvalue. The PE_parse_boot_arg function can also be used to get a string argument. To do this, you must pass in the address of an array of type char as the second argument. The behavior of PE_parse_boot_arg is undefined if a string is passed in for a numeric variable or vice versa. Its behavior is also undefined if a string exceeds the storage space allocated. Be sure to allow enough space for the largest reasonable string including a null delimiter. No attempt is made at bounds checking, since an overflow is generally a fatal error and should reasonably prevent booting. Queues As part of its BSD infrastructure, the OS X kernel provides a number of basic support macrosto simplify handling of linked lists and queues. These are implemented as C macros, and assume a standard C struct. As such, they are probably not suited for writing code in C++. The basic types of lists and queues included are ● SLIST, a singly linked list ● STAILQ, a singly linked tail queue ● LIST, a doubly linked list ● TAILQ, a doubly linked tail queue SLIST is ideal for creating stacks or for handling large sets of data with few or no removals. Arbitrary removal, however, requires an O(n) traversal of the list. STAILQ is similar to SLIST except that it maintains pointers to both ends of the queue. This makes it ideal for simple FIFO queues by adding entries at the tail and fetching entries from the head. Like SLIST, it is inefficient to remove arbitrary elements. Miscellaneous Kernel Services Queues 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 147LIST is a doubly linked version of SLIST. The extra pointersrequire additionalspace, but allow O(1) (constant time) removal of arbitrary elements and bidirectional traversal. TAILQ is a doubly linked version of STAILQ. Like LIST, the extra pointers require additional space, but allow O(1) (constant time) removal of arbitrary elements and bidirectional traversal. Because their functionality is relatively simple, their use is equally straightforward. These macros can be found in xnu/bsd/sys/queue.h. Installing Shutdown Hooks Although OS X does not have traditional BSD-style shutdown hooks, the I/O Kit provides equivalent functionality in recent versions. Since the I/O Kit provides this functionality, you must call it from C++ code. To register for notification, you call registerSleepWakeInterest (described in IOKit/RootDomain.h) and register for sleep notification. If the system is about to be shut down, your handler is called with the message type kIOMessageSystemWillPowerOff. If the system is about to reboot, your handler gets the message type kIOMessageSystemWillRestart. If the system is about to reboot, your handler gets the message type kIOMessageSystemWillSleep. If you no longer need to receive notification (for example, if your KEXT gets unloaded), be certain to release the notifier with IONofitier::release to avoid a kernel panic on shutdown. For example, the following sample KEXT registersforsleep notifications, then logs a message with IOLog when a sleep notification occurs: #include #include #include #include #include #define ALLOW_SLEEP 1 IONotifier *notifier; extern "C" { Miscellaneous Kernel Services Installing Shutdown Hooks 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 148IOReturn mySleepHandler( void * target, void * refCon, UInt32 messageType, IOService * provider, void * messageArgument, vm_size_t argSize ) { IOLog("Got sleep/wake notice. Message type was %d\n", messageType); #if ALLOW_SLEEP acknowledgeSleepWakeNotification(refCon); #else vetoSleepWakeNotification(refCon); #endif return 0; } kern_return_t sleepkext_start (kmod_info_t * ki, void * d) { void *myself = NULL; // Would pass the self pointer here if in a class instance notifier = registerPrioritySleepWakeInterest( &mySleepHandler, myself, NULL); return KERN_SUCCESS; } kern_return_t sleepkext_stop (kmod_info_t * ki, void * d) { notifier->remove(); return KERN_SUCCESS; } } // extern "C" Miscellaneous Kernel Services Installing Shutdown Hooks 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 149As discussed in the chapter “Kernel Architecture Overview” (page 14), OS X provides a kernel extension mechanism as a means of allowing dynamic loading of code into the kernel, without the need to recompile or relink. Because these kernel extensions (KEXTs) provide both modularity and dynamic loadability, they are a natural choice for any relatively self-contained service that requires access to internal kernel interfaces. Because KEXTs run in supervisor mode in the kernel’s address space, they are also harder to write and debug than user-level modules, and must conform to strict guidelines. Further, kernel resources are wired (permanently resident in memory) and are thus more costly to use than resources in a user-space task of equivalent functionality. In addition, although memory protection keeps applications from crashing the system, no such safeguards are in place inside the kernel. A badly behaved kernel extension in OS X can cause as much trouble as a badly behaved application or extension could in Mac OS 9. Bugs in KEXTs can have far more severe consequences than bugs in user-level code. For example, a memory access error in a user application can, at worst, cause that application to crash. In contrast, a memory access error in a KEXT causes a kernel panic, crashing the operating system. Finally, for security reasons, some customers restrict or don’t permit the use of third-party KEXTs. As a result, use of KEXTs is strongly discouraged in situations where user-level solutions are feasible. OS X guarantees that threading in applications is just as efficient as threading inside the kernel, so efficiency should not be an issue. Unless your application requireslow-level accessto kernel interfaces, you should use a higher level of abstraction when developing code for OS X. When you are trying to determine if a piece of code should be a KEXT, the default answer is generally no . Even if your code was a system extension in Mac OS 9, that does not necessarily mean that it should be a kernel extension in OS X. There are only a few good reasons for a developer to write a kernel extension: ● Your code needsto take a primary interrupt—that is,something in the (built-in) hardware needsto interrupt the CPU and execute a handler. ● The primary client of your code is inside the kernel—for example, a block device whose primary client is a file system. ● Your code needs to access kernel interfaces that are not exported to user space. ● Your code has other special requirements that cannot be satisfied in a user space application. 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 150 Kernel Extension OverviewIf your code does not meet any of the above criteria (and possibly even if it does), you should consider developing it as a library or a user-level daemon, or using one of the user-level plug-in architectures (such as QuickTime components or the Core Graphics framework) instead of writing a kernel extension. If you are writing device drivers or code to support a new volume format or networking protocol, however, KEXTs may be the only feasible solution. Fortunately, while KEXTs may be more difficult to write than user-space code, several tools and procedures are available to enhance the development and debugging process. See “Debugging Your KEXT” (page 153) for more information. This chapter provides a conceptual overview of KEXTs and how to create them. If you are interested in building a simple KEXT, see the Apple tutorials listed in the bibliography. These provide step-by-step instructions for creating a simple, generic KEXT or a basic I/O Kit driver. Implementation of a Kernel Extension (KEXT) Kernel extensions are implemented as bundles, folders that the Finder treats as single files. See the chapter about bundles in Mac Technology Overview for a discussion of bundles.The KEXT bundle can contain the following: ● Information property list—a text file that describes the contents, settings, and requirements of the KEXT. This file is required. A KEXT bundle need contain nothing more than this file, although most KEXTs contain one or more kernel modules as well. See the chapter about software configuration in Mac Technology Overview for further information about property lists. ● KEXT binary—a file in Mach-O format, containing the actual binary code used by the KEXT. A KEXT binary (also known as a kernel module or KMOD) represents the minimum unit of code that can be loaded into the kernel. A KEXT usually contains one KEXT binary. If no KEXT binaries are included, the information property list file must contain a reference to another KEXT and change its default settings. ● Resources—for example, icons or localization dictionaries. Resources are optional; they may be useful for a KEXT that needs to display a dialog or menu. At present, no resources are explicitly defined for use with KEXTs. ● KEXT bundles—a kext can contain other KEXTs. This can be used for plug-ins that augment features of a KEXT. Kernel Extension Dependencies Any KEXT can declare that it is dependent upon any other KEXT. The developer lists these dependencies in the OSBundleLibraries dictionary in the module’s property list file. Kernel Extension Overview Implementation of a Kernel Extension (KEXT) 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 151Before a KEXT isloaded, all of itsrequirements are checked. Those required extensions(and their requirements) are loaded first, iterating back through the lists until there are no more required extensions to load. Only after all requirements are met, is the requested KEXT loaded as well. For example, device drivers (a type of KEXT) are dependent upon (require) certain families (another type of KEXT). When a driver isloaded, itsrequired families are also loaded to provide necessary, common functionality. To ensure that all requirements are met, each device drivershould list all of itsrequirements(families and other drivers) in its property list. See the chapter “I/O Kit Overview” (page 94), for an explanation of drivers and families. It is important to list all dependencies for each KEXT. If your KEXT fails to do so, your KEXT may not load due to unrecognized symbols, thusrendering the KEXT useless. Dependenciesin KEXTs can be considered analogous to required header files or librariesin code development; in fact, the Kernel Extension Manager usesthe standard linker to resolve KEXT requirements. Building and Testing Your Extension After creating the necessary property list and C or C++ source files, you use Project Builder to build your KEXT. Any errors in the source code are brought to your attention during the build and you are given the chance to edit your source files and try again. To test your KEXT, however, you need to leave Project Builder and work in the Terminal application (or in console mode). In console mode, all system messages are written directly to your screen, as well as to a log file (/var/log/system.log). If you work in the Terminal application, you must view system messages in the log file or in the Console application.You also need to log in to the root account (or use the su or sudo command), since only the root account can load kernel extensions. When testing your KEXT, you can load and unload it manually, as well as check the load status. You can use the kextload command to load any KEXT. A manual page for kextload is included in OS X. (On OS X prior to 10.2, you must use the kmodload command instead.) Note that this command is useful only when developing a KEXT. Eventually, after it has been tested and debugged, you install your KEXT in one of the standard places (see “Installed KEXTs” (page 154) for details). Then, it will be loaded and unloaded automatically at system startup and shutdown or whenever it is needed (such as when a new device is detected). Kernel Extension Overview Building and Testing Your Extension 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 152Debugging Your KEXT KEXT debugging can be complicated. Before you can debug a KEXT, you must first enable kernel debugging, as OS X is not normally configured to permit debugging the kernel. Only the root account can enable kernel debugging, and you need to reboot OS X for the changes to take effect. (You can use sudo to gain root privileges if you don’t want to enable a root password.) Kernel debugging is performed using two OS X computers, called the development or debug host and the debug target. These computers must be connected over a reliable network connection on the same subnet (or within a single local network). Specifically, there must not be any intervening IP routers or other devices that could make hardware-based Ethernet addressing impossible. The KEXT is registered (and loaded and run) on the target. The debugger is launched and run on the debug host. You can also rebuild your KEXT on the debug host, after you fix any errors you find. Debugging must be performed in this fashion because you must temporarily halt the kernel on the target in order to use the debugger. When you halt the kernel, all other processes on that computer stop. However, a debugger running remotely can continue to run and can continue to examine (or modify) the kernel on the target. Note that bugs in KEXTs may cause the target kernel to freeze or panic. If this happens, you may not be able to continue debugging, even over a remote connection; you have to reboot the target and start over, setting a breakpoint just before the code where the KEXT crashed and working very carefully up to the crash point. Developers generally debug KEXTs using gdb, a source-level debugger with a command-line interface. You will need to work in the Terminal application to run gdb. For detailed information about using gdb, see the documentation included with OS X. You can also use the help command from within gdb. Some features of gdb are unavailable when debugging KEXTs because of implementation limitations. For example: ● You can’t use gdb to call a function or method in a KEXT. ● You should not use gdb to debug interrupt routines. The former is largely a barrier introduced by the C++ language. The latter may work in some cases but is not recommended due to the potential for gdb to interrupt something upon which kdp (the kernel shim used by gdb) depends in order to function properly. Use care that you do not halt the kernel for too long when you are debugging (for example, when you set breakpoints). In a short time, internal inconsistencies can appear that cause the target kernel to panic or freeze, forcing you to reboot the target. Kernel Extension Overview Debugging Your KEXT 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 153Additional information about debugging can be found in “When Things Go Wrong: Debugging the Kernel” (page 161). Installed KEXTs The Kernel Extension Manager (KEXT Manager) is responsible for loading and unloading all installed KEXTs (commands such as kextload are used only during development). Installed KEXTs are dynamically added to the running OS X kernel as part of the kernel’s address space. An installed and enabled KEXT is invoked as needed. Important: Note that KEXTs are only wrappers(bundles) around a property list, KEXT binaries(or references to other KEXTs), and optional resources. The KEXT describes what is to be loaded; it is the KEXT binaries that are actually loaded. KEXTs are usually installed in the folder /System/Libraries/Extensions. The Kernel Extension Manager (in the form of a daemon, kextd), always checks here. KEXTs can also be installed in ROM or inside an application bundle. Installing KEXTs in an application bundle allows an application to register those KEXTs without the need to install them permanently elsewhere within the system hierarchy. This may be more convenient and allows the KEXT to be associated with a specific, running application. When it starts, the application can register the KEXT and, if desired, unregister it on exit. For example, a network packet sniffer application might employ a Network Kernel Extension (NKE). A tape backup application would require that a tape driver be loaded during the duration of the backup process. When the application exits, the kernel extension is no longer needed and can be unloaded. Note that, although the application is responsible for registering the KEXT, this is no guarantee that the corresponding KEXTs are actually ever loaded. It is still up to a kernel component, such as the I/O Kit, to determine a need, such as matching a piece of hardware to a desired driver, thus causing the appropriate KEXTs (and their dependencies) to be loaded. Kernel Extension Overview Installed KEXTs 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 154This chapter is not about building kernel extensions (KEXTs). There are a number of good KEXT tutorials on Apple’s developer documentation site (http://developer.apple.com/documentation). This chapter is about adding new in-kernel modules(optional parts of the kernel), building kernels, and debugging kernel and kernel extension builds. The discussion is divided into three sections. The first, “Adding New Files or Modules” (page 155), describes how to add new functionality into the kernel itself. You should only add files into the kernel when the use of a KEXT is not possible (for example, when adding certain low-level motherboard hardware support). The second section, “Building Your First Kernel” (page 158), describes how to build a kernel, including how to build a kernel with debugger support, how to add new options, and how to obtain sources that are of similar vintage to those in a particular version of OS X or Darwin. The third section, “When Things Go Wrong: Debugging the Kernel” (page 161), tells how to debug a kernel or kernel module using ddb and gdb. This is a must-read for anyone doing kernel development. Adding New Files or Modules In this context, the term module is used loosely to refer to a collection of related files in the kernel that are controlled by a single config option at compile time. It does not refer to loadable modules (KEXTs). This section describes how to add additional files that will be compiled into the kernel, including how to add a new config option for an additional module. Modifying the Configuration Files The details of adding a new file or module into the kernel differ according to what portion of the kernel contains the file. If you are adding a new file or module into the Mach portion of the kernel, you need to list it in various filesin xnu/osfmk/conf. For the BSD portion of the kernel, you should list it in variousfilesin xnu/bsd/conf. In either case, the procedure is basically the same, just in a different directory. This section is divided into two subsections. The first describes adding the module itself and the second describes enabling the module. 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 155 Building and Debugging KernelsAdding the Files or Modules In the appropriate conf directory, you need to add your files or modules into various files. The files MASTER, MASTER.ppc, and MASTER.i386 contain the list of configuration options that should be built into the kernel for all architectures, PowerPC, and i386, respectively. These are supplemented by files, files.ppc, and files.i386, which contain associations between compile options and the files that are related to them for their respective architectures. The format for these two files is relatively straightforward. If you are adding a new module, you should first choose a name for that module. For example, if your module is called mach_foo, you should then add a new option line near the top of files that is whitespace (space or tab) delimited and looks like this: OPTIONS/mach_foo optional mach_foo The first part defines the name of the module as it will be used in #if statements in the code. (See “Modifying the Source Code Files” (page 157) for more information.) The second part is alwaysthe word optional. The third part tells the name of the option as used to turn it on or off in a MASTER file. Any line with mach_foo in the last field will be enabled only if there is an appropriate line in a MASTER file. Then, later in the file, you add osfmk/foo/foo_main.c optional mach_foo osfmk/foo/foo_bar.c optional mach_foo and so on, for each new file associated with that module. This also applies if you are adding a file to an existing module. If you are adding a file that is not associated with any module at all, you add a line that looks like the following to specify that this file should always be included: osfmk/crud/mandatory_file.c standard If you are not adding any modules, then you’re done. Otherwise, you also need to enable your option in one of the MASTER files. Enabling Module Options To enable a module option (as described in the files files), you must add an entry for that option into one of the MASTER files. If your code is not a BSD pseudo-device, you should add something like the following: options MACH_FOO Building and Debugging Kernels Adding New Files or Modules 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 156Otherwise, you should add something like this: pseudo-device mach_foo In the case of a pseudo-device (for example, /dev/random), you can also add a number. When your code checks to see if it should be included, it can also check that number and allocate resources for more than one pseudo-device. The meaning of multiple pseudo-devicesis device-dependent. An example of thisis ppp, which allocates resources for two simultaneous PPP connections. Thus, in the MASTER.ppc file, it has the line: pseudo-device ppp 2 Modifying the Source Code Files In the OS X kernel, all source code files are automatically compiled. It is the responsibility of the C file itself to determine whether its contents need to be included in the build or not. In the example above, you created a module called mach_foo. Assume that you want this file to compile only on PowerPC-based computers. In that case, you should have included the option only in MASTER.ppc and not in MASTER.i386. However, by default, merely specifying the file foo_main.c in files causes it to be compiled, regardless of compile options specified. To make the code compile only when the option mach_foo is included in the configuration, you should begin each C source file with the lines #include #if (MACH_FOO > 0) and end it with #endif /* MACH_FOO */ If mach_foo is a pseudo-device and you need to check the number of mach_foo pseudo-devices included, you can do further tests of the value of MACH_FOO. Note that the file is not something you create. It is created by the makefiles themselves. You must run make exporthdrs before make all to generate these files. Building and Debugging Kernels Adding New Files or Modules 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 157Building Your First Kernel Before you can build a kernel, you must first obtain source code. Source code for the OS X kernel can be found in the Darwin xnu project on http://www.opensource.apple.com. To find out your current kernel version, use the command uname -a. If you run into trouble, search the archives of the darwin-kernel and darwin-development mailing lists for information. If that doesn’t help, ask for assistance on either list. The list archives and subscription information can be found at http://www.lists.apple.com. Note: Before you begin, make sure you extract the sources in a directory whose path does not contain any “special” characters (non-alphanumeric characters other than dash and underscore), as having such characters in the path leading up to the build directory can cause compiling to fail. Also, make sure that /usr/local/bin is in your PATH environment variable as follows: If you are using a csh derivative such as tcsh, you should add set path = (/usr/local/bin $path) to your .tcshrc file If you are using a Bourne shell derivative, you should add export PATH=/usr/local/bin:$PATH to your .bashrc file. Important: Once you have obtained and extracted the sources, before you begin compiling kernelsupport tools, you should configure your system to build using gcc 3.3. The OS X v10.4 kernel will not build using gcc 4.0. To do this, type: sudo gcc_select 3.3 Important: Before building anything, you should make sure you are running the latest version of OS X with the latest developer tools. The xnu compile process may reference various external headers from /System/Library/Frameworks. These headers are only installed as part of a developer toolsinstallation, not as part of the normal OS X install process. Next, you will need to compile several support tools. Get the bootstrap_cmds, Libstreams, kext_tools, IOKitUser, and cctools packagesfrom http://www.opensource.apple.com. Extract the filesfrom these .tar packages, then do the following: sudo mkdir -p /usr/local/bin sudo mkdir -p /usr/local/lib cd bootstrap_cmds-version/relpath.tproj make Building and Debugging Kernels Building Your First Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 158sudo make install cd ../../Libstreams-version make sudo make install cd ../cctools-version sudo cp /usr/include/ar.h \ /System/Library/Frameworks/Kernel.framework/Headers In the cctools package, modify the Makefile, and change the COMMON_SUBDIRS line (including the continuation line after it) to read: COMMON_SUBDIRS = libstuff libmacho misc Finally, issue the following commands: make RC_OS=macos sudo cp misc/seg_hack.NEW /usr/local/bin/seg_hack cd ld make RC_OS=macos kld_build sudo cp static_kld/libkld.a /usr/local/lib sudo ranlib /usr/local/lib/libkld.a Now you’re done with the cctools project. One final step remains: compiling kextsymboltool. To do this, extract the kext_tools tarball, then do the following: sudo mkdir -p /System/Library/Frameworks/IOKit.framework/Versions/A/PrivateHeaders/kext cd /System/Library/Frameworks/IOKit.framework/ sudo ln -s Versions/A/PrivateHeaders PrivateHeaders sudo cp PATH_TO_IOKITUSER/IOKitUser-version/kext.subproj/*.h PrivateHeaders/kext cd PATH_TO_KEXT_TOOLS/kext_tools-version gcc kextsymboltool.c -o kextsymboltool sudo cp kextsymboltool /usr/local/bin Building and Debugging Kernels Building Your First Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 159Warning: If you do not use a version of kextsymboltool that is at least as current as your kernel, you will get serious compile failures. If you see the error message “exported name not in import list”, there’s a good chance you aren’t using a current kextsymboltool. Congratulations. You now have all the necessary tools, libraries, and header files to build a kernel. The next step is to compile the kernel itself. First, change directories into the xnu directory. Next, you need to set a few environment variables appropriately. For your convenience, the kernel sources contain shell scripts to do this for you. If you are using sh, bash, zsh, or some other Bourne-compatible shell, issue the following command: source SETUP/setup.sh If you are using csh, tcsh, or a similar shell, use the following command: source SETUP/setup.csh Then, you should be able to type make exporthdrs make all and get a working kernel in BUILD/obj/RELEASE_PPC/mach_kernel (assuming you are building a RELEASE kernel for PowerPC, of course). If things don’t work, the darwin-kernel mailing list a good place to get help. Building an Alternate Kernel Configuration When building a kernel, you may want to build a configuration other than the RELEASE configuration (the default shipping configuration). Additional configurations are RELEASE_TRACE, DEBUG, DEBUG_TRACE, and PROFILE. These configurations add various additional options (except PROFILE, which is reserved for future expansion, and currently maps onto RELEASE). Building and Debugging Kernels Building an Alternate Kernel Configuration 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 160The most useful and interesting configurations are RELEASE and DEBUG. The release configuration should be the same as a stock Apple-released kernel, so this is interesting only if you are building source that differs from that which was used to build the kernel you are already running. Compiling a kernel without specifying a configuration results in the RELEASE configuration being built. The DEBUG configuration enables ddb, the in-kernel serial debugger. The ddb debugger is helpful to debug panics that occur early in boot or within certain parts of the Ethernet driver. It is also useful for debugging low-level interrupt handler routines that cannot be debugged by using the more traditional gdb. To compile an alternate kernel configuration, you should follow the same basic procedure as outlined previously, changing the final make statement slightly. For example, to build the DEBUG configuration, instead of typing make all you type make KERNEL_CONFIGS=DEBUG all and wait. To turn on additional compile options, you must modify one of the MASTER files. For information on modifying these files, see the section “Enabling Module Options” (page 156). When Things Go Wrong: Debugging the Kernel No matter how careful your programming habits, sometimes things don’t work right the first time. Kernel panics are simply a fact of life during development of kernel extensions or other in-kernel code. There are a number of ways to track down problems in kernel code. In many cases, you can find the problem through careful use of printf or IOLog statements. Some people swear by this method, and indeed, given sufficient time and effort, any bug can be found and fixed without using a debugger. Of course, the key words in that statement are “given sufficient time and effort.” For the rest of us, there are debuggers: gdb and ddb. Setting Debug Flags in Open Firmware With the exception of kernel panics or calls to PE_enter_debugger, it is not possible to do remote kernel debugging without setting debug flags in Open Firmware. These flags are relevant to both gdb and ddb debugging and are important enough to warrant their own section. Building and Debugging Kernels When Things Go Wrong: Debugging the Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 161To set these flags, you can either use the nvram program (from the OS X command line) or access your computer’s Open Firmware. You can access Open Firmware this by holding down Command-Option-O-F at boot time. For most computers, the default is for Open Firmware to present a command–line prompt on your monitor and accept input from your keyboard. For some older computers you must use a serial line at 38400, 8N1. (Technically, such computers are not supported by OS X, but some are usable under Darwin, and thus they are mentioned here for completeness.) From an Open Firmware prompt, you can set the flags with the setenv command. From the OS X command line, you would use the nvram command. Note that when modifying these flags you should always look at the old value for the appropriate Open Firmware variables and add the debug flags. For example, if you want to set the debug flagsto 0x4, you use one of the following commands. For computers with recent versions of Open Firmware, you would type printenv boot-args setenv boot-args original_contents debug=0x4 from Open Firmware or nvram boot-args nvram boot-args="original_contents debug=0x4" from the command line (as root). For older firmware versions, the interesting variable is boot-command. Thus, you might do something like printenv boot-command setenv boot-command 0 bootr debug=0x4 from Open Firmware or nvram boot-command nvram boot-command="0 bootr debug=0x4" from the command line (as root). Of course, the more important issue is what value to choose for the debug flags. Table 20-1 (page 163) lists the debugging flags that are supported in OS X. Building and Debugging Kernels When Things Go Wrong: Debugging the Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 162Table 20-1 Debugging flags Symbolic name Flag Meaning DB_HALT 0x01 Halt at boot-time and wait for debugger attach (gdb). DB_PRT 0x02 Send kernel debugging printf output to console. Drop into debugger on NMI (Command–Power, Command-Option-Control-Shift-Escape, or interrupt switch). DB_NMI 0x04 DB_KPRT 0x08 Send kernel debugging kprintf output to serial port. DB_KDB 0x10 Make ddb (kdb) the default debugger (requires a custom kernel). DB_SLOG 0x20 Output certain diagnostic info to the system log. Allow debugger to ARP and route (allows debugging across routers and removes the need for a permanent ARP entry, but is a potential security hole)—not available in all kernels. DB_ARP 0x40 DB_KDP_BP_DIS 0x80 Support old versions of gdb on newer systems. DB_LOG_PI_SCRN 0x100 Disable graphical panic dialog. The option DB_KDP_BP_DIS is not available on all systems, and should not be important if your target and host systems are running the same or similar versions of OS X with matching developer tools. The last option is only available in Mac OS 10.2 and later. Avoiding Watchdog Timer Problems Macintosh computers have various watchdog timers designed to protect the system from certain types of failures. There are two primary watchdog timersin common use: the power management watchdog timer (not present on all systems) and the system crash watchdog timer. Both watchdogs are part of the power management hardware. The first of these, the power management watchdog timer, is designed to restore the system to a known safe state in the event of unexpected communication loss between the power management hardware and the CPU. Thistimer is only present in G4 and earlier desktops and laptops and in early G5 desktops. More specifically, it is present only in machines containing a PMU (Power Management Unit) chip. Under normal circumstances, when communication with the PMU chip is lost, the PMU driver will attempt to get back in sync with the PMU chip. With the possible exception of a momentary loss of keyboard and mouse control, you probably won't notice that anything has happened (and you should never even experience such a stall unless you are writing a device driver that disables interrupts for an extended period of time). Building and Debugging Kernels When Things Go Wrong: Debugging the Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 163The problem occurs when the disruption in communication is caused by entering the debugger while the PMU chip is in one of these "unsafe" states. If the chip is left in one of these "unsafe" states for too long, it will shut the computer down to prevent overheating or other problems. This problem can be significantly reduced by operating the PMU chip in polled mode. This prevents the watchdog timer from activating. You should only use this option when debugging, however, as it diminishes performance and a crashed system could overheat. To disable this watchdog timer, add the argument pmuflags=1 to the kernel's boot arguments. See “Setting Debug Flags in Open Firmware” (page 161) for information about how to add a boot argument. The second type of watchdog timer is the system crash watchdog timer. This is normally only enabled in OS X Server. If your target machine is running OS X Server, your system will automatically reboot within seconds after a crash to maximize server uptime. You can disable this automatic reboot on crash feature in the server administration tool. Choosing a Debugger There are two basic debugging environments supported by OS X: ddb and gdb. ddb is a built-in debugger that works over a serial line. By contrast, gdb is supported using a debugging shim built into the kernel, which allows a remote computer on the same physical network to attach after a panic (or sooner if you pass certain options to the kernel). For problems involving network extensions or low-level operating system bringups, ddb is the only way to do debugging. For other bugs, gdb is generally easier to use. For completeness, this chapter describes how to use both ddb and gdb to do basic debugging. Since gdb itself is well documented and is commonly used for application programming, this chapter assumes at least a passing knowledge of the basics of using gdb and focuses on the areas where remote (kernel) gdb differs. Note: Only systems with serial hardware support ddb. Thus, it is only possible to use ddb on PowerMac G4 and older systems. Using gdb for Kernel Debugging gdb, short for the GNU Debugger, is a piece of software commonly used for debugging software on UNIX and Linux systems. This section assumes that you have used gdb before, and does not attempt to explain basic usage. In standard OS X builds (and in your builds unless you compile with ddb support), gdb support is built into the system but is turned off except in the case of a kernel panic. Building and Debugging Kernels When Things Go Wrong: Debugging the Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 164Of course, many software failures in the kernel do not result in a kernel panic but still cause aberrant behavior. For these reasons, you can pass additional flags to the kernel to allow you to attach to a remote computer early in boot or after a nonmaskable interrupt (NMI), or you can programmatically drop into the debugger in your code. You can cause the test computer (the debug target) to drop into the debugger in the following ways: ● debug on panic ● debug on NMI ● debug on boot ● programmatically drop into the default debugger The function PE_enter_debugger can be called from anywhere in the kernel, although if gdb is your default debugger, a crash will result if the network hardware is not initialized or if gdb cannot be used in that particular context. This call is described in the header pexpert/pexpert.h. After you have decided what method to use for dropping into the debugger on the target, you must configure your debug host (the computer that will actually be running gdb). Your debug hostshould be running a version of OS X that is comparable to the version running on your target host. However, it should not be running a customized kernel, since a debug host crash would be problematic, to say the least. Note: It is possible to use a non-OS X system as your debug host. This is not a trivial exercise, however, and a description of building a cross-gdb is beyond the scope of this document. When using gdb, the best results can be obtained when the source code for the customized kernel is present on your debug host. This not only makes debugging easier by allowing you to see the lines of code when you stop execution, it also makes it easier to modify those lines of code. Thus, the ideal situation is for your debug host to also be your build computer. This is not required, but it makes things easier. If you are debugging a kernel extension, it generally suffices to have the source for the kernel extension itself on your debug host. However, if you need to see kernel-specific structures, having the kernel sources on your debug host may also be helpful. Once you have built a kernel using your debug host, you must then copy it to your target computer and reboot the target computer. At this point, if you are doing panic-only debugging, you should trigger the panic. Otherwise, you should tell your target computer to drop into the debugger by issuing an NMI (or by merely booting, in the case of debug=0x1). Building and Debugging Kernels When Things Go Wrong: Debugging the Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 165Next, unless your kernelsupports ARP while debugging (and unless you enabled it with the appropriate debug flag), you need to add a permanent ARP entry for the target. It will be unable to answer ARP requests while waiting for the debugger. This ensures that your connection won’t suddenly disappear. The following example assumes that your target is target.foo.com with an IP number of 10.0.0.69: $ ping -c 1 target_host_name ping results: .... $ arp -an target.foo.com (10.0.0.69): 00:a0:13:12:65:31 $ sudo arp -s target.foo.com 00:a0:13:12:65:31 $ arp -an target.foo.com (10.0.0.69) at00:a0:13:12:65:31 permanent Now, you can begin debugging by doing the following: gdb /path/to/mach_kernel source /path/to/xnu/osfmk/.gdbinit p proc0 source /path/to/xnu/osfmk/.gdbinit target remote-kdp attach 10.0.0.69 Note that the mach kernel passed as an argument to gdb should be the symbol–laden kernel file located in BUILD/obj/DEBUG_PPC/mach_kernel.sys (for debug kernel builds, RELEASE_PPC for non-debug builds), not the bootable kernel that you copied onto the debug target. Otherwise most of the gdb macros will fail. The correct kernel should be several times as large as a normal kernel. You must do the p proc0 command and source the .gdbinit file (from the appropriate kernel sources) twice to work around a bug in gdb. Of course, if you do not need any of the macros in .gdbinit, you can skip those two instructions. The macros are mostly of interest to people debugging aspects of Mach, though they also provide ways of obtaining information about currently loaded KEXTs. Warning: It may not be possible to detach in a way that the target computer’s kernel continues to run. If you detach, the target hangs until you reattach. It is not always possible to reattach, though the situation is improving in this area. Do not detach from the remote kernel! Building and Debugging Kernels When Things Go Wrong: Debugging the Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 166If you are debugging a kernel module, you need to do some additional work to get debugging symbol information about the module. First, you need to know the load address for the module. You can get this information by running kextstat (kmodstat on systems running OS X v10.1 or earlier) as root on the target. If you are already in the debugger, then assuming the target did not panic, you should be able to use the continue function in gdb to revive the target, get this information, then trigger another NMI to drop back into the debugger. If the target is no longer functional, and if you have a fully symbol–laden kernel file on your debug host that matches the kernel on your debug target, you can use the showallkmods macro to obtain this information. Obtaining a fully symbol–laden kernel generally requires compiling the kernel yourself. Once you have the load address of the module in question, you need to create a symbol file for the module. You do this in different ways on different versions of OS X. For versions 10.1 and earlier, you use the kmodsyms program to create a symbol file for the module. If your KEXT is called mykext and it is loaded at address 0xf7a4000, for example, you change directories to mykext.kext/Contents/MacOS and type: kmodsyms -k path/to/mach_kernel -o mykext.sym mykext@0xf7a4000 Be sure to specify the correct path for the mach kernel that is running on your target (assuming it is not the same as the kernel running on your debug host). For versions after 10.1, you have two options. If your KEXT does not crash the computer when it loads, you can ask kextload to generate the symbols at load time by passing it the following options: kextload -s symboldir mykext.kext It will then write the symbols for your kernel extension and its dependencies into files within the directory you specified. Of course, this only works if your target doesn’t crash at or shortly after load time. Alternately, if you are debugging an existing panic, or if your KEXT can’t be loaded without causing a panic, you can generate the debugging symbols on your debug host. You do this by typing: kextload -n -s symboldir mykext.kext If will then prompt you for the load address of the kernel extension and the addresses of all its dependencies. As mentioned previously, you can find the addresses with kextstat (or kmodstat) or by typing showallkmods inside gdb. Building and Debugging Kernels When Things Go Wrong: Debugging the Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 167You should now have a file or files containing symbolic information that gdb can use to determine address–to–name mappings within the KEXT. To add the symbols from that KEXT, within gdb on your debug host, type the command add-symbol-file mykext.sym for each symbol file. You should now be able to see a human-readable representation of the addresses of functions, variables, and so on. Special gdb I/O Addressing Issues As described in “Address Spaces” (page 70), some Macintosh hardware has a third addressing mode called I/O addressing which differs from both physical and virtual addressing modes. Most developers will not need to know about these modes in any detail. Where some developers may run into problems is debugging PCI device drivers and attempting to access device memory/registers. To allow I/O-mapped memory dumping, do the following: set kdp_read_io=1 To dump in physical mode, do the following: set kdp_trans_off=1 For example: (gdb) x/x 0xf8022034 0xf8022034: Cannot access memory at address 0xf8022034 (gdb) set kdp_trans_off=1 (gdb) x/x 0xf8022034 0xf8022034: Cannot access memory at address 0xf8022034 (gdb) set kdp_read_io=1 (gdb) x/x 0xf8022034 0xf8022034: 0x00000020 (gdb) Building and Debugging Kernels When Things Go Wrong: Debugging the Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 168If you experience problems accessing I/O addresses that are not corrected by this procedure, please contact Apple Developer Technical Support for additional assistance. Using ddb for Kernel Debugging When doing typical debugging, gdb is probably the best solution. However, there are times when gdb cannot be used or where gdb can easily run into problems. Some of these include ● drivers for built-in Ethernet hardware ● interrupt handlers (the hardware variety, not handler threads) ● early bootstrap before the network hardware is initialized When gdb is not practical (or if you’re curious), there is a second debug mechanism that can be compiled into OS X. This mechanism is called ddb, and is similar to the kdb debugger in most BSD UNIX systems. It is not quite as easy to use as gdb, mainly because of the hardware needed to use it. Unlike gdb (which uses Ethernet for communication with a kernel stub), ddb is built into the kernel itself, and interacts directly with the user over a serial line. Also unlike gdb, using ddb requires building a custom kernel using the DEBUG configuration. For more information on building this kernel, see “Building Your First Kernel” (page 158). Note: ddb requires an actual built-in hardware serial line on the debug target. Neither PCI nor USB serial adapters will work. In order to work reliably for interrupt-level debugging, ddb controls the serial ports directly with a polled-mode driver without the use of the I/O Kit. If your debug target does not have a factory serial port, third-party adapter boards may be available that replace your internal modem with a serial port. Since these devices use the built-in serial controller, they should work for ddb. It is not necessary to install OS X drivers for these devices if you are using them only to support ddb debugging. The use of these serial port adapter cards is not an officially supported configuration, and not all computers support the third-party adapter boards needed for ddb support. Consult the appropriate adapter board vendor for compatibility information. If your target computer has two serial ports, ddb uses the modem port (SCC port 0). However, if your target has only one serial port, that port is probably attached to port 1 of the SCC cell, which means that you have to change the default port if you want to use ddb. To use this port (SCC port 1), change the line: const int console_unit=0; Building and Debugging Kernels When Things Go Wrong: Debugging the Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 169in osfmk/ppc/serial_console.c to read: const int console_unit=1; and recompile the kernel. Once you have a kernel with ddb support, it isrelatively easy to use. First, you need to set up a terminal emulator program on your debug host. If your debug host is running Mac OS 9, you might use ZTerm, for example. For OS X computers, or for computers running Linux or UNIX, minicom provides a good environment. Setting up these programs is beyond the scope of this document. Important: Serial port settings for communicating with ddb must be 57600 8N1. Hardware handshaking may be on, but is not necessary. Note: For targets whose Open Firmware uses the serial ports, remember that the baud rate for communicating with Open Firmware is 38400 and that hardware handshaking must be off. Once you boot a kernel with ddb support, a panic will allow you to drop into the debugger, as will a call to PE_enter_debugger. If the DB_KDB flag is not set, you will have to press the D key on the keyboard to use ddb. Alternately, if both DB_KDB and DB_NMI are set, you should be able to drop into ddb by generating a nonmaskable interrupt (NMI). See “Setting Debug Flags in Open Firmware” (page 161) for more information on debug flags. To generate a nonmaskable interrupt, hold down the command, option, control, and shift keys and hit escape (OS X v10.4 and newer), hold down the command key while pressing the power key on your keyboard (on hardware with a power key), or press the interrupt button on your target computer. At this point, the system should hang, and you should see ddb output on the serial terminal. If you do not, check your configuration and verify that you have specified the correct serial port on both computers. Commands and Syntax of ddb The ddb debugger is much more gdb-like than previous versions, but it still has a syntax that is very much its own (shared only with other ddb and kdb debuggers). Because ddb is substantially different from what most developers are used to using, this section outlines the basic commands and syntax. The commands in ddb are generally in this form: command[/switch] address[,count] Building and Debugging Kernels When Things Go Wrong: Debugging the Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 170The switches can be one of those shown in Table 20-2 (page 171). Table 20-2 Switch options in ddb Switch Description /A Print the location with line number if possible /I Display as instruction with possible alternate machine-dependent format /a Print the location being displayed /b Display or process by bytes Display low 8 bits as a character (nonprinting characters as octal) or count instructions while executing (depends on instruction) /c /d Display as signed decimal /h Display or process by half word (16 bits) /i Display as an instruction /l Display or process by long word (32 bits) /m Display as unsigned hex with character dump for each line /o Display in unsigned octal /p Print cumulative instruction count and call tree depth at each call or return statement /r Display in current radix, signed /s Display the null-terminated string at address (nonprinting as octal). Display in unsigned decimal or set breakpoint at a user space address (depending on command). /u /x Display in unsigned hex /z Display in signed hex The ddb debugger has a rich command set that has grown over its lifetime. Its command set is similar to that of ddb and kdb on other BSD systems, and their manual pages provide a fairly good reference for the various commands. The command set for ddb includes the following commands: Building and Debugging Kernels When Things Go Wrong: Debugging the Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 171break[/u] addr Set a breakpoint at the address specified by addr. Execution will stop when the breakpoint is reached. The /u switch means to set a breakpoint in user space. c or continue[/c] Continue execution after reaching a breakpoint. The /c switch meansto count instructions while executing. call Call a function. cond Set condition breakpoints. This command is not supported on PowerPC. cpu cpunum Causes ddb to switch to run on a different CPU. d or delete [addr|#] Delete a breakpoint. This takes a single argument that can be either an address or a breakpoint number. dk Equivalent to running kextstat while the target computer is running. This lists loaded KEXTs, their load addresses, and various related information. dl vaddr Dumps a range of memory starting from the address given. The parameter vaddr is a kernel virtual address. If vaddr is not specified, the last accessed address is used. See also dr, dv. dm Displays mapping information for the last address accessed. dmacro name Delete the macro called name. See macro. dp Displays the currently active page table. dr addr Dumps a range of memory starting from the address given. The parameter address is a physical address. If addr is not specified, the last accessed address is used. See also dl, dv. ds Dumps save areas of all Mach tasks. dv [addr [vsid]] Dumps a range of memory starting from the address given. The parameter addr is a virtual address in the address space indicated by vsid. If addr is not specified, the last accessed address is used. Similarly, if vsid is not specified, the last vsid is used. See also dl, dr. Building and Debugging Kernels When Things Go Wrong: Debugging the Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 172dwatch addr Delete a watchpoint. See watch. dx Displays CPU registers. examine See print. gdb Switches to gdb mode, allowing gdb to attach to the computer. lt On PowerPC only: Dumps the PowerPC exception trace table. macro name command [ ; command .. ] Create a macro called name that executesthe listed commands. You can show a macro with the command show macro name or delete it with dmacro name. match[/p] Stop at the matching return instruction. If the /p switch is not specified, summary information is printed only at the final return. print[/AIabcdhilmorsuxz] addr1 [addr2 ...] Print the values at the addresses given in the format specified by the switch. If no switch is given, the last used switch is assumed. Synonymous with examine and x. Note that some of the listed switches may work for examine and not for print. reboot Reboots the computer. Immediately. Without doing any file-system unmounts or other cleanup. Do not do this except after a panic. s or step Single step through instructions. search[/bhl] addr value [mask[,count]] Search memory for value starting at addr. If the value is not found, this command can wreak havoc. This command may take other formatting values in addition to those listed. set $name [=] expr Sets the value of the variable or register named by name to the value indicated by expr. show Display system data. For a list of information that can be shown, type the show command by itself. Some additional options are available for certain options, particularly show all. For those suboptions, type show all by itself. Building and Debugging Kernels When Things Go Wrong: Debugging the Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 173trace[/u] Prints a stack backtrace. If the /u flag is specified, the stack trace extends to user space if supported by architecture-dependent code. until[/p] Stop at the next call or return. w or write[/bhl] addr expr1 [expr2 ... ] Writes the value of expr1 to the memory location stored at addr in increments of a byte, half word, or long word. If additional expressions are specified, they are written to consecutive bytes, half words, or long words. watch addr[,size] Sets a watchpoint on a particular address. Execution stops when the value stored at that address is modified. Watch points are not supported on PowerPC. Warning: Watching addresses in wired kernel memory may cause unrecoverable errors on i386. x Short for examine. See print. xb Examine backward. Execute the last examine command, but use the address previous to the last one used (jumping backward by increments of the last width displayed). xf Examine forward. Execute the last examine command, but use the address following the last one used (jumping by increments of the last width displayed). The ddb debugger should seem relatively familiar to users of gdb, and its syntax was changed radically from its predecessor, kdb, to be more gdb-like. However, it is still sufficiently different that you should take some time to familiarize yourself with its use before attempting to debug something with it. It is far easier to use ddb on a system whose memory hasn’t been scribbled upon by an errant DMA request, for example. Building and Debugging Kernels When Things Go Wrong: Debugging the Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 174This bibliography contains related material that may be of interest. The editions listed are the editions that were current when this list was compiled, but newer versions may be available. Apple OS X Publications The following Apple publications have information that could be of interest to you if you are programming in the kernel: Hello Debugger: Debugging a Device Driver With GDB (tutorial). Hello I/O Kit: Creating a Device Driver With Xcode (tutorial) Hello Kernel: Creating a Kernel Extension With Xcode (tutorial). Accessing Hardware From Applications I/O Kit Fundamentals Network Kernel Extensions Programming Guide Network Kernel Extensions (legacy) Mac Technology Overview Porting UNIX/Linux Applications to OS X I/O Kit Device Driver Design Guidelines Packaging Your KEXT for Distribution and Installation(tutorial). General UNIX and Open Source Resources A Quarter Century of UNIX . Peter H. Salus. Addison-Wesley, 1994.ISBN 0-201-54777-5. Berkeley Software Distribution . CSRG, UC Berkeley. USENIX and O’Reilly, 1994.ISBN 1-56592-082-1. 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 175 BibliographyTheCathedralandtheBazaar:MusingsonLinuxandOpenSourcebyanAccidentalRevolutionary . Eric S.Raymond. O’Reilly & Associates, 1999.ISBN 1-56592-724-9. The New Hacker’s Dictionary . 3rd. Ed., Eric S. Raymond. MIT Press, 1996. ISBN 0-262-68092-0. Open Sources: Voices from the Open Source Revolution . Edited by Chris DiBona, Sam Ockman & Mark Stone. O’Reilly & Associates, 1999. ISBN 1-56592-582-3. Proceedings of the First Conference on Freely Redistributable Software . Free Software Foundation. FSF, 1996. ISBN 1-882114-47-7. The UNIX Desk Reference: The hu.man Pages. Peter Dyson. Sybex, 1996. ISBN 0-7821-1658-2. The UNIX Programming Environment. Brian W. Kernighan, Rob Pike. Prentice Hall, 1984. ISBN 0-13-937681-X (paperback), ISBN 0-13-937699-2 (hardback). BSD and UNIX Internals Advanced Topics in UNIX: Processes, Files, and Systems. Ronald J. Leach. Wiley, 1996. ISBN 1-57176-159-4. The Complete FreeBSD. Greg Lehey, Walnut Creek CDROM Books, 1999. ISBN 1-57176-246-9. The Design and Implementation of the 4.4BSD Operating System. Marshall Kirk McKusick, et al. Addison-Wesley, 1996. ISBN 0-201-54979-4. The Design of the UNIX Operating System. Maurice J. Bach. Prentice Hall, 1986. ISBN 0-13-201799-7. Linux Kernel Internals 2nd edition . Michael Beck, et al. Addison-Wesley, 1997. ISBN 0-201-33143-8. Lions’ Commentary on UNIX 6th Edition with Source Code . John Lions. Peer-to-Peer, 1996. ISBN 1-57398-013-7. Panic!: UNIX System Crash Dump Analysis. Chris Drake, Kimberly Brown. Prentice Hall, 1995. ISBN 0-13-149386-8. UNIX Internals: The New Frontiers. Uresh Vahalia. Prentice-Hall, 1995. ISBN 0-13-101908-2. UNIX Systems for Modern Architectures: Symmetric Multiprocessing and Caching for Kernel Programmers. Curt Schimmel. Addison-Wesley, 1994. ISBN 0-201-63338-8. Optimizing PowerPC Code . Gary Kacmarcik. Addison-Wesley Publishing Company, 1995. ISBN 0-201-40839-2. BerkeleySoftwareArchitectureManual4.4BSDEdition .WilliamJoy,Robert Fabry, Samuel Leffler,M.KirkMcKusick, Michael Karels. Computer Systems Research Group, Computer Science Division, Department of Electrical Engineering and Computer Science, University of California, Berkeley. Bibliography BSD and UNIX Internals 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 176Mach CMU Computer Science: A 25th Anniversary Commemorative . Richard F. Rashid, Ed. ACM Press, 1991. ISBN 0-201-52899-1. Load Distribution, Implementation for the Mach Microkernel . Dejan S. Milojicic. Vieweg Verlag, 1994. ISBN 3-528-05424-7. Programming under Mach . Boykin, et al. Addison-Wesley, 1993. ISBN 0-201-52739-1. Mach Workshop Proceedings. USENIX Association. October, 1990. Mach Symposium Proceedings.USENIX Association. November, 1991. Mach III Symposium Proceedings. USENIX Association. April, 1993, ISBN 1-880446-49-9. Mach 3 Documentation Series. Open Group Research Institute (RI), now Silicomp: Final Draft Specifications OSF/1 1.3 Engineering Release . RI. May 1993. OSF Mach Final Draft Kernel Principles. RI. May, 1993. OSF Mach Final Draft Kernel Interfaces. RI. May, 1993. OSF Mach Final Draft Server Writer’s Guide . RI. May, 1993. OSF Mach Final Draft Server Library Interfaces, RI, May, 1993. Research Institute Microkernel Series. Open Group Research Institute (RI): Operating Systems Collected Papers. Volume I. RI. March, 1993. Operating Systems Collected Papers. Volume II. RI. October,1993. Operating Systems Collected Papers. Volume III. RI. April, 1994. Operating Systems Collected Papers. Volume IV. RI. October, 1995. Mach: A New Kernel Foundation for UNIX Development. Proceedings of the Summer 1986 USENIX Conference. Atlanta, GA., http://www.usenix.org. UNIX as an Application Program. Proceedings of the Summer 1990 USENIX Conference. Anaheim, CA., http://www.usenix.org. OSF RI papers (Spec ‘93): OSF Mach Final Draft Kernel Interfaces Bibliography Mach 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 177OSF Mach Final Draft Kernel Principles OSF Mach Final Draft Server Library Interfaces OSF Mach Final Draft Server Writer's Guide OSF Mach Kernel Interface Changes OSF RI papers (Spec ‘94): OSF RI 1994 Mach Kernel Interfaces Draft OSF RI 1994 Mach Kernel Interfaces Draft (Part A) OSF RI 1994 Mach Kernel Interfaces Draft (Part B) OSF RI 1994 Mach Kernel Interfaces Draft (Part C) OSF RI papers (miscellaneous): Debugging an object oriented system using the Mach interface Unix File Access and Caching in a Multicomputer Environment Untyped MIG: The Protocol Untyped MIG: What Has Changed and Migration Guide Towards a World-Wide Civilization of Objects A Preemptible Mach Kernel A Trusted, Scalable, Real-Time Operating System Environment Mach Scheduling Framework Networking UNIX Network Programming . Volume 1, Networking APIs: Sockets and XTI . W. Richard Stevens. Prentice Hall, 1998, ISBN 0-13-490012-X. UNIX Network Programming . Volume 2, Interprocess Communications. W. Richard Stevens. Prentice Hall, 1998. ISBN 0-13-081081-9. TCP/IP Illustrated . Volume 1, The Protocols. W. Richard Stevens. Addison-Wesley, 1994. ISBN 0-201-63346-9. Bibliography Networking 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 178TCP/IP Illustrated . Volume 2, The Implementation .W. Richard Stevens.Addison-Wesley, 1995. ISBN0-201-63354-X. TCP/IP Illustrated . Volume 3, TCP for Transactions, HTTP, NNTP, and the UNIX Domain Protocols. W. Richard Stevens. Addison-Wesley, 1996. ISBN 0-201-63495-3. Operating Systems Advanced Computer Architecture: Parallelism, Scalability, Programmability . Kai Hwang. McGraw-Hill, 1993. ISBN 0-07-031622-8. Concurrent Systems: An Integrated Approach to Operating Systems, Database, and Distributed Systems. Jean Bacon. Addison-Wesley, 1993. ISBN 0-201-41677-8. Distributed Operating Systems. Andrew S. Tanenbaum. Prentice Hall, 1995. ISBN 0-13-219908-4. Distributed Operating Systems: The Logical Design . A. Goscinski. Addison-Wesley, 1991. ISBN 0-201-41704-9. Distributed Systems, Concepts, and Designs. G. Coulouris, et al. Addison-Wesley, 1994. ISBN 0-201-62433-8. Operating System Concepts. 4th Ed., Abraham Silberschatz, Peter Galvin. Addison-Wesley, 1994. ISBN 0-201-50480-4. POSIX Information Technology-PortableOperating SystemInterface (POSIX): SystemApplication ProgramInterface (API) (C Language). ANSI/IEEE Std. 1003.1. 1996 Edition. ISO/IEC 9945-1: 1996. IEEE Standards Office. ISBN 1-55937-573-6. Programming with POSIX Threads. David R. Butenhof. Addison Wesley Longman, Inc., 1997. ISBN 0-201-63392-2. Programming Advanced Programming in theUNIX Environment. RichardW. Stevens.Addison-Wesley, 1992. ISBN0-201-56317-7. Debugging with GDB: The GNU Source-Level Debugger Eighth Edition for GDB version 5.0 . Richard Stallman et al. Cygnus Support. http://developer.apple.com/documentation/DeveloperTools/gdb/gdb/gdb_toc.html. Open Source Development with CVS , Karl Franz Fogel. Coriolis Group, 1999. ISBN: 1-57610-490-7. Porting UNIX Software: From Download to Debug . Greg Lehey. O’Reilly, 1995. ISBN 1-56592-126-7. Bibliography Operating Systems 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 179The Standard C Library . P.J. Plauger. Prentice Hall, 1992. ISBN 0-13-131509-9. Websites and Online Resources Apple’s developer website (http://www.apple.com/developer/) is a general repository for developer documentation. Additionally, the following sites provide more domain-specific information. Apple’s Public Source projects and Darwin http://www.opensource.apple.com/ The Berkeley Software Distribution (BSD) http://www.FreeBSD.org http://www.NetBSD.org http://www.OpenBSD.org BSD Networking http://www.kohala.com/start/ Embedded C++ http://www.caravan.net/ec2plus GDB, GNUPro Toolkit 99r1 Documentation http://www.redhat.com/docs/manuals/gnupro/ The Internet Engineering Task Force (IETF) http://www.ietf.org jam http://www.perforce.com/jam/jam.html The PowerPC CPU http://www.freescale.com/webapp/sps/site/homepage.jsp?nodeId=0162468rH3bTdG The Single UNIX Specification Version 2 http://www.opengroup.org/onlinepubs/007908799 Bibliography Websites and Online Resources 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 180The USENIX Association; USENIX Proceedings http://www.usenix.org http://www.usenix.org/publications/library/ Security and Cryptography Applied Cryptography: Protocols, Algorithms, and Source Code in C. Bruce Schneier. John Wiley & Sons, 1994. ISBN 0-471-59756-2. comp.security newsgroup (news:comp.security). comp.security.unix newsgroup (news:comp.security.unix). Computer Security . Dieter Gollmann. John Wiley and Son Ltd, 1999. ISBN 0-471-97844-2. Foundations of Cryptography . Oded Goldreich. Cambridge University Press, 2001. ISBN 0-521-79172-3. Secrets and Lies: Digital Security in a Networked World . Bruce Schneier. John Wiley & Sons, 2000. ISBN 0-471-25311-1. Bibliography Security and Cryptography 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 181This table describes the changes to Kernel Programming Guide . Date Notes 2012-02-16 Updated for OS X v10.7. Added a chapter that discusses the early stages of the boot process. “The Early Boot Process” (page 21) was formerly part of Daemons and Services Programming Guide , and was moved here during a reorganization of that book. 2011-03-08 2006-11-07 Added security information and improved kernel build instructions. 2006-10-03 Made minor corrections. 2006-05-23 Added a note about pmuflags to the debugging section. 2006-04-04 Removed out-of-date information for OS X v10.4. 2006-03-08 Updated some stale content for OS X version 10.4. 2006-01-10 Corrected locking prototypes. Made minor fixesto the file system section. Revised networking, synchronization, and kernel services APIs for OS X v10.4. 2005-11-09 Changed terminology from "fat binary" to "universal binary." Clarified the distinction between memory objects and VM objects. 2005-08-11 2005-07-07 Fixed minor errors in build instructions. 2005-06-04 Updated kernel build instructions for OS X v10.4; other minor fixes. 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 182 Document Revision HistoryDate Notes Added information about generating NMI on newer hardware in OS X v10.4 and later; various other minor changes. 2005-04-29 2005-02-03 Made minor corrections. 2004-12-02 Made section number fix to man page reference in Chapter 14. 2004-11-01 Minor wording changes. Added details comparing current_task to mach_task_self. Added information about using AltiVec and floating point in the kernel. 2004-08-01 2003-09-01 Minor corrections to kernel build information Added information relating to Power Macintosh G5 VM issues and debugging. Clarified wait queue documentation (event_t). 2003-08-01 Minor update release. Added index and tweaked wording throughout. Fixed minor errata in debugging chapter. Added a few missing details in the security chapter and cleaned up the equations presented. Corrected a few very minor OS X v10.2-specific details that weren’t caught during the first revision. 2003-02-01 OS X v10.2 update release. Changed information on KEXT management, various small corrections (mainly wording improvements). 2002-08-01 Full web release to coincide with WWDC. Corrected a few minor errata from the previous release. 2002-06-01 2002-01-01 Initial partial web release. Document Revision History 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 183abstraction (v) The process of separating the interface to some functionality from the underlying implementation in such a way that the implementation can be changed without changing the way that piece of code is used. (n) The API (interface) for some piece of functionality that has been separated in this way. address space The virtual addressranges available to a given task (note: the task may be the kernel). In OS X, processes do not share the same address space. The addressspaces of multiple processes can, however, point to the same physical addressranges. This is referred to as shared memory. anonymous memory Virtual memory backed by the default pager to swap files, rather than by a persistent object. Anonymous memory is zero-initialized and exists only for the life of the task. See also default pager; task. API (application programming interface) The interface (calling convention) by which an application program accesses a service. This service may be provided by the operating system, by libraries, or by other parts of the application. Apple Public Source License Apple’s Open Source license, available at http://www.apple.com/publicsource. Darwin is distributed under this license. See also Open Source. AppleTalk A suite of network protocols that is standard on Macintosh computers. ASCII (American Standard Code for Information Interchange) A 7-bit character set (commonly represented using 8 bits) that defines 128 unique character codes. See also Unicode. BSD (Berkeley Software Distribution Formerly known as the Berkeley version of UNIX, BSD is now simply called the BSD operating system. The BSD portion of the OS X kernel is based on FreeBSD, a version of BSD. bundle A directory thatstores executable code and the software resources related to that code. Applications, plug-ins, and frameworks represent types of bundles. Except for frameworks, bundles are presented by the Finder as if they were a single file. Carbon An application environment in OS X that features a set of programming interfaces derived from earlier versions of the Mac OS. The Carbon APIs have been modified to work properly with OS X. Carbon applications can run in OS X, Mac OS 9, and all versions of Mac OS 8 later than Mac OS 8.1 (with appropriate libraries). Classic An application environment in OS X that lets users run non-Carbon legacy Mac OS software. It supports programs built for both Power PC and 68K processor architectures. clock An object used to abstract time in Mach. 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 184 GlossaryCocoa An advanced object-oriented development platform on OS X. Cocoa is a set of frameworks with programming interfaces in both Java and Objective-C. It is based on the integration of OPENSTEP, Apple technologies, and Java. condition variable Essentially a wait queue with additional locking semantics. When a thread sleeps waiting for some event to occur, it releases a related lock so that another thread can cause that event to occur. When the second thread posts the event, the first thread wakes up, and, depending on the condition variable semantics used, either takes the lock immediately or begins waiting for the lock to become available. console (1) A text-based login environment that also displays system log messages, kernel panics, and other information. (2) A special window in OS X that displays messages that would be printed to the text console if the GUI were not in use. This window also displays output written to the standard error and standard output streams by applications launched from the Finder. (3) An application by the same name that displays the console window. control port In Mach, access to the control port allows an object to be manipulated. Also called the privileged port. See also port; name port. cooperative multitasking A multitasking environment in which a running programcan receive processing time only if other programs allow it; each application must give up control of the processor cooperatively in order to allow others to run. Mac OS 9 is a cooperative multitasking environment. See also preemptive multitasking. copy-on-write A delayed copy optimization used in Mach. The object to be copied is marked temporarily read-only. When a thread attempts to write to any page in that object, a trap occurs, and the kernel copies only the page or pages that are actually being modified. See also thread. daemon A long-lived process, usually without a visible user interface, that performs a system-related service. Daemons are usually spawned automatically by the system and may either live forever or be regenerated at intervals. They may also be spawned by other daemons. Darwin The core of OS X, Darwin is an Open Source project that includes the Darwin kernel, the BSD commands and C libraries, and several additional features.The Darwin kernel is synonymous with the OS X kernel. default pager In Mach, one of the built-in pagers. The default pager handles nonpersistent (anonymous)memory. See also anonymousmemory; vnode pager; pager. demand paging An operating-system facility that brings pages of data from disk into physical memory only as they are needed. DLIL (Data Link Interface Layer) The part of the OS X kernel’s networking infrastructure that provides the interface between protocol handling and network device driversin the I/O Kit. A generalization of the BSD “ifnet” architecture. DMA (direct memory access) A means of transferring data between host memory and a peripheral device without requiring the host processor to move the data itself. This reduces processor overhead for I/O operations and may reduce contention on the processor bus. Glossary 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 185driver Software that deals with getting data to and from a device, as well as control of that device. In the I/O Kit, an object that manages a piece of hardware (a device), implementing the appropriate I/O Kit abstractions for that device. See also object. DVD (Digital Versatile Disc) Originally, Digital Video Disc. An opticalstorage medium that provides greater capacity and bandwidth than CD-ROM; DVDs are frequently used for multimedia as well as data storage. dyld (dynamic link editor) A utility that allows programs to dynamically load (and link to) needed functions. EMMI (External Memory Management Interface) Mach’sinterface to memory objectsthat allowstheir contents to be contributed by user-mode tasks. See also external pager. Ethernet A family of high-speed local area network technologies in common use. Some common variants include 802.3 and 802.11 (Airport). exception An interruption to the normal flow of program control, caused by the program itself or by executing an illegal instruction. exception port A Mach port on which a task or thread receives messages when exceptions occur. external pager A module that manages the relationship between virtual memory and a backing store. External pagers are clients of Mach’s EMMI. The pager API is currently not exported to userspace. The built-in pagersin OS X are the default pager, the device pager, and the vnode pager. See also EMMI (External Memory Management Interface). family In the I/O Kit, a family defines a collection of software abstractions that are common to all devices of a particular category (for example, PCI, storage, USB). Families provide functionality and services to drivers. See also driver. FAT (file allocation table) A data structure used in the MS-DOS file system. Also synonymous with the file system that uses it. The FAT file system is also used as part of Microsoft Windows and has been adopted for use inside devices such as digital cameras. fat files See universal binaries. FIFO (first-in first-out) A data processing scheme in which data is read in the order in which it was written, processes are run in the order in which they were scheduled, and so forth. file descriptor A per-process unique, nonnegative integer used to identify an open file (or socket). firewall Software (or a computer running such software) that prevents unauthorized access to a network by users outside of the network. fixed-priority policy In Mach, a scheduling policy in which threads execute for a certain quantum of time, and then are put at the end of the queue of threads of equal priority. fork (1) A stream of data that can be opened and accessed individually under a common filename. The Macintosh Standard and Extended file systems store a separate “data” fork and a “resource” fork as part of every file; data in each fork can be accessed and manipulated independently of the other. (2) In BSD, fork is a system call that creates a new process. framework A bundle containing a dynamic shared library and associated resources, including image files, header files, and documentation. Frameworks Glossary 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 186are often used to provide an abstraction for manipulating device driver families from applications. FreeBSD A variant of the BSD operating system. See http://www.freebsd.org for details. gdb (GNU debugger) gdb is a powerful, source-level debugger with a command-line interface. gdb is a popular Open Source debugger and is included with the OS X developer tools. HFS (hierarchical file system) The Mac OS Standard file system format, used to represent a collection of files as a hierarchy of directories (folders), each of which may contain either files or foldersthemselves. HFS+ The Mac OS Extended file system format. This file system format was introduced as part of Mac OS 8.1, adding support for filenames longer than 31 characters, Unicode representation of file and directory names, and efficient operation on larger disks. host (1) The computer that is running (is host to) a particular program or service. The term is usually used to refer to a computer on a network. (2) In debugging, the computer that is running the debugger itself. In this context, the target is the machine running the application, kernel, or driver being debugged. host processor The microprocessor on which an application program resides. When an application is running, the host processor may call other, peripheral microprocessors, such as a digital signal processor, to perform specialized operations. IDE (integrated development environment) An application or set of tools that allows a programmer to write, compile, edit, and in some cases test and debug within an integrated, interactive environment. inheritance attribute In Mach, a value indicating the degree to which a parent process and its child process share pages in the parent process’s address space. A memory page can be inherited as copy-on-write, shared, or not at all. in-line data Data that’s included directly in a Mach message, rather than referred to by a pointer. See also out-of-line data. info plist See information property list. information property list A special form of property list with predefined keysforspecifying basic bundle attributes and information of interest, such as supported document types and offered services. See also bundle; property list. interrupt service thread A thread running in kernel space for handling I/O that is triggered by an interrupt, but does not run in an interrupt context. Also called an I/O service thread. I/O (input/output) The exchange of data between two parts of a computer system, usually between system memory and a peripheral device. I/O Kit Apple’s object-oriented I/O development model. The I/O Kit provides a framework for simplified driver development, supporting many families of devices. See also family. I/O service thread See interrupt service thread. IPC (interprocess communication) The transfer of information between processes or between the kernel and a process. IPL (interrupt priority level) A means of basic synchronization on uniprocessor systems in traditional BSD systems, set using the spl macro. Interrupts with lower priority than the current IPL will not be acted upon until the IPL is lowered. In many parts of the kernel, changing the IPL in OS X Glossary 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 187is not useful as a means ofsynchronization. New use of spl macros is discouraged. See also spl (set priority level). KDP The kernelshim used for communication with a remote debugger (gdb). Kerberos An authentication system based on symmetric key cryptography. Used in MIT Project Athena and adopted by the Open Software Foundation (OSF). kernel The complete OS X core operating-system environment that includes Mach, BSD, the I/O Kit, file systems, and networking components. kernel crash An unrecoverable system failure in the kernel caused by an illegal instruction, memory access exception, or other failure rather than explicitly triggered as in a panic. See also panic. kernel extension See KEXT (kernel extension). kernel mode See supervisor mode. kernel panic See panic. kernel port A Mach port whose receive right is held by the kernel. See also task port; thread port. KEXT (kernel extension) A bundle that extendsthe functionality of the kernel. The I/O Kit, File system, and Networking components are designed to allow and expect the creation and use of KEXTs. KEXT binary A file (or files) in Mach-O format, containing the actual binary code of a KEXT. A KEXT binary is the minimum unit of code that can be loaded into the kernel. Also called a kernel module or KMOD. See also KEXT (kernel extension); Mach-O. key signing In public key cryptography, to (electronically)state your trust that a public key really belongs to the person who claims to own it, and potentially that the person who claims to own it really is who he or she claims to be. KMOD (kernel module) See KEXT binary. lock A basic means of synchronizing multiple threads. Generally only one thread can “hold” a lock at any given time. While a thread is holding the lock, any other thread that tries to take it will wait, either by blocking or by spinning, depending on the nature of the lock. Some lock variants such as read-write locks allow multiple threads to hold a single lock under certain conditions. Mach The lowest level of the OS X kernel. Mach provides such basic services and abstractions as threads, tasks, ports, IPC, scheduling, physical and virtual address space management, VM, and timers. Mach-O Mach object file format. The preferred object file format for OS X. Mach server A task that providesservicesto clients, using a MIG-generated RPC interface. See also MIG (Mach interface generator). main thread By default, a process has one thread, the main thread. If a process has multiple threads, the main thread is the first thread in the process. A user process can use the POSIX thread API to create other user threads. makefile A makefile detailsthe files, dependencies, and rules by which an executable application is built. memory-mapped files A facility that maps virtual memory onto a physical file. Thereafter, any access to that part of virtual memory causes the corresponding page of the physical file to be accessed. The contents of the file can be changed by changing the contents in memory. Glossary 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 188memory object An object managed by a pager that represents the memory, file, or other storage that backs a VM object. See also pager. memory protection A system of memory management in which programs are prevented from being able to modify or corrupt the memory partition of another program, usually through the use of separate address spaces. message A unit of data sent by one task or thread that is guaranteed to be delivered atomically to another task or thread. In Mach, a message consists of a header and a variable-length body. Some system services are invoked by passing a message from a thread to the Mach port representing the task that provides the desired service. microkernel A kernel implementing a minimal set of abstractions. Typically, higher-level OS services such as file systems and device drivers are implemented in layers above a microkernel, possibly in trusted user-mode servers. OS X is a hybrid between microkernel and monolithic kernel architectures. See also monolithic kernel. MIG (Mach interface generator) (1) A family of software that generates and supports the use of a procedure call interface to Mach’s system of interprocess communication. (2) The interface description language supported by MIG. monolithic kernel A kernel architecture in which all pieces of the kernel are closely intertwined. A monolithic kernel providessubstantial performance improvements. It is difficult to evolve the individual components independently, however. The OS X kernel is a hybrid of the monolithic and microkernel models. See also microkernel. multicast A process in which a single packet can be addressed to multiple recipients. Multicast is used, for example, in streaming video, in which many megabytes of data are sent over the network. multihoming The ability to have multiple network addresses in one computer, usually on different networks. For example, multihoming might be used to create a system in which one address is used to talk to hosts outside a firewall and the other to talk to hosts inside; the computer provides facilities for passing information between the two. multitasking The concurrent execution of multiple programs. OS X uses preemptive multitasking. Mac OS 9 uses cooperative multitasking. mutex See mutex lock (mutual exclusion lock). mutex lock (mutual exclusion lock) A type of lock characterized by putting waiting threads to sleep until the lock is available. named (memory) entry A handle (a port) to a mappable object backed by a memory manager. The object can be a region or a memory object. name port In Mach, accessto the name port allows non-privileged operations against an object (for example, obtaining information about the object). In effect, it provides a name for the object without providing any significant access to the object. See also port; control port. named region In Mach, a form of named memory entry that provides a form of memory sharing. namespace An agreed-upon context in which names (identifiers) can be defined. Within a given namespace, all names must be unique. Glossary 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 189NAT (network address translation) A scheme that transforms network packets at a gateway so network addresses that are valid on one side of the gateway are translated into addresses that are valid on the other side. network A group of hosts that can communicate with each other. NFS (network file system) A commonly used file server protocol often found in UNIX and UNIX-based environments. NKE (network kernel extension) A type of KEXT that provides a way to extend and modify the networking infrastructure of OS X dynamically without recompiling or relinking the kernel. NMI (nonmaskable interrupt) An interrupt produced by a particular keyboard sequence or button that cannot be blocked in software. It can be used to interrupt a hung system, for example to drop into a debugger. nonsimple message In Mach, a message that contains either a reference to a port or a pointer to data. See also simple message. notify port A special Mach port that is part of a task. A task’s notify port receives messages from the kernel advising the task of changes in port access rights and of the status of messages it has sent. nub An I/O Kit object that represents a point of connection for a device or logical service. Each nub provides accessto the device orservice it represents, and provides such services as matching, arbitration, and power management. It is most common that a driver publishes one nub for each individual device or service it controls; it is possible for a driver that vends only a single device orservice to act asits own nub. NVRAM (nonvolatile RAM) RAM storage that retains its state even when the power is off. See also RAM (random-access memory). object (1) A collection of data. (2) In Mach, a collection of data, with permissions and ownership. (3) In object-oriented programming, an instance of a class. OHCI (Open Host Controller Interface) The register-level standards that are used by most USB and Firewire controller chips. Open Source Software that includesfreely available access to source code, redistribution, modification, and derived works. The full definition is available at http://www.opensource.org. Open Transport A communications architecture for implementing network protocols and other communication features on computers running classic Mac OS. Open Transport provides a set of programming interfacesthatsupports, among other things, both the AppleTalk and TCP/IP protocols. out-of-line data Data that’s passed by reference in a Mach message, rather than being included in the message. See also in-line data. packet An individual piece of information sent on a network. page (n) (1) The largest block of virtual address space for which the underlying physical address space is guaranteed contiguous—in other words, the unit of mapping between virtual and physical addresses. (2) logical page size: The minimum unit of information that an anonymous pager transfers between system memory and the backing store. (3) physical page size: The unit of information treated as a unit by a hardware MMU. The logical page size must be at least as large as the physical page size Glossary 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 190for hardware-based memory protection to be possible. (v) To move data between memory and a backing store. pager A module responsible for providing the data for the pages of a memory object. See also default pager; vnode pager. panic An unrecoverable system failure explicitly triggered by the kernel with a call to panic. See also kernel crash. PEF (Preferred Executable Format) The format of executable files used for applications and shared libraries in Mac OS 9; supported in OS X. The preferred format for OS X is Mach-O. physical address An address to which a hardware device,such as a memory chip, can directly respond. Programs, including the Mach kernel, use virtual addresses that are translated to physical addresses by mapping hardware controlled by the Mach kernel. pmap Part of Mach VM that provides an abstract way to set and fetch virtual to physical mappings from hardware. The pmap system is the machine-dependent layer of the VM system. port In Mach, a secure unidirectional channel for communication between tasks running on a single system. In IP transport protocols, an integer identifier used to select a receiving service for an incoming packet, or to specify the sender of an outgoing packet. port name In Mach, an integer index into a port namespace; a port right is specified with respect to its port name. See also port rights. portrights In Mach, the ability to send to or receive from a Mach port. Also known as port access rights. port set In Mach, a set of zero or more Mach ports. A thread can receive messages sent to any of the ports contained in a port set by specifying the port set as a parameter to msg_receive(). POSIX (Portable Operating System Interface) A standard that defines a set of operating-system services. It is supported by ISO/IEC, IEEE, and The Open Group. preemption The act of interrupting a currently running program in order to give time to another task. preemptive multitasking A type of multitasking in which the operating system can interrupt a currently running task in order to run another task, as needed. See also cooperative multitasking. priority In scheduling, a number that indicates how likely a thread is to run. The higher the thread’s priority, the more likely the thread isto run. See also scheduling policy. process A BSD abstraction for a running program. A process’s resources include an address space, threads, and file descriptors. In OS X, a process is based on one Mach task and one or more Mach threads. process identifier (PID), A number that uniquely identifies a process. Also called a process ID. programmed I/O I/O in which the CPU accomplishes data transfer with explicit load and store instructions to device registers, rather than DMA, and without the use of interrupts. This data transfer is often done in a byte-by-byte, or word-by-word fashion. Also known as direct or polled I/O. See also DMA (direct memory access). property list A textual way to represent data. Elements of the property list represent data of certain types,such as arrays, dictionaries, and strings. Glossary 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 191System routines allow programs to read property lists into memory and convert the textual data representation into “real” data. See also information property list. protected memory See memory protection. protocol handler A network module that extracts data from input packets (giving the data to interested programs) and inserts data into output packets(giving the output packet to the appropriate network device driver). pthreads The POSIX threads implementation. See also POSIX (Portable Operating System Interface); thread. quantum The fixed amount of time a thread or process can run before being preempted. RAM (random-access memory) Memory that a microprocessor can either read from or write to. real-time performance Performance characterized by guaranteed worst-case response times. Real-time support is important for applications such as multimedia. receive rights In Mach, the ability to receive messages on a Mach port. Only one task at a time can have receive rights for any one port. See also send rights. remote procedure call See RPC (remote procedure call). reply port A Mach port associated with a thread that is used in remote procedure calls. ROM (read-only memory) Memory that cannot be written to. root (1) An administrative account with special privileges. For example, only the root account can load kernel extensions.(2) In graph theory, the base of a tree. (3) root directory: The base of a file system tree. (4) root file system: The primary file system off which a computer boots, so named because it includes the root node of the file system tree. routine In Mach, a remote procedure call that returns a value. This can be used for synchronous or asynchronous operations. See also simpleroutine. RPC (remote procedure call) An interface to IPC that appears (to the caller) as an ordinary function call. In Mach, RPCs are implemented using MIG-generated interface libraries and Mach messages. scheduling The determination of when each process or task runs, including assignment of start times. scheduling policy In Mach, how the thread’s priority isset and under what circumstancesthe thread runs. See also priority. SCSI (Small Computer Systems Interface) A standard communications protocol used for connecting devicessuch as disk drivesto computers. Also, a family of physical bus designs and connectors commonly used to carry SCSI communication. semaphore Similar to a lock, except that a finite number of threads can be holding a semaphore at the same time. See also lock. send rights In Mach, the ability to send messages to a Mach port. Many tasks can have send rights for the same port. See also receive rights. session key In cryptography, a temporary key that is only used for one message, one connection session, orsimilar. Session keys are generally treated asshared secrets, and are frequently exchanged over a channel encrypted using public key cryptography. Glossary 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 192shadow object In Mach VM, a memory object that holds modified pages that originally belonged to another memory object. Thisis used when an object that was duplicated in a copy-on-write fashion is modified. If a page is not found in this shadow object, the original object is referenced. simple message In Mach, a message that contains neither references to ports nor pointers to data. See also nonsimple message. simpleroutine In Mach, a remote procedure call that does not return a value, and has no out or inout parameters. This can be used for asynchronous operations. See also routine. SMP (symmetric multiprocessing) A system architecture in which two or more processors are managed by one kernel, share the same memory, have equal access to I/O devices, and in which any task, including kernel tasks, can run on any processor. spinlock Any of a family of lock types characterized by continuously polling to see if a lock is available, rather than putting the waiting thread to sleep. spin/sleep lock Any of a family of lock types characterized by some combination of the behaviors of spinlocks and mutex (sleep) locks. spl (set priority level) A macro thatsetsthe current IPL. Interrupts with lower priority than the current IPL will not be acted upon until the IPL is lowered. The spl macros have no effect in many parts of OS X, so their use is discouraged as a means of synchronization in new programming except when modifying code that already uses spl macros. See also IPL (interrupt priority level). socket (1) In a user process, a file descriptor that has been allocated using socket(2). (2) In the kernel, the data structure allocated when the kernel’s implementation of the socket(2) call is made. (3) In AppleTalk protocols, a socket serves the same purpose as a port in IP transport protocols. submap A collection of mappingsin the VM system that is shared among multiple Mach tasks. supervisor mode Also known as kernel mode, the processor mode in which certain privileged instructions can be executed, including those related to page table management, cache management, clock setting, and so on. symmetric multiprocessing See SMP (symmetric multiprocessing). task A Mach abstraction, consisting of a virtual address space and a port namespace. A task itself performs no computation; rather, it isthe framework in which threads run. See also thread. task port A kernel port that represents a task and is used to manipulate that task. See also kernel port; thread port. TCP/IP (Transmission Control Protocol/Internet Protocol) An industry standard protocol used to deliver messages between computers over the network. TCP/IP is the primary networking protocol used in OS X. thread The unit of program execution. A thread consists of a program counter, a set of registers, and a stack pointer. See also task. thread port A kernel port that represents a thread and is used to manipulate that thread. See also kernel port; task port. thread-safe code Code that can be executed safely by multiple threads simultaneously. Glossary 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 193time-sharing policy In Mach, a scheduling policy in which a thread’s priority is raised and lowered to balance its resource consumption against other timesharing threads. UDF (Universal Disk Format) The file system format used in DVD disks. UFS (UNIX file system) An industry standard file system format used in UNIX and similar operating systems such as BSD. UFS in OS X is a derivative of 4.4BSD UFS. Unicode A 16-bit character set that defines unique character codes for characters in a wide range of languages. Unlike ASCII, which defines 128 distinct characters typically represented in 8 bits, there are as many as 65,536 distinct Unicode characters that represent the unique characters used in most foreign languages. universal binaries Executable files containing object code for more than one machine architecture. UPL (universal page list) A data structure used when communicating with the virtual memory system. UPLs can be used to change the behavior of pages with respect to caching, permissions, mapping, and so on. USB (Universal Serial Bus) A multiplatform bus standard that can support up to 127 peripheral devices, including printers, digital cameras, keyboards and mice, and storage devices. UTF-8 (Unicode Transformation Format 8) A format used to represent a sequence of 16-bit Unicode characters with an equivalent sequence of 8-bit characters, none of which are zero. This sequence of characters can be represented using an ordinary C language string. VFS (virtual file system) A set of standard internal file-system interfaces and utilities that facilitate support for additional file systems. VFS provides an infrastructure for file systems built into the kernel. virtual address An address as viewed from the perspective of an application. Each task has its own range of virtual addresses, beginning at address zero. The Mach VM system makes the CPU hardware map these addresses onto physical memory. See also physical address. virtual memory A system in which addresses as seen by software are not the same as addressesseen by the hardware. This provides support for memory protection, reduces the need for code relocatability, and allows the operating system to provide the illusion to each application that it has resources much larger than those that could actually be backed by RAM. VM See virtual memory. vnode An in-memory data structure containing information about a file. vnode pager In Mach, one of the built-in pagers. The vnode pager maps files into memory objects. See also default pager; pager. work loop The main loop of an application or KEXT that waits repeatedly for incoming events and dispatches them. XML (Extensible Markup Language) A dialect of SGML (Standard Generalized Markup Language), XML provides a metalanguage containing rules for constructing specialized markup languages. XML users can create their own tags, making XML very flexible. Glossary 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 194Apple Inc. © 2002, 2012 Apple Inc. All rights reserved. No part of this publication may be reproduced, stored in a retrievalsystem, or transmitted, in any form or by any means, mechanical, electronic, photocopying, recording, or otherwise, without prior written permission of Apple Inc., with the following exceptions: Any person is hereby authorized to store documentation on a single computer for personal use only and to print copies of documentation for personal use provided that the documentation contains Apple’s copyright notice. No licenses, express or implied, are granted with respect to any of the technology described in this document. Apple retains all intellectual property rights associated with the technology described in this document. This document is intended to assist application developers to develop applications only for Apple-labeled computers. Apple Inc. 1 Infinite Loop Cupertino, CA 95014 408-996-1010 Apple, the Apple logo, AppleTalk, Carbon, Cocoa, Finder, FireWire, Keychain, Logic, Mac, Mac OS, Macintosh, Objective-C, OS X, Pages, Panther, Power Mac,Quartz,QuickTime, Spaces, and Xcode are trademarks of Apple Inc., registered in the U.S. and other countries. .Mac is a service mark of Apple Inc., registered in the U.S. and other countries. NeXT and OPENSTEP are trademarks of NeXT Software, Inc., registered in the U.S. and other countries. DEC is a trademark of Digital Equipment Corporation. Intel and Intel Core are registered trademarks of Intel Corporation or its subsidiaries in the United States and other countries. Java is a registered trademark of Oracle and/or its affiliates. OpenGL is a registered trademark of Silicon Graphics, Inc. PowerPC and the PowerPC logo are trademarks of International Business Machines Corporation, used under license therefrom. SPEC is a registered trademark of the Standard Performance Evaluation Corporation (SPEC). UNIX is a registered trademark of The Open Group. Even though Apple has reviewed this document, APPLE MAKES NO WARRANTY OR REPRESENTATION, EITHER EXPRESS OR IMPLIED, WITH RESPECT TO THIS DOCUMENT, ITS QUALITY, ACCURACY, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.ASARESULT, THISDOCUMENT IS PROVIDED “AS IS,” AND YOU, THE READER, ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND ACCURACY. IN NO EVENT WILL APPLE BE LIABLE FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL,OR CONSEQUENTIAL DAMAGES RESULTING FROM ANY DEFECT OR INACCURACY IN THIS DOCUMENT, even if advised of the possibility of such damages. THE WARRANTY AND REMEDIES SET FORTH ABOVE ARE EXCLUSIVE AND IN LIEU OF ALL OTHERS, ORAL OR WRITTEN, EXPRESS OR IMPLIED. No Apple dealer, agent, or employee is authorized to make any modification, extension, or addition to this warranty. Some states do not allow the exclusion or limitation of implied warranties or liability for incidental or consequential damages, so the above limitation or exclusion may not apply to you. This warranty gives you specific legal rights, and you may also have other rights which vary from state to state. RED Workflows with Final Cut Pro X White Paper June 2012White Paper 2 RED Workflows with Final Cut Pro X With the continuing popularity of the RED® family of cameras (www.red.com), Final Cut Pro X editors have been looking for proven workflows with REDCODE® RAW files. This white paper outlines how professional production companies are achieving excellent results when recording with RED cameras, editing in Final Cut Pro X, and finishing in applications such as DaVinci Resolve. This document outlines a complete RED-based post-production workflow, following the steps below: 1. Transcode REDCODE RAW files to Apple ProRes using REDCINE-X® PRO. 2. Batch sync audio and video files. 3. Import synced files into Final Cut Pro X. During import, Final Cut Pro X can automatically create lightweight Apple ProRes 422 (Proxy) files for editing. Or, if you have a lot of footage and multiple editors, you can use Compressor to create the Apple ProRes 422 (Proxy) files. 4. Edit and lock picture with Final Cut Pro X. 5. Export an XML file of the project from Final Cut Pro X. 6. Color grade the project in DaVinci Resolve using either high-quality Apple ProRes or R3D RAW files. You can relink the project XML file to the original R3D files in either REDCINE-X PRO or DaVinci Resolve. 7. Export an XML file from DaVinci Resolve and import it back into Final Cut Pro X. 8. Export a final master from Final Cut Pro X. This method combines the best of both worlds—the speed of editing with Apple ProRes on a wide variety of notebook and desktop systems, and the color grading advantages of RAW when finishing. You can further simplify this workflow by transcoding to high-quality Apple ProRes files and using those throughout color grading and delivery. The sections below include additional detail about each stage of the workflow. Transcode REDCODE RAW Files to Apple ProRes RED cameras record a RAW file (R3D) that must be “debayered” and decompressed to convert the original sensor data to viewable pixels, so that the file can play back in video editing software. Apple ProRes is an excellent choice for this conversion, because it’s a codec optimized for both quality and editing speed. Apple ProRes is a full frame size, intra-frame codec designed to efficiently use multiple processors for playback and rendering. The free RED application REDCINE-X PRO supports Apple ProRes encoding, which can be accelerated using the RED ROCKET® card. REDCINE-X PRO also allows you to apply a “one-light” color correction during the transcoding process, giving your footage a more finished look for editing and review.White Paper 3 RED Workflows with Final Cut Pro X In the Field As workflows expand to include field review and even rough cut editing, digital imaging technicians (DITs) are actively transcoding R3D footage to Apple ProRes using high-end portable systems. A typical field-based workflow includes these steps: • Copy the footage from the camera’s recording medium, like the REDMAG™ removable solid-state drive (SSD). • Create backups so that camera originals can be stored in two different places for data protection. • Create Apple ProRes dailies by transcoding the R3D files to Apple ProRes files for editing and H.264 files for uploading to a secure website for client review. Alternatively, after making backup copies, you can deliver the R3D files to the post facility for transcoding to Apple ProRes dailies. Choose Transcoding Settings When you transcode your files to Apple ProRes, choose the level of quality that’s appropriate to your specific production. Workflow Apple ProRes codec Disk space is a consideration, or you’re editing a large multicam project. Apple ProRes 422 (Proxy) or Apple ProRes 422 (LT) You’re delivering Apple ProRes files as a final master for the web or TV. Apple ProRes 422 or Apple ProRes 422 (HQ) You’re delivering for theater projection or effects compositing. Apple ProRes 4444 Although you can transcode to the final delivery quality and then work with that throughout post-production, it’s more efficient to work with smaller frame sizes and higher image compression during the craft edit. So even though you may have shot at 4K or 5K resolution in the field, you can transcode to a smaller frame size to save time and disk space. For example, you can set the resolution to 1920x1080 or 1280x720, and you can set the debayer quality to 1/4. If you’re generating Apple ProRes files for use as proxy media, you can also choose to superimpose, or “burn in,” the source timecode and filename over the image. This makes it easy to go back to the original R3D files at any point during post-production for a quick visual double-check that the files are correct. For more details, see the REDCINE-X PRO manual at https://www.red.com/downloads. Note: You can speed up transcoding by using a RED ROCKET card, which offloads the processor-intensive debayer and decompression tasks from software to custom hardware. RED ROCKET can be a valuable tool when transcoding a large number of shots.White Paper 4 RED Workflows with Final Cut Pro X Apply One-Light Color Correction When recording with RED cameras, it’s common to shoot a scene “flat” to avoid clipping highlights and shadows and provide more flexibility when manipulating images in post-production. This recording setup can give the footage a washed-out appearance. Many editors and clients prefer working with more visually appealing images that include higher contrast and color saturation. To accommodate this workflow, the free REDCINE-X PRO application allows you to add a one-light color correction as part of the transcoding process. You can choose from several presets to create more common looks, or you can create your own look. Be sure to keep the original names of the R3D files when you generate new Apple ProRes media so that you can easily relink to them later. After you apply the one-light color correction during transcoding, it stays with the image until you go back to the original R3D file and create a new Apple ProRes version. Batch Sync Audio and Video Files After all your media has been transcoded, you can choose to sync second-source audio to the video files. You can sync the files directly in Final Cut Pro X using the built-in synchronization feature that analyzes waveforms to match the scratch audio in your video files to the high-quality audio from your field recorder. You can also use a third-party application like Intelligent Assistance’s Sync-N-Link X (www.intelligentassistance.com), RED’s REDCINE-X PRO (www.red.com/learn), or Singular Software’s PluralEyes (www.singularsoftware.com). Simply select all the audio and Apple ProRes video files and batch sync. Then export the XML to Final Cut Pro X, and all of the synced material is imported into an event, ready for editing. Import Files into Final Cut Pro X After creating Apple ProRes files with REDCINE-X PRO, you can import these files directly into Final Cut Pro X. Even if you transcode R3D files to a high-quality Apple ProRes codec, such as Apple ProRes 4444, you may still choose to use lightweight Apple ProRes 422 (Proxy) files for editing. Final Cut Pro X allows you to generate Apple ProRes proxy files in the background and seamlessly switch to these files for editing, providing great flexibility when editing on a notebook, for example. To create proxy files while importing media 1. In Final Cut Pro, choose File > Import > Files. 2. Select a file or folder, or Command-click to select multiple files to import. 3. Do one of the following: • To add the imported files to an existing event: Select “Add to existing Event,” and choose the event from the pop-up menu. • To create a new event: Select “Create new Event,” type a name in the text field, and choose the disk where you want to store the event from the “Save to” pop-up menu. 4. To have Final Cut Pro copy your media files and add them to the Final Cut Pro Events folder you specified, select the “Copy files to Final Cut Events folder” checkbox. If you’re working with a SAN and want to keep the files in a central location and have multiple users link to them, leave this option unselected. For more information, see Final Cut Pro X: Xsan Best Practices.White Paper 5 RED Workflows with Final Cut Pro X 5. Select the “Create proxy media” checkbox. When this option is selected, Final Cut Pro creates Apple ProRes 422 (Proxy) files in the background after the media files are imported. You can begin to edit your project and, when the proxy files are created, you can open Playback preferences and switch to the proxy files with a single click. 6. Click Import. Final Cut Pro imports your media in the background, and then creates proxy files in the background. You can view the progress of the background tasks in the Background Tasks window. You can now begin editing, even if importing and transcoding are not yet complete. To switch to the Apple ProRes proxy files, select “Use proxy media” in Final Cut Pro Playback preferences. It’s just as easy to switch back to the original media when the creative editing is finished and you want to work on color or effects at the highest quality. When you change these settings, all media in events and projects is affected. Edit in Final Cut Pro X and Export XML After all your media has been imported into Final Cut Pro X, you can edit just as you would any other project. The application was designed for modern, file-based workflows, making it easy to browse, organize, and edit large amounts of material. Use skimming to quickly view your footage. Mark range-based keywords and favorites, and save custom searches as Smart Collections. Quickly and easily arrange clips in the Timeline and add titles and effects, which render in the background as you work. When you’re finished editing, you can send your project to a third-party finishing system such as DaVinci Resolve. Just select the project in the Project Library, choose File > Export XML, and select a location to save the XML file. Color Grade in DaVinci Resolve and Export XML Choose Apple ProRes or RAW for Grading Before importing the Final Cut Pro X XML file into DaVinci Resolve, you should choose between a few different color grading workflows. If you edited with Apple ProRes 422 (HQ) or Apple ProRes 4444 in Final Cut Pro X, you may want to grade these same files in DaVinci Resolve. Alternatively, you can relink the project to the original R3D files in either DaVinci Resolve or REDCINE-X PRO. These RAW files offer a wide range of values to use when grading, which can help improve the look of images that were shot without extensive lighting control or that need a unique style. You can get more image detail out of the highlights and shadows, which is why so many colorists choose to use the RAW files in the color grading stage. White Paper 6 RED Workflows with Final Cut Pro X To relink to the original R3D media in DaVinci Resolve 1. In DaVinci Resolve Preferences, add the location of the R3D files to the Media Storage Volumes list. 2. Save the preferences and reopen DaVinci Resolve. 3. On the Browse page, import the R3D files to the Media Pool. 4. On the Conform page, in the Timeline Management section, click the Load button. 5. Select the XML file that you exported from Final Cut Pro X. 6. In the Load XML window, deselect “Automatically import source clips into media pool.” 7. Choose any other options that are applicable to your project, and click Ok. The XML file is imported and relinked to the corresponding media in the Media Pool using reel name and timecode. A new session appears in the Timeline Management list, and the edit appears in the Timeline. Note: Alternatively, if you’re working with large amounts of media and DaVinci Resolve 8.1 or later, you can have DaVinci Resolve relink to the R3D files automatically when you import the XML file. Just be sure to select the following checkboxes: • Automatically import source clips into media pool • Ignore file extensions when matching Render New Media After color grading the final project in DaVinci Resolve, you can choose the render format based on your final delivery. For example, you may choose to render Apple ProRes 4444 for theater projection, or Apple ProRes 422 if you’re delivering a master for the web or TV. You may want to set a handle length for the rendered media (at least one second), so that you can make additional changes such as adding a longer dissolve or extending an edit. For more details, see the DaVinci Resolve manual at http://www.blackmagic-design.com/support. Export XML from DaVinci Resolve and Import into Final Cut Pro X After you render the media in DaVinci Resolve, you can transfer the project back to Final Cut Pro X by exporting an XML file. To export an XML file from DaVinci Resolve 1. Open the Conform page and, in the Timeline Management list, select the session you want to export an XML file from. 2. Click the Export button at the bottom of the Timeline Management list. 3. In the Export XML dialog, choose FCP X XML 1.1 Files from the Format pop-up menu, type a name and choose a location for the exported XML file, and click Save. An XML version of that session is saved, complete with internal references to the graded media you rendered, and ready for importing into Final Cut Pro X. Import the XML file back into Final Cut Pro X using the Import XML command in the File menu. Make sure that you’re linking to the high-quality media by selecting “Use original or optimized media” in the Playback pane of the Final Cut Pro Preferences window. Now you can add finished audio, adjust titles, insert graphics, and continue to make editorial changes. Because you’ve imported the individual media files and the XML metadata instead of a single QuickTime movie, you can make changes right up to the last minute before delivery. For information about Final Cut Pro X, see Final Cut Pro X Help.White Paper 7 RED Workflows with Final Cut Pro X Copyright © 2012 Apple Inc. All rights reserved. Apple, the Apple logo, Final Cut, Final Cut Pro, QuickTime, and Xsan are trademarks of Apple Inc., registered in the U.S. and other countries. R3D, RED, REDCINE, REDCINE-X, REDCODE, REDMAG, and RED ROCKET are trademarks or registered trademarks of Red.com, Inc. in the United States and other countries. The YouTube logo is a trademark of Google Inc. Other product and company names mentioned herein may be trademarks of their respective companies. Mention of third-party products is for informational purposes only and constitutes neither an endorsement nor a recommendation. Apple assumes no responsibility with regard to the performance or use of these products. Product specifications are subject to change without notice. 019-2378 June 2012 Export a Master from Final Cut Pro X The final step in the workflow is to export a finished master from Final Cut Pro X. To export your project as a master file 1. To make sure the project’s render format is set to the quality level you want for the final master, select the project in the Project Library, click the Inspector button in the toolbar, and click the Project Properties button . The Render Format pop-up menu shows the current render codec. 2. Select the project in the Project Library and choose Share > Export Media (or press Command-E). 3. Choose an option from the Export pop-up menu. The default setting, Video and Audio, creates a movie file containing both video and audio. For information about the other options, see Final Cut Pro X Help. To export a file that matches the project’s properties, choose Current Settings from the “Video codec” pop-up menu. When you export using Current Settings, the final master is exported at the quality of the render settings, and the export is as fast as a file copy with no further compression added. 4. To see details about the file that will be output, click Summary. 5. Click Next, type a name and choose a location for the exported file, and click Save. If you’re exporting for review on the web, you can export an H.264 version directly to a private account on YouTube or Vimeo. You can also burn the project to a DVD, or to a Blu-ray disc if you have a third-party Blu-ray burner. If you have Compressor installed, you can choose Share > Send to Compressor to transfer your project to that application for total control over your final export settings. Compressor also allows you to set up render clusters that use the processors of multiple computers on a network. Create a Compressor droplet for drag-and-drop simplicity, or create custom export settings to match unique delivery requirements. If you need to output to tape, all three major video I/O device manufacturers offer free software to support tape delivery. The applications are AJA‘s VTR Xchange, Blackmagic Design’s Media Express, and Matrox’s Vetura. Download the application that works with your video I/O device and use the QuickTime export from Final Cut Pro X to lay back to tape. Conclusion Using Apple ProRes for editing and R3D RAW files for color grading enables a highly flexible workflow optimized for speed, quality, and creative control. This process also takes advantage of the metadata and XML capabilities of Final Cut Pro X, which have been designed for the future of file-based production. By using this document as a template for working with RED and Final Cut Pro X, editors and post-production facilities can further customize the process to suit their unique needs. Transitioning to ARC Release NotesContents Transitioning to ARC Release Notes 3 Summary 3 ARC Overview 4 ARC Enforces New Rules 5 ARC Introduces New Lifetime Qualifiers 7 ARC Uses a New Statement to Manage Autorelease Pools 11 Patterns for Managing Outlets Become Consistent Across Platforms 11 Stack Variables Are Initialized with nil 12 Use Compiler Flags to Enable and Disable ARC 12 Managing Toll-Free Bridging 12 The Compiler Handles CF Objects Returned From Cocoa Methods 13 Cast Function Parameters Using Ownership Keywords 14 Common Issues While Converting a Project 15 Frequently Asked Questions 19 Document Revision History 23 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 2Automatic Reference Counting (ARC) is a compiler feature that provides automatic memory management of Objective-C objects. Rather than having to think about about retain and release operations, ARC allows you to concentrate on the interesting code, the object graphs, and the relationships between objects in your application. {app_code} {app_code} {app_code} {app_code} {app_code} {app_code} {app_code} {app_code} {app_code} {app_code} Reference counting manually Automatic Reference Counting retain/release code retain/release code retain/release code retain/release code retain/release code retain/release code Time to produce Time to produce Summary ARC works by adding code at compile time to ensure that objects live as long as necessary, but no longer. Conceptually, it follows the same memory management conventions as manual reference counting (described in Advanced Memory Management Programming Guide ) by adding the appropriate memory management calls for you. 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 3 Transitioning to ARC Release NotesIn order for the compiler to generate correct code, ARC restricts the methods you can use and how you use toll-free bridging (see “Toll-Free Bridged Types”). ARC also introduces new lifetime qualifiers for object references and declared properties. ARC is supported in Xcode 4.2 for OS X v10.6 and v10.7 (64-bit applications) and for iOS 4 and iOS 5. Weak references are not supported in OS X v10.6 and iOS 4. Xcode provides a tool that automates the mechanical parts of the ARC conversion (such as removing retain and release calls) and helps you to fix issues the migrator can’t handle automatically (choose Edit > Refactor > Convert to Objective-C ARC). The migration tool converts all filesin a project to use ARC. You can also choose to use ARC on a per-file basis if it’s more convenient for you to use manual reference counting for some files. See also: ● Advanced Memory Management Programming Guide ● Memory Management Programming Guide for Core Foundation ARC Overview Instead of you having to remember when to use retain, release, and autorelease, ARC evaluates the lifetime requirements of your objects and automatically inserts appropriate memory management calls for you at compile time. The compiler also generates appropriate dealloc methods for you. In general, if you’re only using ARC the traditional Cocoa naming conventions are important only if you need to interoperate with code that uses manual reference counting. A complete and correct implementation of a Person class might look like this: @interface Person : NSObject @property NSString *firstName; @property NSString *lastName; @property NSNumber *yearOfBirth; @property Person *spouse; @end @implementation Person @end Transitioning to ARC Release Notes ARC Overview 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 4(Object properties are strong by default; the strong attribute is described in “ARC Introduces New Lifetime Qualifiers” (page 7).) Using ARC, you could implement a contrived method like this: - (void)contrived { Person *aPerson = [[Person alloc] init]; [aPerson setFirstName:@"William"]; [aPerson setLastName:@"Dudney"]; [aPerson setYearOfBirth:[[NSNumber alloc] initWithInteger:2011]]; NSLog(@"aPerson: %@", aPerson); } ARC takes care of memory management so that neither the Person nor the NSNumber objects are leaked. You could also safely implement a takeLastNameFrom: method of Person like this: - (void)takeLastNameFrom:(Person *)person { NSString *oldLastname = [self lastName]; [self setLastName:[person lastName]]; NSLog(@"Lastname changed from %@ to %@", oldLastname, [self lastName]); } ARC ensures that oldLastName is not deallocated before the NSLog statement. ARC Enforces New Rules To work, ARC imposes some new rules that are not present when using other compiler modes. The rules are intended to provide a fully reliable memory management model; in some cases, they simply enforce best practice, in some others they simplify your code or are obvious corollaries of your not having to deal with memory management. If you violate these rules, you get an immediate compile-time error, not a subtle bug that may become apparent at runtime. ● You cannot explicitly invoke dealloc, or implement or invoke retain, release, retainCount, or autorelease. The prohibition extends to using @selector(retain), @selector(release), and so on. Transitioning to ARC Release Notes ARC Overview 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 5You may implement a dealloc method if you need to manage resources other than releasing instance variables. You do not have to (indeed you cannot) release instance variables, but you may need to invoke [systemClassInstance setDelegate:nil] on system classes and other code that isn’t compiled using ARC. Custom dealloc methods in ARC do not require a call to [super dealloc] (it actually results in a compiler error). The chaining to super is automated and enforced by the compiler. You can still use CFRetain, CFRelease, and other related functions with Core Foundation-style objects (see “Managing Toll-Free Bridging” (page 12)). ● You cannot use NSAllocateObject or NSDeallocateObject. You create objects using alloc; the runtime takes care of deallocating objects. ● You cannot use object pointers in C structures. Rather than using a struct, you can create an Objective-C class to manage the data instead. ● There is no casual casting between id and void *. You must use special caststhat tell the compiler about object lifetime. You need to do thisto cast between Objective-C objects and Core Foundation types that you pass as function arguments. For more details, see “Managing Toll-Free Bridging” (page 12). ● You cannot use NSAutoreleasePool objects. ARC provides @autoreleasepool blocks instead. These have an advantage of being more efficient than NSAutoreleasePool. ● You cannot use memory zones. There is no need to use NSZone any more—they are ignored by the modern Objective-C runtime anyway. To allow interoperation with manual retain-release code, ARC imposes a constraint on method naming: ● You cannot give an accessor a name that begins with new. This in turn means that you can’t, for example, declare a property whose name begins with new unless you specify a different getter: // Won't work: @property NSString *newTitle; // Works: @property (getter=theNewTitle) NSString *newTitle; Transitioning to ARC Release Notes ARC Overview 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 6ARC Introduces New Lifetime Qualifiers ARC introduces several new lifetime qualifiers for objects, and weak references. A weak reference does not extend the lifetime of the object it points to, and automatically becomes nil when there are no strong references to the object. You should take advantage of these qualifiers to manage the object graphs in your program. In particular, ARC does not guard against strong reference cycles (previously known as retain cycles—see “Practical Memory Management”). Judicious use of weak relationships will help to ensure you don’t create cycles. Property Attributes The keywords weak and strong are introduced as new declared property attributes, asshown in the following examples. // The following declaration is a synonym for: @property(retain) MyClass *myObject; @property(strong) MyClass *myObject; // The following declaration is similar to "@property(assign) MyClass *myObject;" // except that if the MyClass instance is deallocated, // the property value is set to nil instead of remaining as a dangling pointer. @property(weak) MyClass *myObject; Under ARC, strong is the default for object types. Variable Qualifiers You use the following lifetime qualifiers for variables just like you would, say, const. __strong __weak __unsafe_unretained __autoreleasing ● __strong is the default. An object remains “alive” as long as there is a strong pointer to it. ● __weak specifies a reference that does not keep the referenced object alive. A weak reference is set to nil when there are no strong references to the object. Transitioning to ARC Release Notes ARC Overview 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 7● __unsafe_unretained specifies a reference that does not keep the referenced object alive and is not set to nil when there are no strong references to the object. If the object it references is deallocated, the pointer is left dangling. ● __autoreleasing is used to denote argumentsthat are passed by reference (id *) and are autoreleased on return. You should decorate variables correctly. When using qualifiers in an object variable declaration, the correct format is: ClassName * qualifier variableName; for example: MyClass * __weak myWeakReference; MyClass * __unsafe_unretained myUnsafeReference; Other variants are technically incorrect but are “forgiven” by the compiler. To understand the issue, see http://cdecl.org/. Take care when using __weak variables on the stack. Consider the following example: NSString * __weak string = [[NSString alloc] initWithFormat:@"First Name: %@", [self firstName]]; NSLog(@"string: %@", string); Although string is used after the initial assignment, there is no other strong reference to the string object at the time of assignment; it is therefore immediately deallocated. The log statement shows that string has a null value. (The compiler provides a warning in this situation.) You also need to take care with objects passed by reference. The following code will work: NSError *error; BOOL OK = [myObject performOperationWithError:&error]; if (!OK) { // Report the error. // ... However, the error declaration is implicitly: Transitioning to ARC Release Notes ARC Overview 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 8NSError * __strong e; and the method declaration would typically be: -(BOOL)performOperationWithError:(NSError * __autoreleasing *)error; The compiler therefore rewrites the code: NSError * __strong error; NSError * __autoreleasing tmp = error; BOOL OK = [myObject performOperationWithError:&tmp]; error = tmp; if (!OK) { // Report the error. // ... The mismatch between the local variable declaration (__strong) and the parameter (__autoreleasing) causesthe compiler to create the temporary variable. You can get the original pointer by declaring the parameter id __strong * when you take the address of a __strong variable. Alternatively you can declare the variable as __autoreleasing. Use Lifetime Qualifiers to Avoid Strong Reference Cycles You can use lifetime qualifiers to avoid strong reference cycles. For example, typically if you have a graph of objects arranged in a parent-child hierarchy and parents need to refer to their children and vice versa, then you make the parent-to-child relationship strong and the child-to-parent relationship weak. Other situations may be more subtle, particularly when they involve block objects. In manual reference counting mode, __block id x; hasthe effect of not retaining x. In ARC mode, __block id x; defaults to retaining x (just like all other values). To get the manual reference counting mode behavior under ARC, you could use __unsafe_unretained __block id x;. As the name __unsafe_unretained implies, however, having a non-retained variable is dangerous (because it can dangle) and is therefore discouraged. Two better options are to either use __weak (if you don’t need to support iOS 4 or OS X v10.6), or set the __block value to nil to break the retain cycle. The following code fragment illustrates this issue using a pattern that is sometimes used in manual reference counting. Transitioning to ARC Release Notes ARC Overview 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 9MyViewController *myController = [[MyViewController alloc] init…]; // ... myController.completionHandler = ^(NSInteger result) { [myController dismissViewControllerAnimated:YES completion:nil]; }; [self presentViewController:myController animated:YES completion:^{ [myController release]; }]; As described, instead, you can use a __block qualifier and set the myController variable to nil in the completion handler: MyViewController * __block myController = [[MyViewController alloc] init…]; // ... myController.completionHandler = ^(NSInteger result) { [myController dismissViewControllerAnimated:YES completion:nil]; myController = nil; }; Alternatively, you can use a temporary __weak variable. The following example illustrates a simple implementation: MyViewController *myController = [[MyViewController alloc] init…]; // ... MyViewController * __weak weakMyViewController = myController; myController.completionHandler = ^(NSInteger result) { [weakMyViewController dismissViewControllerAnimated:YES completion:nil]; }; For non-trivial cycles, however, you should use: MyViewController *myController = [[MyViewController alloc] init…]; // ... MyViewController * __weak weakMyController = myController; myController.completionHandler = ^(NSInteger result) { Transitioning to ARC Release Notes ARC Overview 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 10MyViewController *strongMyController = weakMyController; if (strongMyController) { // ... [strongMyController dismissViewControllerAnimated:YES completion:nil]; // ... } else { // Probably nothing... } }; In some cases you can use __unsafe_unretained if the class isn’t __weak compatible. This can, however, become impractical for nontrivial cycles because it can be hard or impossible to validate that the __unsafe_unretained pointer is still valid and still points to the same object in question. ARC Uses a New Statement to Manage Autorelease Pools Using ARC, you cannot manage autorelease pools directly using the NSAutoreleasePool class. Instead, you use @autoreleasepool blocks: @autoreleasepool { // Code, such as a loop that creates a large number of temporary objects. } This simple structure allows the compiler to reason about the reference count state. On entry, an autorelease pool is pushed. On normal exit (break, return, goto, fall-through, and so on) the autorelease pool is popped. For compatibility with existing code, if exit is due to an exception, the autorelease pool is not popped. Thissyntax is available in all Objective-C modes. It is more efficient than using the NSAutoreleasePool class; you are therefore encouraged to adopt it in place of using the NSAutoreleasePool. Patterns for Managing Outlets Become Consistent Across Platforms The patternsfor declaring outletsin iOS and OS X change with ARC and become consistent across both platforms. The pattern you should typically adopt is: outletsshould be weak, except for those from File’s Owner to top-level objects in a nib file (or a storyboard scene) which should be strong. Full details are given in “Nib Files” in Resource Programming Guide . Transitioning to ARC Release Notes ARC Overview 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 11Stack Variables Are Initialized with nil Using ARC,strong, weak, and autoreleasing stack variables are now implicitly initialized with nil. For example: - (void)myMethod { NSString *name; NSLog(@"name: %@", name); } will log null for the value of name rather than perhaps crashing. Use Compiler Flags to Enable and Disable ARC You enable ARC using a new -fobjc-arc compiler flag. You can also choose to use ARC on a per-file basis if it’s more convenient for you to use manual reference counting for some files. For projects that employ ARC as the default approach, you can disable ARC for a specific file using a new -fno-objc-arc compiler flag for that file. ARC is supported in Xcode 4.2 and later OS X v10.6 and later (64-bit applications) and for iOS 4 and later. Weak references are not supported in OS X v10.6 and iOS 4. There is no ARC support in Xcode 4.1 and earlier. Managing Toll-Free Bridging In many Cocoa applications, you need to use Core Foundation-style objects, whether from the Core Foundation framework itself (such as CFArrayRef or CFMutableDictionaryRef) or from frameworks that adopt Core Foundation conventions such as Core Graphics (you might use types like CGColorSpaceRef and CGGradientRef). The compiler does not automatically manage the lifetimes of Core Foundation objects; you must call CFRetain and CFRelease (or the corresponding type-specific variants) as dictated by the Core Foundation memory management rules (see Memory Management Programming Guide for Core Foundation ). If you cast between Objective-C and Core Foundation-style objects, you need to tell the compiler about the ownership semantics of the object using either a cast (defined in objc/runtime.h) or a Core Foundation-style macro (defined in NSObject.h): ● __bridge transfers a pointer between Objective-C and Core Foundation with no transfer of ownership. ● __bridge_retained or CFBridgingRetain casts an Objective-C pointer to a Core Foundation pointer and also transfers ownership to you. Transitioning to ARC Release Notes Managing Toll-Free Bridging 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 12You are responsible for calling CFRelease or a related function to relinquish ownership of the object. ● __bridge_transfer or CFBridgingRelease moves a non-Objective-C pointer to Objective-C and also transfers ownership to ARC. ARC is responsible for relinquishing ownership of the object. For example, if you had code like this: - (void)logFirstNameOfPerson:(ABRecordRef)person { NSString *name = (NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty); NSLog(@"Person's first name: %@", name); [name release]; } you could replace it with: - (void)logFirstNameOfPerson:(ABRecordRef)person { NSString *name = (NSString *)CFBridgingRelease(ABRecordCopyValue(person, kABPersonFirstNameProperty)); NSLog(@"Person's first name: %@", name); } The Compiler Handles CF Objects Returned From Cocoa Methods The compiler understands Objective-C methods that return Core Foundation types follow the historical Cocoa naming conventions (see Advanced Memory Management Programming Guide ). For example, the compiler knows that, in iOS, the CGColor returned by the CGColor method of UIColor is not owned. You must still use an appropriate type cast, as illustrated by this example: NSMutableArray *colors = [NSMutableArray arrayWithObject:(id)[[UIColor darkGrayColor] CGColor]]; [colors addObject:(id)[[UIColor lightGrayColor] CGColor]]; Transitioning to ARC Release Notes Managing Toll-Free Bridging 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 13Cast Function Parameters Using Ownership Keywords When you cast between Objective-C and Core Foundation objectsin function calls, you need to tell the compiler about the ownership semantics of the passed object. The ownership rules for Core Foundation objects are those specified in the Core Foundation memory management rules (see Memory Management Programming Guide for Core Foundation ); rules for Objective-C objects are specified in Advanced Memory Management Programming Guide . In the following code fragment, the array passed to the CGGradientCreateWithColors function requires an appropriate cast. Ownership of the object returned by arrayWithObjects: is not passed to the function, thus the cast is __bridge. NSArray *colors = <#An array of colors#>; CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)colors, locations); The code fragment is shown in context in the following method implementation. Notice also the use of Core Foundation memory management functions where dictated by the Core Foundation memory management rules. - (void)drawRect:(CGRect)rect { CGContextRef ctx = UIGraphicsGetCurrentContext(); CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray(); CGFloat locations[2] = {0.0, 1.0}; NSMutableArray *colors = [NSMutableArray arrayWithObject:(id)[[UIColor darkGrayColor] CGColor]]; [colors addObject:(id)[[UIColor lightGrayColor] CGColor]]; CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)colors, locations); CGColorSpaceRelease(colorSpace); // Release owned Core Foundation object. CGPoint startPoint = CGPointMake(0.0, 0.0); CGPoint endPoint = CGPointMake(CGRectGetMaxX(self.bounds), CGRectGetMaxY(self.bounds)); CGContextDrawLinearGradient(ctx, gradient, startPoint, endPoint, kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation); CGGradientRelease(gradient); // Release owned Core Foundation object. } Transitioning to ARC Release Notes Managing Toll-Free Bridging 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 14Common Issues While Converting a Project When migrating existing projects, you are likely to run into various issues. Here are some common issues, together with solutions. You can’t invoke retain, release, or autorelease. This is a feature. You also can’t write: while ([x retainCount]) { [x release]; } You can’t invoke dealloc. You typically invoke dealloc if you are implementing a singleton or replacing an object in an init methods. Forsingletons, use the shared instance pattern. In init methods, you don't have to call dealloc anymore, because the object will be freed when you overwrite self. You can’t use NSAutoreleasePool objects. Use the new @autoreleasepool{} construct instead. This forces a block structure on your autorelease pool, and is about six times faster than NSAutoreleasePool. @autoreleasepool even works in non-ARC code. Because @autoreleasepool is so much faster than NSAutoreleasePool, many old “performance hacks” can simply be replaced with unconditional @autoreleasepool. The migrator handles simple uses of NSAutoreleasePool, but it can't handle complex conditional cases, or cases where a variable is defined inside the body of the new @autoreleasepool and used after it. ARC requires you to assign the result of [super init] to self in init methods. The following is invalid in ARC init methods: [super init]; The simple fix is to change it to: self = [super init]; The proper fix is to do that, and check the result for nil before continuing: self = [super init]; if (self) { ... Transitioning to ARC Release Notes Common Issues While Converting a Project 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 15You can’t implement custom retain or release methods. Implementing custom retain or release methods breaks weak pointers. There are several common reasons for wanting to provide custom implementations: ● Performance. Please don’t do this any more; the implementation of retain and release for NSObject is much faster now. If you still find problems, please file bugs. ● To implement a custom weak pointer system. Use __weak instead. ● To implement singleton class. Use the shared instance pattern instead. Alternatively, use class instead of instance methods, which avoids having to allocate the object at all. “Assigned” instance variables become strong. Before ARC, instance variables were non-owning references—directly assigning an object to an instance variable did not extend the lifetime of the object. To make a property strong, you usually implemented or synthesized accessor methods that invoked appropriate memory management methods; in contrast, you may have implemented accessor methods like those shown in the following example to maintain a weak property. @interface MyClass : Superclass { id thing; // Weak reference. } // ... @end @implementation MyClass - (id)thing { return thing; } - (void)setThing:(id)newThing { thing = newThing; } // ... Transitioning to ARC Release Notes Common Issues While Converting a Project 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 16@end With ARC, instance variables are strong references by default—assigning an object to an instance variable directly does extend the lifetime of the object. The migration tool is not able to determine when an instance variable is intended to be weak. To maintain the same behavior as before, you must mark the instance variable as being weak, or use a declared property. @interface MyClass : Superclass { id __weak thing; } // ... @end @implementation MyClass - (id)thing { return thing; } - (void)setThing:(id)newThing { thing = newThing; } // ... @end Or: @interface MyClass : Superclass @property (weak) id thing; // ... @end @implementation MyClass @synthesize thing; // ... @end Transitioning to ARC Release Notes Common Issues While Converting a Project 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 17You can't use strong ids in C structures. For example, the following code won’t compile: struct X { id x; float y; }; This is because x defaults to strongly retained and the compiler can’t safely synthesize all the code required to make it work correctly. For example, if you pass a pointer to one of these structures through some code that ends up doing a free, each id would have to be released before the struct is freed. The compiler cannot reliably do this, so strong ids in structures are disallowed completely in ARC mode. There are a few possible solutions: 1. Use Objective-C objects instead of structs. This is considered to be best practice anyway. 2. If using Objective-C objects is sub-optimal, (maybe you want a dense array of these structs) then consider using a void* instead. This requires the use of the explicit casts, described below. 3. Mark the object reference as __unsafe_unretained. This approach may be useful for the semi-common patterns like this: struct x { NSString *S; int X; } StaticArray[] = { @"foo", 42, @"bar, 97, ... }; You declare the structure as: struct x { NSString * __unsafe_unretained S; int X; } This may be problematic and is unsafe if the object could be released out from under the pointer, but it is very useful for things that are known to be around forever like constant string literals. You can’t directly cast between id and void* (including Core Foundation types). This is discussed in greater detail in “Managing Toll-Free Bridging” (page 12). Transitioning to ARC Release Notes Common Issues While Converting a Project 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 18Frequently Asked Questions How do I think about ARC? Where does it put the retains/releases? Try to stop thinking about where the retain/release calls are put and think about your application algorithms instead. Think about “strong and weak” pointers in your objects, about object ownership, and about possible retain cycles. Do I still need to write dealloc methods for my objects? Maybe. Because ARC does not automate malloc/free, management of the lifetime of Core Foundation objects, file descriptors, and so on, you still free such resources by writing a dealloc method. You do not have to (indeed cannot) release instance variables, but you may need to invoke [self setDelegate:nil] on system classes and other code that isn’t compiled using ARC. dealloc methods in ARC do not require—or allow—a call to [super dealloc]; the chaining to super is handled and enforced by the runtime. Are retain cycles still possible in ARC? Yes. ARC automates retain/release, and inherits the issue of retain cycles. Fortunately, code migrated to ARC rarely starts leaking, because properties already declare whether the properties are retaining or not. How do blocks work in ARC? Blocks “just work” when you pass blocks up the stack in ARC mode, such as in a return. You don’t have to call Block Copy any more. You still need to use [^{} copy] when passing “down” the stack into arrayWithObjects: and other methods that do a retain. The one thing to be aware of isthat NSString * __block myString isretained in ARC mode, not a possibly dangling pointer. To get the previous behavior, use __block NSString * __unsafe_unretained myString or (better still) use __block NSString * __weak myString. Can I develop applications for OS X with ARC using Snow Leopard? No. The Snow Leopard version of Xcode 4.2 doesn’t support ARC at all on OS X, because it doesn’t include the 10.7 SDK. Xcode 4.2 for Snow Leopard does support ARC for iOS though, and Xcode 4.2 for Lion supports both OS X and iOS. This means you need a Lion system to build an ARC application that runs on Snow Leopard. Can I create a C array of retained pointers under ARC? Transitioning to ARC Release Notes Frequently Asked Questions 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 19Yes, you can, as illustrated by this example: // Note calloc() to get zero-filled memory. __strong SomeClass **dynamicArray = (__strong SomeClass **)calloc(sizeof(SomeClass *), entries); for (int i = 0; i < entries; i++) { dynamicArray[i] = [[SomeClass alloc] init]; } // When you're done, set each entry to nil to tell ARC to release the object. for (int i = 0; i < entries; i++) { dynamicArray[i] = nil; } free(dynamicArray); There are a number of aspects to note: ● You will need to write __strong SomeClass ** in some cases, because the default is __autoreleasing SomeClass **. ● The allocated memory must be zero-filled. ● You must set each element to nil before freeing the array (memset or bzero will not work). ● You should avoid memcpy or realloc. Is ARC slow? It depends on what you’re measuring, but generally “no.” The compiler efficiently eliminates many extraneous retain/release calls and much effort has been invested in speeding up the Objective-C runtime in general. In particular, the common “return a retain/autoreleased object” pattern is much faster and does not actually put the object into the autorelease pool, when the caller of the method is ARC code. One issue to be aware of is that the optimizer is not run in common debug configurations, so expect to see a lot more retain/release traffic at -O0 than at -Os. Does ARC work in ObjC++ mode? Yes. You can even put strong/weak ids in classes and containers. The ARC compiler synthesizes retain/release logic in copy constructors and destructors etc to make this work. Which classes don’t support weak references? Transitioning to ARC Release Notes Frequently Asked Questions 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 20You cannot currently create weak references to instances of the following classes: NSATSTypesetter, NSColorSpace, NSFont, NSMenuView, NSParagraphStyle, NSSimpleHorizontalTypesetter, and NSTextView. Note: In addition, in OS X v10.7, you cannot create weak referencesto instances of NSFontManager, NSFontPanel, NSImage, NSTableCellView, NSViewController, NSWindow, and NSWindowController. In addition, in OS X v10.7 no classes in the AV Foundation framework support weak references. For declared properties, you should use assign instead of weak; for variables you should use __unsafe_unretained instead of __weak. In addition, you cannot create weak references from instances of NSHashTable, NSMapTable, or NSPointerArray under ARC. What do I have to do when subclassing NSCell or another class that uses NSCopyObject? Nothing special. ARC takes care of cases where you had to previously add extra retains explicitly. With ARC, all copy methods should just copy over the instance variables. Can I opt out of ARC for specific files? Yes. Transitioning to ARC Release Notes Frequently Asked Questions 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 21When you migrate a project to use ARC, the -fobjc-arc compiler flag is set as the default for all Objective-C source files. You can disable ARC for a specific class using the -fno-objc-arc compiler flag for that class. In Xcode, in the target Build Phasestab, open the Compile Sources group to reveal the source file list. Double-click the file for which you want to set the flag, enter -fno-objc-arc in the pop-up panel, then click Done. Is GC (Garbage Collection) deprecated on the Mac? Garbage collection is deprecated in OS X Mountain Lion v10.8, and will be removed in a future version of OS X. Automatic Reference Counting is the recommended replacement technology. To aid in migrating existing applications, the ARC migration tool in Xcode 4.3 and later supports migration of garbage collected OS X applications to ARC. Note: For apps targeting the Mac App Store, Apple strongly recommends you replace garbage collection with ARC as soon as feasible, because Mac App Store guidelines (see App Store Review Guidelines for Mac Apps) prohibit the use of deprecated technologies. Transitioning to ARC Release Notes Frequently Asked Questions 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 22This table describes the changes to Transitioning to ARC Release Notes. Date Notes 2012-07-17 Updated for OS X v10.8. 2012-03-14 Noted that under ARC properties are strong by default. 2012-02-16 Corrected out-of-date advice regarding C++ integration. 2012-01-09 Added note to search for weak references. First version of a document that describes how to transition code from manual retain/release to use ARC. 2011-10-12 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 23 Document Revision HistoryApple Inc. © 2012 Apple Inc. All rights reserved. No part of this publication may be reproduced, stored in a retrievalsystem, or transmitted, in any form or by any means, mechanical, electronic, photocopying, recording, or otherwise, without prior written permission of Apple Inc., with the following exceptions: Any person is hereby authorized to store documentation on a single computer for personal use only and to print copies of documentation for personal use provided that the documentation contains Apple’s copyright notice. No licenses, express or implied, are granted with respect to any of the technology described in this document. Apple retains all intellectual property rights associated with the technology described in this document. This document is intended to assist application developers to develop applications only for Apple-labeled computers. Apple Inc. 1 Infinite Loop Cupertino, CA 95014 408-996-1010 Apple, the Apple logo, Cocoa, Leopard, Mac, Objective-C, OS X, Snow Leopard, and Xcode are trademarks of Apple Inc., registered in the U.S. and other countries. App Store and Mac App Store are service marks of Apple Inc. iOS is a trademark or registered trademark of Cisco in the U.S. and other countries and is used under license. Even though Apple has reviewed this document, APPLE MAKES NO WARRANTY OR REPRESENTATION, EITHER EXPRESS OR IMPLIED, WITH RESPECT TO THIS DOCUMENT, ITS QUALITY, ACCURACY, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.ASARESULT, THISDOCUMENT IS PROVIDED “AS IS,” AND YOU, THE READER, ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND ACCURACY. IN NO EVENT WILL APPLE BE LIABLE FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL,OR CONSEQUENTIAL DAMAGES RESULTING FROM ANY DEFECT OR INACCURACY IN THIS DOCUMENT, even if advised of the possibility of such damages. THE WARRANTY AND REMEDIES SET FORTH ABOVE ARE EXCLUSIVE AND IN LIEU OF ALL OTHERS, ORAL OR WRITTEN, EXPRESS OR IMPLIED. No Apple dealer, agent, or employee is authorized to make any modification, extension, or addition to this warranty. Some states do not allow the exclusion or limitation of implied warranties or liability for incidental or consequential damages, so the above limitation or exclusion may not apply to you. This warranty gives you specific legal rights, and you may also have other rights which vary from state to state. App Sandbox Design GuideContents About App Sandbox 5 At a Glance 5 How to Use This Document 6 Prerequisites 6 See Also 6 App Sandbox Quick Start 8 Create the Xcode Project 8 Enable App Sandbox 10 Create a Code Signing Certificate for Testing 10 Specify the Code Signing Identity 11 Confirm That the App Is Sandboxed 12 Resolve an App Sandbox Violation 13 App Sandbox in Depth 15 The Need for a Last Line of Defense 15 Container Directories and File System Access 16 The App Sandbox Container Directory 16 The Application Group Container Directory 17 Powerbox and File System Access Outside of Your Container 17 Open and Save Dialog Behavior with App Sandbox 19 Entitlements and System Resource Access 20 Security-Scoped Bookmarks and Persistent Resource Access 21 Two Distinct Types of Security-Scoped Bookmark 21 Using Security-Scoped Bookmarks 22 App Sandbox and Code Signing 24 External Tools, XPC Services, and Privilege Separation 26 Designing for App Sandbox 27 Six Steps for Adopting App Sandbox 27 Determine Whether Your App Is Suitable for Sandboxing 27 Design a Development and Distribution Strategy 29 Resolve API Incompatibilities 29 Opening, Saving, and Tracking Documents 29 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 2Retaining Access to File System Resources 29 Creating a Login Item for Your App 30 Accessing User Data 30 Accessing Preferences of Other Apps 30 Apply the App Sandbox Entitlements You Need 31 Add Privilege Separation Using XPC 32 Implement a Migration Strategy 32 Migrating an App to a Sandbox 33 Creating a Container Migration Manifest 34 Undoing a Migration for Testing 36 An Example Container Migration Manifest 36 Use Variables to Specify Support-File Directories 37 Document Revision History 39 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 3 ContentsTables and Listings App Sandbox in Depth 15 Table 2-1 The App Sandbox mindset 15 Table 2-2 Open and Save class inheritance with App Sandbox 20 Migrating an App to a Sandbox 33 Table 4-1 How system directory variables resolve depending on context 37 Table 4-2 Variables for support-file directories 38 Listing 4-1 An example container migration manifest 36 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 4App Sandbox provides a last line of defense against stolen, corrupted, or deleted user data if malicious code exploits your app. App Sandbox also minimizes the damage from coding errors in your app or in frameworks you link against. Your app All system resources All user data Unrestricted access Other system resources Other user data Your app Unrestricted access No access Without App Sandbox With App Sandbox Your sandbox App Sandbox is an access control technology provided in OS X, enforced at the kernel level. Its strategy is twofold: 1. App Sandbox enables you to describe how your app interacts with the system. The system then grants your app the access it needs to get its job done, and no more. 2. App Sandbox allows the user to transparently grant your app additional access by way of Open and Save dialogs, drag and drop, and other familiar user interactions. At a Glance Based on simple security principles, App Sandbox provides strong defense against damage from malicious code. The elements of App Sandbox are container directories, entitlements, user-determined permissions, privilege separation, and kernel enforcement. It’s up to you to understand these elements and then to use your understanding to create a plan for adopting App Sandbox. 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 5 About App SandboxRelevant chapters: “App Sandbox Quick Start” (page 8), “App Sandbox in Depth” (page 15) After you understand the basics, look at your app in light of this security technology. First, determine if your app issuitable forsandboxing. Most apps are. Design your developmentstrategy, resolve API incompatibilities, determine which entitlements you need, and consider applying privilege separation to maximize the defensive value of App Sandbox. Relevant chapter: “Designing for App Sandbox” (page 27) Some file system locations that your app uses are different when you adopt App Sandbox. In particular, you gain a container directory to be used for app support files, databases, caches, and other files apart from user documents. OS X and Xcode support migration of files from their legacy locations to your container. Relevant chapter: “Migrating an App to a Sandbox” (page 33) How to Use This Document To get up and running with App Sandbox, perform the tutorial in “App Sandbox Quick Start” (page 8). Before sandboxing an app you intend to distribute, be sure you understand “App Sandbox in Depth” (page 15). When you’re ready to startsandboxing a new app, or to convert an existing app to adopt App Sandbox, read “Designing for App Sandbox” (page 27). If you’re providing a new, sandboxed version of your app to users already running a version that is not sandboxed, read “Migrating an App to a Sandbox” (page 33). Prerequisites Before you read this document, make sure you understand the place of App Sandbox and code signing in the overall OS X development process by reading Mac App Programming Guide . See Also To complement the damage containment provided by App Sandbox, you must provide a first line of defense by adopting secure coding practices throughout your app. To learn how, read Security Overview and Secure Coding Guide . About App Sandbox How to Use This Document 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 6An important step in adopting App Sandbox is requesting entitlements for your app. For details on all the available entitlements, see Entitlement Key Reference . You can enhance the benefits of App Sandbox in a full-featured app by implementing privilege separation. You do this using XPC, an OS X implementation of interprocess communication. To learn the details of using XPC, read Daemons and Services Programming Guide . About App Sandbox See Also 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 7In this Quick Start you get an OS X app up and running in a sandbox. You verify that the app isindeed sandboxed and then learn how to troubleshoot and resolve a typical App Sandbox error. The apps you use are Xcode, Keychain Access, Activity Monitor, and Console. Create the Xcode Project The app you create in this Quick Start uses a WebKit web view and consequently uses a network connection. Under App Sandbox, network connections don’t work unless you specifically allow them—making this a good example app for learning about sandboxing. To create the Xcode project for this Quick Start 1. In Xcode 4, create a new Xcode project for an OS X Cocoa application. ● Name the project AppSandboxQuickStart. ● Set a company identifier, such as com.yourcompany, if none is already set. ● Ensure that Use Automatic Reference Counting is selected and that the other checkboxes are unselected. 2. In the project navigator, click the MainMenu nib file. The Interface Builder canvas appears. 3. In the Xcode dock, click the Window object. The app’s window is now visible on the canvas. 4. In the object library (in the utilities area), locate the WebView object. 5. Drag a web view onto the window on the canvas. 6. (Optional) To improve the display of the web view in the running app, perform the following steps: ● Drag the sizing controls on the web view so that it completely fills the window’s main view. ● Using the size inspector for the web view, ensure that all of the inner and outer autosizing contraints are active. 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 8 App Sandbox Quick Start7. Create and connect an outlet for the web view in the AppDelegate class. In Xcode, use the following specification: Outlet connection source The WebView object of the MainMenu nib file. Outlet variable location The interface block of the AppDelegate.h header file. Outlet name webView Storage weak At this point, if you were to build the app, Xcode would report an error because the project doesn’t yet use WebKit but does have a web view in the nib file. You take care of this in the next step. 8. Add the WebKit framework to the app. ● Import the WebKit framework by adding the following statement above the interface block in the AppDelegate.h header file: #import ● Link the WebKit framework to the Quick Start project as a required framework. 9. Add the following awakeFromNib method to the AppDelegate.m implementation file: - (void) awakeFromNib { [self.webView.mainFrame loadRequest: [NSURLRequest requestWithURL: [NSURL URLWithString: @"http://www.apple.com"]]]; } On application launch, this method requeststhe specified URL from the computer’s network connection and then sends the result to the web view for display. Now, build and run the app—which is not yet sandboxed and so has free access to system resources including its network sockets. Confirm that the app’s window displays the page you specified in the awakeFromNib method. When done, quit the app. App Sandbox Quick Start Create the Xcode Project 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 9Enable App Sandbox You enable App Sandbox by selecting a checkbox in the Xcode target editor. In Xcode, click the project file in the project navigator and click the AppSandboxQuickStart target, if they’re not already selected. View the Summary tab of the target editor. To enable App Sandbox for the project 1. In the Summary tab of the target editor, click Enable Entitlements. An entitlement is a key-value pair, defined in a property list file, that confers a specific capability or security permission to a target. When you click Enable Entitlements, Xcode automatically checks the Code Sign Application checkbox and the Enable App Sandboxing checkbox. Together, these are the essential projectsettingsfor enabling App Sandbox. When you click Enable Entitlements, Xcode also creates a .entitlements property list file, visible in the project navigator. As you use the graphical entitlementsinterface in the target editor, Xcode updates the property list file. 2. Clear the contents of the iCloud entitlement fields. This Quick Start doesn’t use iCloud. Because Xcode automatically adds iCloud entitlement values when you enable entitlements, delete them as follows: ● In the Summary tab of the target editor,select and then delete the content of the iCloud Key-Value Store field. ● Click the top row in the iCloud Containers field and click the minus button. At this point in the Quick Start, you have enabled App Sandbox but have not yet provided a code signing identity for the Xcode project. Consequently, if you attempt to build the project now, the build fails. You take care of this in the next two sections. Create a Code Signing Certificate for Testing To build a sandboxed app in Xcode, you must have a code signing certificate and its associated private key in your keychain, and then use that certificate’s code signing identity in the project. The entitlements you specify, including the entitlement that enables App Sandbox, become part of the app’s code signature when you build the project. App Sandbox Quick Start Enable App Sandbox 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 10In this section, you create a code signing certificate. This simplified process lets you stay focused on the steps for enabling a sandbox. Important: A code signing certificate that you create as described in this Quick Start is not appropriate to use with an app you intend to distribute. Before you work on sandboxing an app you plan to distribute, read “App Sandbox and Code Signing” (page 24). To create a code signing certificate for testing App Sandbox 1. In Keychain Access (available in Applications/Utilities), choose KeyChain Access > Certificate Assistant > Create a Certificate. Certificate Assistant opens. Note: Before you invoke the “Create a Certificate” menu command, ensure that no key is selected in the Keychain Access main window. If a key is selected, the menu command is not available. 2. In Certificate Assistant, name the certificate something like My Test Certificate. 3. Complete the configuration of the certificate as follows: Identity type Self Signed Root Certificate type Code Signing Let me override defaults unchecked 4. Click Create. 5. In the alert that appears, click Continue. 6. In the Conclusion window, click Done. Your new code signing certificate, and its associated public and private keys, are now available in Keychain Access. Specify the Code Signing Identity Now, configure the Xcode project to use the code signing identity from the certificate you created in the previous task. App Sandbox Quick Start Specify the Code Signing Identity 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 11To specify the code signing identity for the project 1. View the Build Settings tab in the project editor. Take care that you are using the project editor, not the target editor. 2. In the Code Signing section, locate the Code Signing Identity row. 3. Click the value area of the Code Signing Identity row. 4. In the popup menu that opens, choose Other. 5. In the text entry window that opens, enter the exact name of the newly created code signing certificate, then press . If you’re using the suggested name from thisQuick Start, the name you enter is My Test Certificate. Now, build the app. The codesign tool may display an alert asking for permission to use the new certificate. If you do see this alert, click Always Allow. Confirm That the App Is Sandboxed Build and run the Quick Start app. The window opens, but if the app issuccessfully sandboxed, no web content appears. This is because you have not yet conferred permission to access a network connection. Apart from blocked behavior, there are two specific signs that an OS X app is successfully sandboxed. To confirm that the Quick Start app is successfully sandboxed 1. In Finder, look at the contents of the ~/Library/Containers/ folder. If the Quick Start app is sandboxed, there is now a container folder named after your app. The name includes the company identifier for the project, so the complete folder name would be, for example, com.yourcompany.AppSandboxQuickStart. The system creates an app’s container folder, for a given user, the first time the user runs the app. 2. In Activity Monitor, check that the system recognizes the app as sandboxed. ● Launch Activity Monitor (available in /Applications/Utilities). ● In Activity Monitor, choose View > Columns. Ensure that the Sandbox menu item is checked. ● In the Sandbox column, confirm that the value for the Quick Start app is Yes. App Sandbox Quick Start Confirm That the App Is Sandboxed 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 12To make it easier to locate the app in Activity monitor, enter the name of the Quick Start app in the Filter field. Tip: If the app crashes when you attempt to run it,specifically by receiving an EXC_BAD_INSTRUCTION signal, the most likely reason is that you previously ran a sandboxed app with the same bundle identifier but a different code signature. This crashing upon launch is an App Sandbox security feature that prevents one app from masquerading as another and thereby gaining access to the other app’s container. You learn how to design and build your apps, in light of this security feature, in “App Sandbox and Code Signing” (page 24). Resolve an App Sandbox Violation An App Sandbox violation occurs if your app tries to do something that App Sandbox does not allow. For example, you have already seen in this Quick Start that the sandboxed app is unable to retrieve content from the web. Fine-grained restriction over access to system resources is the heart of how App Sandbox provides protection should an app become compromised by malicious code. The most common source of App Sandbox violations is a mismatch between the entitlement settings you specified in Xcode and the needs of your app. In this section you observe and then correct an App Sandbox violation. To diagnose an App Sandbox violation 1. Build and run the Quick Start app. The app starts normally, but fails to display the webpage specified in its awakeFromNib method (as you’ve previously observed in “Confirm That the App Is Sandboxed” (page 12)). Because displaying the webpage worked correctly before you sandboxed the app, it is appropriate in this case to suspect an App Sandbox violation. 2. Open Console (available in /Applications/Utilities/) and ensure that All Messages is selected in the sidebar. In the filter field of the Console window, enter sandboxd to display only App Sandbox violations. sandboxd is the name of the App Sandbox daemon that reports on sandbox violations. The relevant messages, as displayed in Console, look similar to the following: 3:56:16 pm sandboxd: ([4928]) AppSandboxQuickS(4928) deny network-outbound 111.30.222.15:80 3:56:16 pm sandboxd: ([4928]) AppSandboxQuickS(4928) deny system-socket App Sandbox Quick Start Resolve an App Sandbox Violation 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 13The problem that generates these console messages is that the Quick Start app does not yet have the entitlement for outbound network access. Tip: To see the full backtraces for either violation, click the paperclip icon near the right edge of the corresponding Console message. The steps in the previous task illustrate the general pattern to use for identifying App Sandbox violations: 1. Confirm that the violation occurs only with App Sandbox enabled in your project. 2. Provoke the violation (such as by attempting to use a network connection, if your app is designed to do that). 3. Look in Console for sandboxd messages. There is also a simple, general pattern to use for resolving such violations. To resolve the App Sandbox violation by adding the appropriate entitlement 1. Quit the Quick Start app. 2. In the Summary tab of the target editor, look for the entitlement that corresponds to the reported sandboxd violation. In this case, the primary error is deny network-outbound. The corresponding entitlement is Allow Outgoing Network Connections. 3. In the Summary tab of the target editor, select the Allow Outgoing Network Connections checkbox. Doing so applies a TRUE value, for the needed entitlement, to the Xcode project. 4. Build and run the app. The intended webpage now displays in the app. In addition, there are no new App Sandbox violation messages in Console. App Sandbox Quick Start Resolve an App Sandbox Violation 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 14The access control mechanisms used by App Sandbox to protect user data are small in number and easy to understand. But the specific steps for you to take, as you adopt App Sandbox, are unique to your app. To determine what those steps are, you must understand the key concepts for this technology. The Need for a Last Line of Defense You secure your app against attack from malware by following the practices recommended in Secure Coding Guide . But despite your best efforts to build an invulnerable barrier—by avoiding buffer overflows and other memory corruptions, preventing exposure of user data, and eliminating other vulnerabilities—your app can be exploited by malicious code. An attacker needs only to find a single hole in your defenses, or in any of the frameworks and libraries that you link against, to gain control of your app’s interactions with the system. App Sandbox is designed to confront this scenario head on by letting you describe your app’s intended interactions with the system. The system then grants your app only the access your app needs to get its job done. If malicious code gains control of a properly sandboxed app, it is left with access to only the files and resources in the app’s sandbox. To successfully adopt App Sandbox, use a different mindset than you might be accustomed to, as suggested in Table 2-1. Table 2-1 The App Sandbox mindset When developing… When adopting App Sandbox… Add features Minimize system resource use Take advantage of access throughout your app Partition functionality, then distrust each part Use the most convenient API Use the most secure API View restrictions as limitations View restrictions as safeguards 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 15 App Sandbox in DepthWhen designing for App Sandbox, you are planning for the following worst-case scenario: Despite your best efforts, malicious code breaches an unintended security hole—either in your code or in a framework you’ve linked against. Capabilities you’ve added to your app become capabilities of the hostile code. Keep this in mind as you read the rest of this document. Container Directories and File System Access When you adopt App Sandbox, the system provides a special directory for use by your app—and only by your app—called a container. Each user on a system gets an individual container for your app, within their home directory; your app has unfettered read/write access to the container for the current user. The App Sandbox Container Directory The container has the following characteristics: ● It is located at a system-defined path, within the user’s home directory, that you can obtain by calling the NSHomeDirectory function. ● Your app has unrestricted read/write access to the container and its subdirectories. ● OS X path-finding APIs (above the POSIX layer) refer to locations that are specific to your app. Most of these path-finding APIsrefer to locationsrelative to your app’s container. For example, the container includes an individual Library directory (specified by the NSLibraryDirectory search path constant) for use only by your app, with individual Application Support and Preferences subdirectories. Using your container forsupport filesrequires no code change (from the pre-sandbox version of your app) but may require one-time migration, as explained in “Migrating an App to a Sandbox” (page 33). Some path-finding APIs (above the POSIX layer) refer to app-specific locations outside of the user’s home directory. In a sandboxed app, for example, the NSTemporaryDirectory function provides a path to a directory that is outside of the user’s home directory but specific to your app and within your sandbox; you have unrestricted read/write access to it for the current user. The behavior of these path-finding APIs is suitably adjusted for App Sandbox and no code change is needed. ● OS X establishes and enforces the connection between your app and its container by way of your app’s code signature. ● The container isin a hidden location, and so users do not interact with it directly. Specifically, the container is not for user documents. It is for files that your app uses, along with databases, caches, and other app-specific data. For a shoebox-style app, in which you provide the only user interface to the user’s content, that content goes in the container and your app has full access to it. App Sandbox in Depth Container Directories and File System Access 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 16iOS Note: Because it is not for user documents, an OS X container differs from an iOS container—which, in iOS, is the one and only location for user documents. In addition, an iOS container contains the app itself. This is not so in OS X. iCloud Note: Apple’s iCloud technology, as described in “iCloud Storage”, uses the name “container” as well. There is no functional connection between an iCloud container and an App Sandbox container. Thanks to code signing, no other sandboxed app can gain access to your container, even if it attempts to masquerade as your app by using your bundle identifier. Future versions of your app, however—provided that you use the same code signature and bundle identifier—do reuse your app’s container. The time at which a container directory is created for an App Sandbox–enabled app is when the app is first run. Because a container is within a user’s home folder, each user on a system gets their own container for your app. A given user’s container is created when that user first runs your app. The Application Group Container Directory In addition to per-app containers, beginning in OS X v10.7.4, an application can use entitlements to request access to a shared container that is common to multiple applications produced by the same development team. This container is intended for content that is not user-facing, such as shared caches or databases. Applicationsthat are members of an application group also gain the ability to share Mach and POSIX semaphores and to use certain other IPC mechanisms in conjunction with other group members. These group containers are automatically created or added into each app’s sandbox container as determined by the existence of these keys, and are stored in ~/Library/Group Containers/, where can be whatever name you choose. Your app can obtain the path to the group containers by calling the containerURLForSecurityApplicationGroupIdentifier: method of NSURL. For more details, see “Adding an Application to an Application Group” in Entitlement Key Reference . Powerbox and File System Access Outside of Your Container Your sandboxed app can access file system locations outside of its container in the following three ways: ● At the specific direction of the user App Sandbox in Depth Container Directories and File System Access 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 17● By using entitlements for specific file-system locations (described in “Entitlements and System Resource Access” (page 20)) ● When the file system location is in certain directories that are world readable The OS X security technology that interacts with the user to expand yoursandbox is called Powerbox. Powerbox has no API. Your app uses Powerbox transparently when you use the NSOpenPanel and NSSavePanel classes. You enable Powerbox by setting an entitlement using Xcode, as described in “Enabling User-Selected File Access” in Entitlement Key Reference . When you invoke an Open or Save dialog from your sandboxed app, the window that appears is presented not by AppKit but by Powerbox. Using Powerbox is automatic when you adopt App Sandbox—it requires no code change from the pre-sandbox version of your app. Accessory panelsthat you’ve implemented for opening or saving are faithfully rendered and used. Note: When you adopt App Sandbox, there are some important behavioral differences for the NSOpenPanel and NSSavePanel classes, described in “Open and Save Dialog Behavior with App Sandbox” (page 19). The security benefit provided by Powerbox is that it cannot be manipulated programmatically—specifically, there is no mechanism for hostile code to use Powerbox for accessing the file system. Only a user, by interacting with Open and Save dialogs via Powerbox, can use those dialogs to reach portions of the file system outside of your previously established sandbox. For example, if a user saves a new document, Powerbox expands your sandbox to give your app read/write access to the document. When a user of your app specifies they want to use a file or a folder, the system adds the associated path to your app’s sandbox. Say, for example, a user drags the ~/Documents folder onto your app’s Dock tile (or onto your app’s Finder icon, or into an open window of your app), thereby indicating they want to use that folder. In response, the system makes the ~/Documents folder, its contents, and its subfolders available to your app. If a user instead opens a specific file, or saves to a new file, the system makes the specified file, and that file alone, available to your app. In addition, the system automatically permits a sandboxed app to: ● Connect to system input methods ● Invoke services chosen by the user from the Services menu (only those services flagged as “safe” by the service provider are available to a sandboxed app) ● Open files chosen by the user from the Open Recent menu ● Participate with other apps by way of user-invoked copy and paste App Sandbox in Depth Container Directories and File System Access 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 18● Read files that are world readable, in certain directories, including the following directories: ● /bin ● /sbin ● /usr/bin ● /usr/lib ● /usr/sbin ● /usr/share ● /System After a user hasspecified a file they want to use, that file is within your app’ssandbox. The file isthen vulnerable to attack if your app is exploited by malicious code: App Sandbox provides no protection. To provide protection for the files within your sandbox, follow the recommendations in Secure Coding Guide . A critical aspect of following user intent is that throughout OS X, simulation or alteration of user input is not allowed. This has implications for assistive apps, as described in “Determine Whether Your App Is Suitable for Sandboxing” (page 27). By default, files opened or saved by the user remain within your sandbox until your app terminates, except for files that were open at the time that your app terminates. Such files reopen automatically by way of the OS X Resume feature the next time your app launches, and are automatically added back to your app’ssandbox. To provide persistent access to resources located outside of your container, in a way that doesn’t depend on Resume, use security-scoped bookmarks as explained in “Security-Scoped Bookmarks and Persistent Resource Access” (page 21). Open and Save Dialog Behavior with App Sandbox Certain NSOpenPanel and NSSavePanel methods behave differently when App Sandbox is enabled for your app: ● You cannot invoke the OK button using the ok: method. ● You cannot rewrite the user’sselection using the panel:userEnteredFilename:confirmed: method from the NSOpenSavePanelDelegate protocol. In addition, the effective, runtime inheritance path for the NSOpenPanel and NSSavePanel classesis different with App Sandbox, as illustrated in Table 2-2. App Sandbox in Depth Container Directories and File System Access 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 19Table 2-2 Open and Save class inheritance with App Sandbox Without App Sandbox NSOpenPanel : NSSavePanel : NSPanel : NSWindow : NSResponder : NSObject With App Sandbox NSOpenPanel : NSSavePanel : NSObject Because of this runtime difference, an NSOpenPanel or NSSavePanel object inherits fewer methods with App Sandbox. If you attempt to send a message to an NSOpenPanel or NSSavePanel object, and that method is defined in the NSPanel, NSWindow, or NSResponder classes, the system raises an exception. The Xcode compiler does not issue a warning or error to alert you to this runtime behavior. Entitlements and System Resource Access An app that is notsandboxed has accessto all user-accessible system resources—including the built-in camera and microphone, network sockets, printing, and most of the file system. If successfully attacked by malicious code, such an app can behave as a hostile agent with wide-ranging potential to inflict harm. When you enable App Sandbox for your app, you remove all but a minimalset of privileges and then deliberately restore them, one-by-one, using entitlements. An entitlement is a key-value pair that identifies a specific capability, such as the capability to open an outbound network socket. One special entitlement—Enable App Sandboxing—turns on App Sandbox. When you enable sandboxing, Xcode creates a .entitlements property list file and shows it in the project navigator. If your app requires a capability, request it by adding the corresponding entitlement to your Xcode project using the Summary tab of the target editor. If you don’t require a capability, take care to not include the corresponding entitlement. You request entitlements on a target-by-target basis. If your app has a single target—the main application—you request entitlements only forthat target. If you design your app to use a main application along with helpers (in the form of XPC services), you request entitlements individually, and as appropriate, for each target. You learn more about this in “XPC and Privilege Separation” (page 26). You may require finer-grained control over your app’s entitlements than is available in the Xcode target editor. For example, you might request a temporary exception entitlement because App Sandbox does not support a capability your app needs, such as the ability to send Apple events. To work with temporary exception entitlements, use the Xcode property list editor to edit a target’s .entitlements property list file directly. App Sandbox in Depth Entitlements and System Resource Access 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 20Note: If you request a temporary exception entitlement, be sure to follow the guidance regarding entitlements provided on the iTunes Connect website. In particular, use the Review Notes field in iTunes Connect to explain why your app needs the temporary exception. OS X App Sandbox entitlements are described in “Enabling App Sandbox” in Entitlement Key Reference . For a walk-through of requesting an entitlement for a target in an Xcode project,see “App Sandbox Quick Start” (page 8). Security-Scoped Bookmarks and Persistent Resource Access Your app’s access to file-system locations outside of its container—as granted to your app by way of user intent, such as through Powerbox—does not automatically persist across app launches or system restarts. When your app reopens, you have to start over. (The one exception to this is for files open at the time that your app terminates, which remain in your sandbox thanks to the OS X Resume feature). Starting in OS X v10.7.3, you can retain access to file-system resources by employing a security mechanism, known as security-scoped bookmarks, that preserves user intent. Here are a few examples of app features that can benefit from this: ● A user-selected download, processing, or output folder ● An image browser library file, which points to user-specified images at arbitrary locations ● A complex document format that supports embedded media stored in other locations Two Distinct Types of Security-Scoped Bookmark Security-scoped bookmarks, available starting in OS X v10.7.3, support two distinct use cases: ● An app-scoped bookmark provides your sandboxed app with persistent access to a user-specified file or folder. For example, if your app employs a download or processing folder that is outside of the app container, obtain initial access by presenting an NSOpenPanel dialog to obtain the user’s intent to use a specific folder. Then, create an app-scoped bookmark for that folder and store it as part of the app’s configuration (perhaps in a property list file or using the NSUserDefaults class). With the app-scoped bookmark, your app can obtain future access to the folder. ● A document-scoped bookmark provides a specific document with persistent access to a file. App Sandbox in Depth Security-Scoped Bookmarks and Persistent Resource Access 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 21For example, a code editor typically supports the notion of a project document that refers to other files and needs persistent access to those files. Other examples are an image browser or editor that maintains an image library, in which the library file needs persistent accessto the imagesit owns; or a word processor that supports embedded images, multimedia, or font files in its document format. In these cases, you configure the document format (of the project file, library file, word processing document, and so on) to be able to store security-scoped bookmarks to the files a document refers to. Obtain initial access to a referred item by asking for user intent to use that item. Then, create a document-scoped bookmark for the item and store the bookmark as part of the document’s data. A document-scoped bookmark can be resolved by any app that has access to the bookmark data itself and to the document that owns the bookmark. This supports portability, allowing a user, for example, to send a document to another user; the document’s secure bookmarks remain usable for the recipient. The document can be a flat file or a document distributed as a bundle. A document-scoped bookmark can point only to a file, not a folder, and only to a file that is not in a location used by the system (such as /private or /Library). Using Security-Scoped Bookmarks To use either type of security-scoped bookmark requires you to perform five steps: 1. Set the appropriate entitlement in the target that needs to use security-scoped bookmarks. Do this once per target as part of configuring your Xcode project. 2. Create a security-scoped bookmark. Do this when a user has indicated intent (such as via Powerbox) to use a file-system resource outside of your app’s container, and you want to preserve your app’s ability to access the resource. 3. Resolve the security-scoped bookmark. Do this when your app later (for example, after app relaunch) needs access to a resource you bookmarked in step 2. The result of this step is a security-scoped URL. 4. Explicitly indicate that you want to use the file-system resource whose URL you obtained in step 3. Do this immediately after obtaining the security-scoped URL (or, when you later want to regain access to the resource after having relinquished your access to it). 5. When done using the resource, explicitly indicate that you want to stop using it. Do this as soon as you know that you no longer need access to the resource (typically, after you close it). After you relinquish access to a file-system resource, to use that resource again you must return to step 4 (to again indicate you want to use the resource). If your app is relaunched, you must return to step 3 (to resolve the security-scoped bookmark). App Sandbox in Depth Security-Scoped Bookmarks and Persistent Resource Access 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 22The first step in the preceding list, requesting entitlements, is the prerequisite for using either type of security-scoped bookmark. Perform this step as follows: ● To use app-scoped bookmarksin a target,setthe com.apple.security.files.bookmarks.app-scope entitlement value to true. ● To use document-scoped bookmarks in a target, set the com.apple.security.files.bookmarks.document-scope entitlement value to true. You can request either or both of these entitlements in a target, as needed. These entitlements are available starting in OS X v10.7.3 and are described in “Enabling Security-Scoped Bookmark and URL Access” in Entitlement Key Reference . With the appropriate entitlements, you can create a security-scoped bookmark by calling the bookmarkDataWithOptions:includingResourceValuesForKeys:relativeToURL:error: method of the NSURL class (or its Core Foundation equivalent, the CFURLCreateBookmarkData function). When you later need access to a bookmarked resource, resolve its security-scoped bookmark by calling the the URLByResolvingBookmarkData:options:relativeToURL:bookmarkDataIsStale:error:method of the NSURL class (or its Core Foundation equivalent, the CFURLCreateByResolvingBookmarkData function). In a sandboxed app, you cannot access the file-system resource that a security-scoped URL points to until you call the startAccessingSecurityScopedResource method (or its Core Foundation equivalent, the CFURLStartAccessingSecurityScopedResource function) on the URL. When you no longer need access to a resource that you obtained using security scope (typically, after you close the resource) you must call the stopAccessingSecurityScopedResource method (or its Core Foundation equivalent, the CFURLStopAccessingSecurityScopedResource function) on the resource’s URL. Calls to start and stop access are nestable on a per-process basis. This means that if your app calls the start method on a URL twice, to fully relinquish access to the referenced resource you must call the corresponding stop method twice. If you call the stop method on a URL whose referenced resource you do not have access to, nothing happens. Warning: You must balance every call to the startAccessingSecurityScopedResource method with a corresponding call to the stopAccessingSecurityScopedResource method. If you fail to relinquish your access when you no longer need a file-system resource, your app leaks kernel resources. If sufficient kernel resources are leaked, your app loses its ability to add file-system locations to its sandbox, such as via Powerbox or security-scoped bookmarks, until relaunched. App Sandbox in Depth Security-Scoped Bookmarks and Persistent Resource Access 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 23For detailed descriptions of the methods, constants, and entitlementsto use for implementing security-scoped bookmarks in your app, read NSURL Class Reference or CFURL Reference , and read “Enabling Security-Scoped Bookmark and URL Access” in Entitlement Key Reference . App Sandbox and Code Signing After you enable App Sandbox and specify other entitlements for a target in your Xcode project, you must code sign the project. Take note of the distinction between how you set entitlements and how you set a code signing identity: ● Use the Xcode target editor to set entitlements on a target-by-target basis ● Use the Xcode project build settings to set the code signing identity for a project as a whole You must perform code signing because entitlements (including the special entitlement that enables App Sandbox) are built into an app’s code signature. From another perspective, an unsigned app is not sandboxed and has only default entitlements, regardless of settings you’ve applied in the Xcode target editor. OS X enforces a tie between an app’s container and the app’s code signature. This important security feature ensures that no other sandboxed app can access your container. The mechanism works as follows: After the system creates a container for an app, each time an app with the same bundle ID launches, the system checks that the app’s code signature matches a code signature expected by the container. If the system detects a mismatch, it prevents the app from launching. OS X’s enforcement of container integrity impacts your development and distribution cycle. This is because, in the course of creating and distributing an app, the app is code signed using various signatures. Here’s how the process works: 1. Before you create a project, you obtain two code signing certificatesfrom Apple: a development certificate and a distribution certificate. (To learn how to obtain code signing certificates, read “Creating Signing Certificates” in Tools Workflow Guide for Mac .) For development and testing, you sign your app with the development code signature. 2. When the Mac App Store distributes your app, it is signed with an Apple code signature. For testing and debugging, you may want to run both versions of your app: the version you sign and the version Apple signs. But OS X sees the Apple-signed version of your app as an intruder and won’t allow it to launch: Its code signature does not match the one expected by your app’s existing container. If you try to run the Apple-signed version of your app, you get a crash report containing a statement similar to this: App Sandbox in Depth App Sandbox and Code Signing 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 24Exception Type: EXC_BAD_INSTRUCTION (SIGILL) The solution is to adjust the access control list (ACL) on your app’s container to recognize the Apple-signed version of your app. Specifically, you add the designated code requirement of the Apple-signed version of your app to the app container’s ACL. To adjust an ACL to recognize an Apple-signed version of your app 1. Open Terminal (in /Applications/Utilities). 2. Open a Finder window that contains the Apple-signed version of your app. 3. In Terminal, enter the following command: asctl container acl add -file In place of the placeholder, substitute the path to the Apple-signed version of your app. Instead of manually typing the path, you can drag the app’s Finder icon to the Terminal window. The container’s ACL now includes the designated code requirements for both versions of your app. OS X then allows you to run either version of your app. You can use this same technique to share a container between (1) a version of an app that you initially signed with a self-generated code signature, such as the one you created in “App Sandbox Quick Start” (page 8), and (2) a later version that you signed with a development code signature from Apple. You can view the list of code requirements in a container’s ACL. For example, after adding the designated code requirement for the Apple-signed version of your app, you can confirm that the container’s ACL lists two permissible code requirements. To display the list of code requirements in a container’s ACL 1. Open Terminal (in /Applications/Utilities). 2. In Terminal, enter the following command: asctl container acl list -bundle In place of the placeholder,substitute the name of your app’s container directory. (The name of your app’s container directory is typically the same as your app’s bundle identifier.) App Sandbox in Depth App Sandbox and Code Signing 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 25For more information about working with App Sandbox container access control lists and their code requirements, read the man page for the asctl (App Sandbox control) tool. External Tools, XPC Services, and Privilege Separation Some app operations are more likely to be targets of malicious exploitation. Examples are the parsing of data received over a network, and the decoding of video frames. By using XPC, you can improve the effectiveness of the damage containment offered by App Sandbox by separating such potentially dangerous activities into their own address spaces. XPC is an OS X interprocess communication technology that complements App Sandbox by enabling privilege separation. Privilege separation, in turn, is a development strategy in which you divide an app into pieces according to the system resource access that each piece needs. The component pieces that you create are called XPC services. You create an XPC service as an individual target in your Xcode project. Each service gets its own sandbox—specifically, it gets its own container and its own set of entitlements. In addition, an XPC service that you include with your app is accessible only by your app. These advantages add up to making XPC the best technology for implementing privilege separation in an OS X app. By contrast, a child process created by using the posix_spawn function, by calling fork and exec (discouraged), or by using the NSTask class simply inherits the sandbox of the process that created it. You cannot configure a child process’s entitlements. For these reasons, child processes do not provide effective privilege separation. To use XPC with App Sandbox: ● Confer minimal privileges to each XPC service, according to its needs. ● Design the data transfers between the main app and each XPC service to be secure. ● Structure your app’s bundle appropriately. The life cycle of an XPC service, and its integration with Grand Central Dispatch (GCD), is managed entirely by the system. To obtain this support, you need only to structure your app’s bundle correctly. For more on XPC, see “Creating XPC Services” in Daemons and Services Programming Guide . App Sandbox in Depth External Tools, XPC Services, and Privilege Separation 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 26There’s a common, basic workflow for designing or converting an app for App Sandbox. The specific steps to take for your particular app, however, are as unique as your app. To create a work plan for adopting App Sandbox, use the process outlined here, along with the conceptual understanding you have from the earlier chapters in this document. Six Steps for Adopting App Sandbox The workflow to convert an OS X app to work in a sandbox typically consists of the following six steps: 1. Determine whether your app is suitable for sandboxing. 2. Design a development and distribution strategy. 3. Resolve API incompatibilities. 4. Apply the App Sandbox entitlements you need. 5. Add privilege separation using XPC. 6. Implement a migration strategy. Determine Whether Your App Is Suitable for Sandboxing Most OS X apps are fully compatible with App Sandbox. If you need behavior in your app that App Sandbox does not allow, consider an alternative approach. For example, if your app depends on hard-coded paths to locationsin the user’s home directory, consider the advantages of using Cocoa and Core Foundation path-finding APIs, which use the sandbox container instead. If you choose to not sandbox your app now, or if you determine that you need a temporary exception entitlement, use Apple’s bug reporting system to let Apple know what’s not working for you. Apple considers feature requests as it develops the OS X platform. Also, if you request a temporary exception, be sure to use the Review Notes field in iTunes Connect to explain why the exception is needed. The following app behaviors are incompatible with App Sandbox: ● Use of Authorization Services 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 27 Designing for App SandboxWith App Sandbox, you cannot do work with the functions described in Authorization Services C Reference . ● Use of accessibility APIs in assistive apps With App Sandbox, you can and should enable your app for accessibility, as described in Accessibility Overview for OS X . However, you cannot sandbox an assistive app such as a screen reader, and you cannot sandbox an app that controls another app. ● Sending Apple events to arbitrary apps With App Sandbox, you can receive Apple events and respond to Apple events, but you cannotsend Apple events to arbitrary apps. By using a temporary exception entitlement, you can enable the sending of Apple eventsto a list ofspecific apps that you specify, as described in Entitlement Key Reference . ● Sending user-info dictionaries in broadcast notifications to other tasks With App Sandbox, you cannot include a user-info dictionary when posting to an NSDistributedNotificationCenter object for messaging other tasks. (You can , as usual, include a user-info dictionary when messaging other parts of your app by way of posting to an NSNotificationCenter object.) ● Loading kernel extensions Loading of kernel extensions is prohibited with App Sandbox. ● Simulation of user input in Open and Save dialogs If your app depends on programmatically manipulating Open or Save dialogs to simulate or alter user input, your app is unsuitable for sandboxing. ● Setting preferences on other apps With App Sandbox, each app maintains its preferences inside its container. Your app has no access to the preferences of other apps. ● Configuring network settings With App Sandbox, your app cannot modify the system’s network configuration (whether with the System Configuration framework, the CoreWLAN framework, or other similar APIs) because doing so requires administrator privileges. ● Terminating other apps With App Sandbox, you cannot use the NSRunningApplication class to terminate other apps. Designing for App Sandbox Determine Whether Your App Is Suitable for Sandboxing 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 28Design a Development and Distribution Strategy During development, you may have occasion to run versions of your app that are signed with different code signatures. After you’ve run your app signed using one signature, the system won’t allow a second version of your app, signed with a second signature, to launch—unless you modify the app’s container. Be sure to understand how to handle this, as described in “App Sandbox and Code Signing” (page 24), as you design your development strategy. When a customer first launches a sandboxed version of your app, the system creates a container for your app. The access control list (ACL) for the container is established at that time, and the ACL istied to the code signature of that version of your app. The implication for you is that all future versions of the app that you distribute must use the same code signature. To learn how to obtain code signing certificatesfrom Apple, read “Creating Signing Certificates” in Tools Workflow Guide for Mac . Resolve API Incompatibilities If you are using OS X APIs in ways that were not intended, or in ways that expose user data to attack, you may encounter incompatibilities with App Sandbox. This section provides some examples of app design that are incompatible with App Sandbox and suggests what you can do instead. Opening, Saving, and Tracking Documents If you are managing documents using any technology other than the NSDocument class, you should convert to using this classto benefit from its built-in App Sandbox support. The NSDocument class automatically works with Powerbox. NSDocument also provides support for keeping documents within your sandbox if the user moves them using the Finder. Remember that the inheritance path of the NSOpenPanel and NSSavePanel classes is different when your app is sandboxed. See “Open and Save Dialog Behavior with App Sandbox” (page 19). If you don’t use the NSDocument class to manage your app’s documents, you can craft your own file-system support for App Sandbox by using the NSFileCoordinator class and the NSFilePresenter protocol. Retaining Access to File System Resources If your app depends on persistent access to file system resources outside of your app’s container, you need to adopt security-scoped bookmarks as described in “Security-Scoped Bookmarks and Persistent Resource Access” (page 21). Designing for App Sandbox Design a Development and Distribution Strategy 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 29Creating a Login Item for Your App To create a login item for your sandboxed app, use the SMLoginItemSetEnabled function (declared in ServiceManagement/SMLoginItem.h) as described in “Adding Login Items Using the Service Management Framework” in Daemons and Services Programming Guide . (With App Sandbox, you cannot create a login item using functions in the LSSharedFileList.h header file. For example, you cannot use the function LSSharedFileListInsertItemURL. Nor can you manipulate the state of launch services, such as by using the function LSRegisterURL.) Accessing User Data OS X path-finding APIs, above the POSIX layer, return paths relative to the container instead of relative to the user’s home directory. If your app, before you sandbox it, accesses locations in the user’s actual home directory (~) and you are using Cocoa or Core Foundation APIs, then, after you enable sandboxing, your path-finding code automatically uses your app’s container instead. For first launch of your sandboxed app, OS X automatically migrates your app’s main preferences file. If your app uses additional support files, perform a one-time migration of those files to the container, as described in “Migrating an App to a Sandbox” (page 33). If you are using a POSIX function such as getpwuid to obtain the path to the user’s actual home directory, consider instead using a Cocoa or Core Foundation symbol such as the NSHomeDirectory function. By using Cocoa or Core Foundation, you support the App Sandbox restriction against directly accessing the user’s home directory. If your app requires access to the user’s home directory in order to function, let Apple know about your needs using the Apple bug reporting system. In addition, be sure to follow the guidance regarding entitlements provided on the iTunes Connect website. Accessing Preferences of Other Apps Because App Sandbox directs path-finding APIs to the container for your app, reading or writing to the user’s preferencestakes place within the container. Preferencesfor othersandboxed apps are inaccessible. Preferences for appsthat are notsandboxed are placed in the ~/Library/Preferences directory, which is also inaccessible to your sandboxed app. If your app requires access to another app’s preferences in order to function—for example, if it requires access to the playlists that a user has defined for iTunes—let Apple know about your needs using the Apple bug reporting system. In addition, be sure to follow the guidance regarding entitlements provided on the iTunes Connect website. Designing for App Sandbox Resolve API Incompatibilities 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 30With these provisosin mind, you can use a path-based temporary exception entitlement to gain programmatic accessto the user’s ~/Library/Preferences folder. Use a read-only entitlement to avoid opening the user’s preferences to malicious exploitation. A POSIX function, such as getpwuid, can provide the file system path you need. For details on entitlements, see Entitlement Key Reference . Apply the App Sandbox Entitlements You Need To adopt App Sandbox for a target in an Xcode project, apply the value to the com.apple.security.app-sandbox entitlement key for that target. Do this in the Xcode target editor by selecting the Enable App Sandboxing checkbox. Apply other entitlements as needed. For a complete list, refer to Entitlement Key Reference . Important: App Sandbox protects user data most effectively when you minimize the entitlements you request. Take care not to request entitlements for privileges your app does not need. Consider whether making a change in your app could eliminate the need for an entitlement. Here’s a basic workflow to use to determine which entitlements you need: 1. Run your app and exercise its features. 2. In the Console app (available in /Applications/Utilities/), look for sandboxd violations in the All Messages system log query. Each such violation indicates that your app attempted to do something not allowed by your sandbox. Here’s what a sandboxd violation looks like in Console: 3:56:16 pm sandboxd: ([4928]) AppSandboxQuickS(4928) deny network-outbound 111.30.222.15:80 3:56:16 pm sandboxd: ([4928]) AppSandboxQuickS(4928) deny system-socket Click the paperclip icon to the right of a violation message to view the backtrace that shows what led to the violation. 3. For each sandboxd violation you find, determine how to resolve the problem. In same cases, a simple change to your app,such as using your Container instead of other file system locations,solvesthe problem. In other cases, applying an App Sandbox entitlement using the Xcode target editor is the best choice. 4. Using the Xcode target editor, enable the entitlement that you think will resolve the violation. 5. Run the app and exercise its features again. Either confirm that you have resolved the sandboxd violation, or investigate further. Designing for App Sandbox Apply the App Sandbox Entitlements You Need 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 31If you choose not to sandbox your app now or to use a temporary exception entitlement, use Apple’s bug reporting system to let Apple know about the issue you are encountering. Apple considers feature requests as it develops the OS X platform. Also, be sure use the Review Notes field in iTunes Connect to explain why the exception is needed. Add Privilege Separation Using XPC When developing for App Sandbox, look at your app’s behaviors in terms of privileges and access. Consider the potential benefitsto security and robustness ofseparating high-risk operationsinto their own XPC services. When you determine that a feature should be placed into an XPC service, do so by referring to “Creating XPC Services” in Daemons and Services Programming Guide . Implement a Migration Strategy Ensure that customers who are currently using a pre-sandbox version of your app experience a painless upgrade when they install the sandboxed version. For details on how to implement a container migration manifest, read “Migrating an App to a Sandbox” (page 33). Designing for App Sandbox Add Privilege Separation Using XPC 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 32An app that is not sandboxed places its support files in locations that are inaccessible to a sandboxed version of the same app. For example, the typical locations for support files are shown here: Path Description Legacy location ~/Library/Application Support// Sandbox location ~/Library/Containers//Data/Library/Application Support// As you can see, the sandbox location for the Application Support directory is within an app’s container—thus allowing the sandboxed app unrestricted read/write access to those files. If you previously distributed your app without sandboxing and you now want to provide a sandboxed version, you must move support files into their new, sandbox-accessible locations. Note: The system automatically migrates your app’s preferences file (~/Library/Preferences/com.yourCompany.YourApp.plist) on firstlaunch of yoursandboxed app. OS X provides support-file migration, on a per-user basis, when a user first launches the sandboxed version of your app. This support depends on a special property list file you create, called a container migration manifest. A container migration manifest consists of an array of strings that identify the support files and directories you want to migrate when a user first launches the sandboxed version of your app. The file’s name must be container-migration.plist. For each file or directory you specify for migration, you have a choice of allowing the system to place the item appropriately in your container, or explicitly specifying the destination location. OS X moves—it does not copy—the files and directories you specify in a container migration manifest. That is, the files and directories migrated into your app’s container no longer exist at their original locations. In addition, container migration is a one-way process: You are responsible for providing a way to undo it, should you need to do so during development or testing. The section “Undoing a Migration for Testing” (page 36) provides a suggestion about this. 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 33 Migrating an App to a SandboxCreating a Container Migration Manifest To support migration of app support files when a user first launches the sandboxed version of your app, create a container migration manifest. To create and add a container migration manifest to an Xcode project 1. Add a property list file to the Xcode project. The Property List template is in the OS X “Resource” group in the file template dialog. Important: Be sure to name the file container-migration.plist spelled and lowercased exactly this way. 2. Add a Move property to the container migration manifest. The Move property is the lone top-level key in a container migration manifest. You add it to the empty file as follows: ● Right-click the empty editor for the new .plist file, then choose Add Row. ● In the Key column, enter Move as the name of the key. You must use this exact casing and spelling. ● In the Type column, choose Array. 3. Add a string to the Move array for the first file or folder you want to migrate. For example, suppose you want to migrate your Application Support directory (along with its contained files and subdirectories) to your container. If your directory is called App Sandbox Quick Start and is currently within the ~/Library/Application Support directory, use the following string as the value for the new property list item: ${ApplicationSupport}/App Sandbox Quick Start No trailing slash character is required, and space characters are permitted. The search-path constant in the path is equivalent to ~/Library/Application Support. This constant is described, along with other commonly used directories, in “Use Variables to Specify Support-File Directories” (page 37). Similarly, add additional strings to identify the original (before sandboxing) paths of additional files or folders you want to migrate. Migrating an App to a Sandbox Creating a Container Migration Manifest 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 34When you specify a directory to be moved, keep in mind that the move is recursive—it includes all the subdirectories and files within the directory you specify. Before you first test a migration manifest, provide a way to undo the migration, such as suggested in “Undoing a Migration for Testing” (page 36). To test a container migration manifest 1. In the Finder, open two windows as follows: ● In one window, view the contents of the ~/Library/Containers/ directory. ● In the other window, view the contents of the directory containing the support files named in the container migration manifest—that is, the files you want to migrate. 2. Build and run the Xcode project. Upon successful migration, the support files disappear from the original (nonsandbox) directory and appear in your app’s container. If you want to alter the arrangement ofsupport files during migration, use a slightly more complicated .plist structure. Specifically, for a file or directory whose migration destination you want to control, provide both a starting and an ending path. The ending path is relative to the Data directory in your container. In specifying an ending path, you can use any of the search-path constants described in “Use Variablesto Specify Support-File Directories” (page 37). If your destination path specifies a custom directory (one that isn’t part of a standard container), the system creates the directory during migration. The following task assumes that you’re using the Xcode property list editor and working with the container migration manifest you created earlier in this chapter. To control the destination of a migrated file or directory 1. In the container migration manifest, add a new item to the Move array. 2. In the Type column, choose Array. 3. Add two strings as children of the new array item. 4. In the top string of the pair, specify the origin path of the file or directory you want to migrate. 5. In the bottom string of the pair, specify the destination (sandbox) custom path for the file or directory you want to migrate. Migrating an App to a Sandbox Creating a Container Migration Manifest 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 35File migration proceeds from top-to-bottom through the container migration manifest. Take care to list items in an order that works. For example,suppose you want to move your entire Application Support directory as-is, except for one file. You want that file to go into a new directory parallel to Application Support in the container. For this approach to work, you must specify the individual file move before you specify the move of the Application Support directory—that is, specify the individual file move higher in the container migration manifest. (If Application Support were specified to be moved first, the individual file would no longer be at its original location at the time the migration process attempted to move it to its new, custom location in the container.) Undoing a Migration for Testing When testing migration of support files, you may find it necessary to perform migration more than once. To support this, you need a way to restore your starting directory structures—that is, the structures as they exist prior to migration. One way to do this is to make a copy of the directories to migrate, before you perform a first migration. Save this copy in a location unaffected by the migration manifest. The following task assumes you have created this sort of backup copy. To manually undo a container migration for testing purposes 1. Manually copy the files and directories—those specified in the manifest—from your backup copy to their original (premigration) locations. 2. Delete your app’s container. The next time you launch the app, the system recreates the container and migrates the support files according to the current version of the container migration manifest. An Example Container Migration Manifest Listing 4-1 shows an example manifest as viewed in a text editor. Listing 4-1 An example container migration manifest Migrating an App to a Sandbox Undoing a Migration for Testing 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 36 Move ${Library}/MyApp/MyConfiguration.plist ${Library}/MyApp/MyDataStore.xml ${ApplicationSupport}/MyApp/MyDataStore.xml This manifest specifies the migration of two items from the user’s Library directory to the app’s container. For the first item, MyConfiguration.plist, only the origin path is specified, leaving it to the migration process to place the file appropriately. For the second item, MyDataStore.xml, both an origin and a custom destination path are specified. The ${Library} and ${ApplicationSupport} portions of the paths are variables you can use as a convenience. For a list of variables you can use in a container migration manifest, see “Use Variables to Specify Support-File Directories” (page 37). Use Variables to Specify Support-File Directories When you specify a path in a container migration manifest, you can use certain variables that correspond to commonly used support file directories. These variables work in origin and destination paths, but the path that a variable resolves to depends on the context. Refer to Table 4-1. Table 4-1 How system directory variables resolve depending on context Context Variable resolves to Origin path Home-relative path (relative to the ~ directory) Destination path Container-relative path (relative to the Data directory in the container) Migrating an App to a Sandbox Use Variables to Specify Support-File Directories 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 37The variables you can use for specifying support-file directories are described in Table 4-2 (page 38). For an example of how to use these variables, see Listing 4-1 (page 36). You can also use a special variable that resolves to your app’s bundle identifier, allowing you to conveniently incorporate it into an origin or destination path. This variable is ${BundleId}. Table 4-2 Variables for support-file directories Variable Directory The directory containing application support files. Corresponds to the NSApplicationSupportDirectory search-path constant. ${ApplicationSupport} The directory containing the user’s autosaved documents. Corresponds to the NSAutosavedInformationDirectory search-path constant. ${AutosavedInformation} The directory containing discardable cache files. Corresponds to the NSCachesDirectory search-path constant. ${Caches} Each variable correspondsto the directory containing the user’s documents. Corresponds to the NSDocumentDirectory search-path constant. ${Document} ${Documents} The current user’s home directory. Corresponds to the directory returned by the NSHomeDirectory function. When in a destination path in a manifest, resolves to the Container directory. ${Home} The directory containing application-related support and configuration files. Corresponds to the NSLibraryDirectory search-path constant. ${Library} Migrating an App to a Sandbox Use Variables to Specify Support-File Directories 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 38This table describes the changes to App Sandbox Design Guide . Date Notes 2012-09-19 Clarified information about launching external tools. 2012-07-23 Added an explanation of app group containers. Improved the explanation of security-scoped bookmarks in “Security-Scoped Bookmarks and Persistent Resource Access” (page 21); updated that section for OS X v10.7.4. 2012-05-14 Added a brief section in the “Designing for App Sandbox” chapter: “Retaining Access to File System Resources” (page 29). Improved the discussion in “Opening, Saving, and Tracking Documents” (page 29), adding information about using file coordinators. Corrected the information in “Creating a Login Item for Your App” (page 30). Improved explanation ofsecurity-scoped bookmarksin “Security-Scoped Bookmarks and Persistent Resource Access” (page 21). 2012-03-14 Clarified the explanation of the container directory in “The App Sandbox Container Directory” (page 16) Updated for OS X v10.7.3, including an explanation of how to use security-scoped bookmarks. 2012-02-16 Added a section explaining how to provide persistent accessto file-system resources, “Security-Scoped Bookmarks and Persistent Resource Access” (page 21). 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 39 Document Revision HistoryDate Notes Expanded the discussion in “Powerbox and File System Access Outside of Your Container” (page 17) to better explain how user actions expand your app’s file system access. Added a section detailing the changes in behavior of Open and Save dialogs, “Open and Save Dialog Behavior with App Sandbox” (page 19). New document that explains Apple's security technology for damage containment, and how to use it. 2011-09-27 Portions of this document were previously published in Code Signing and Application Sandboxing Guide . Document Revision History 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 40Apple Inc. © 2012 Apple Inc. All rights reserved. No part of this publication may be reproduced, stored in a retrievalsystem, or transmitted, in any form or by any means, mechanical, electronic, photocopying, recording, or otherwise, without prior written permission of Apple Inc., with the following exceptions: Any person is hereby authorized to store documentation on a single computer for personal use only and to print copies of documentation for personal use provided that the documentation contains Apple’s copyright notice. No licenses, express or implied, are granted with respect to any of the technology described in this document. Apple retains all intellectual property rights associated with the technology described in this document. This document is intended to assist application developers to develop applications only for Apple-labeled computers. Apple Inc. 1 Infinite Loop Cupertino, CA 95014 408-996-1010 Apple, the Apple logo, Cocoa, Finder, iTunes, Keychain, Mac, OS X, Sand, and Xcode are trademarks of Apple Inc., registered in the U.S. and other countries. QuickStart is a trademark of Apple Inc. iCloud is a service mark of Apple Inc., registered in the U.S. and other countries. App Store and Mac App Store are service marks of Apple Inc. iOS is a trademark or registered trademark of Cisco in the U.S. and other countries and is used under license. Even though Apple has reviewed this document, APPLE MAKES NO WARRANTY OR REPRESENTATION, EITHER EXPRESS OR IMPLIED, WITH RESPECT TO THIS DOCUMENT, ITS QUALITY, ACCURACY, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.ASARESULT, THISDOCUMENT IS PROVIDED “AS IS,” AND YOU, THE READER, ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND ACCURACY. IN NO EVENT WILL APPLE BE LIABLE FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL,OR CONSEQUENTIAL DAMAGES RESULTING FROM ANY DEFECT OR INACCURACY IN THIS DOCUMENT, even if advised of the possibility of such damages. THE WARRANTY AND REMEDIES SET FORTH ABOVE ARE EXCLUSIVE AND IN LIEU OF ALL OTHERS, ORAL OR WRITTEN, EXPRESS OR IMPLIED. No Apple dealer, agent, or employee is authorized to make any modification, extension, or addition to this warranty. Some states do not allow the exclusion or limitation of implied warranties or liability for incidental or consequential damages, so the above limitation or exclusion may not apply to you. This warranty gives you specific legal rights, and you may also have other rights which vary from state to state. iTunes Connect Sales and Trends Guide App Store  Apple Inc. iTunes Connect Sales and Trends Guide, App Store Version 5.3  iTunes Connect Sales and Trends Guide, App Store (Version 5.3, August 2012) 1Apple Inc. © 2012 Apple Inc. All rights reserved. No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form or by any means, mechanical, electronic, photocopying, recording, or otherwise, without prior written permission of Apple Inc., with the following exceptions: Any person is hereby authorized to store documentation on a single computer for personal use only and to print copies of documentation for personal use provided that the documentation contains Apple’s copyright notice. The Apple logo is a trademark of Apple Inc. Use of the “keyboard” Apple logo (Option-Shift-K) for commercial purposes without the prior written consent of Apple may constitute trademark infringement and unfair competition in violation of federal and state laws. No licenses, express or implied, are granted with respect to any of the technology described in this document. Apple retains all intellectual property rights associated with the technology described in this document. This document is intended to assist partners in understanding the Sales and Trends module of iTunes Connect. Every effort has been made to ensure that the information in this document is accurate. Apple is not responsible for typographical errors. Apple Inc. 1 Infinite Loop Cupertino, CA 95014 408-996-1010 Even though Apple has reviewed this document, APPLE MAKES NO WARRANTY OR REPRESENTATION, EITHER EXPRESS OR IMPLIED, WITH RESPECT TO THIS DOCUMENT, ITS QUALITY, ACCURACY, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. AS A RESULT, THIS DOCUMENT IS PROVIDED “AS IS,” AND YOU, THE READER, ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND ACCURACY. IN NO EVENT WILL APPLE BE LIABLE FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES RESULTING FROM ANY DEFECT OR INACCURACY IN THIS DOCUMENT, even if advised of the possibility of such damages THE WARRANTY AND REMEDIES SET FORTH ABOVE ARE EXCLUSIVE AND IN LIEU OF ALL OTHERS, ORAL OR WRITTEN, EXPRESS OR IMPLIED. No Apple dealer, agent, or employee is authorized to make any modification, extension, or addition to this warranty. Some states do not allow the exclusion or limitation of implied warranties or liability for incidental or consequential damages, so the above limitation or exclusion may not apply to you. This warranty gives you specific legal rights, and you may also have other rights which vary from state to state. Apple Inc. iTunes Connect Sales and Trends Guide, App Store Version 5.3  iTunes Connect Sales and Trends Guide, App Store (Version 5.3, August 2012) 2Contents 1. Getting Started 4 2. Navigating and Viewing Your Sales and Trends Data 5 2.1. Dashboard View 6 2.2. Sales View 11 3. Downloading, Reading and Understanding Sales and Trends Data 13 3.1. Downloading Reports 13 3.2. Auto-Ingest Tool 14 3.3. Reading Reports 16 3.4. Understanding Units 18 4. Contact Us 19 Appendix A - Sales Report Field Definitions 20 Appendix B - Opt-In Report Field Definitions 21 Appendix C - Apple Fiscal Calendar 22 Appendix D - Definition of Day and Week 23 Appendix E – Product Type Identifiers 24 Appendix F – Country Codes 25 Appendix G – Promotional Codes 26 Appendix H – Currency Codes 27 Appendix I - Subscription and Period Field Values 28 Appendix J - FAQs 29 Appendix K - Sample Sales Report 30 Appendix L – Other Uses 32 Appendix M - Newsstand Report Field Definitions 33 Apple Inc. iTunes Connect Sales and Trends Guide, App Store Version 5.3  iTunes Connect Sales and Trends Guide, App Store (Version 5.3, August 2012) 31. Getting Started iTunes Connect can be accessed at http://itunesconnect.apple.com. Once you login, you will be presented with the Welcome page below, which contains notifications at the top and module links to help you navigate through iTunes Connect. The Welcome page you will see is based on the modules applicable to you and may be different from what is shown below. This guide is primarily intended to cover the Sales and Trends module. The initial user who entered into the program license agreement has the “Admin” role, which provides access to all modules, including the ability to add other “Admin” users (using the Manage Users module). The “Admin” users associated with your account are expected to manage (add, modify, and delete) your users based on your needs. Apple Inc. iTunes Connect Sales and Trends Guide, App Store Version 5.3  iTunes Connect Sales and Trends Guide, App Store (Version 5.3, August 2012) 42. Navigating and Viewing Your Sales and Trends Data The iTunes Connect Sales and Trends module allows you to interact with your sales data in various ways: ■ A summary that provides total units, percent differences, graphs, top selling content and largest market information (Dashboard view). ■ Previews that provide the top 50 transactions of sales aggregated at the title level in descending sorted order (Sales view). ■ Download full transaction reports for import and further analysis (Sales view). When you are ready to access the Sales and Trends module, click on the following link located on the Welcome page: Upon selecting the Sales and Trends module, you will be taken to the Dashboard view. Apple Inc. iTunes Connect Sales and Trends Guide, App Store Version 5.3  iTunes Connect Sales and Trends Guide, App Store (Version 5.3, August 2012) 52.1. Dashboard View The Dashboard will load and display the most recent daily data available. The following identifies the various components of the dashboard. The “Selection” controls located above the graph allow you to change the information displayed. Vendor Selection The Vendor Selection display lists the legal entity name for the Sales and Trends that you are viewing. Apple Inc. iTunes Connect Sales and Trends Guide, App Store Version 5.3  iTunes Connect Sales and Trends Guide, App Store (Version 5.3, August 2012) 6View Selection The View Selection allows you to switch between different views. In addition to the Dashboard view, you can toggle to the Sales view (the Sales view is covered in section 2.2). Period Selection You can choose the type (daily or weekly), as well as the period of interest. The date menu will display all periods available up to the last 13 weeks or 14 days. Category Selection You can choose the specific category you wish to view in the Dashboard if you sell more than one type of content (i.e. iOS and MacOS). Apple Inc. iTunes Connect Sales and Trends Guide, App Store Version 5.3  iTunes Connect Sales and Trends Guide, App Store (Version 5.3, August 2012) 7Type Selection You can choose the specific type of content within a category to view in the Dashboard’s graph, Top Products and Top Markets. The available types are the same for both the iOS and MacOS category. Refer to Appendix E for the complete product breakdown by product type. Graph Selection You can choose between a line graph and bar graph by clicking on the graph buttons located on the right top corner of the graph. Graph The data displayed in the graph is based on the period (specific day or week), category and type selected. When you hover over a specific day or week in the graph (bar or line), the date, number of units and type will be displayed. The following displays the graph for the period of August 30, 2010 and the Free Apps category while mousing over the August 30, 2010 bar. When viewing daily reports, the graph will also display the percentage change from the same day in the prior period. In the graph above you see the percentage change of free apps sold on 8/30 (Monday) to those sold on 8/24 (Monday of prior week) based on units. Apple Inc. iTunes Connect Sales and Trends Guide, App Store Version 5.3  iTunes Connect Sales and Trends Guide, App Store (Version 5.3, August 2012) 8Top Products Display The Top Products display is based on the period (specific day or week), category (iOS or Mac OS) and the type (Free Apps, Paid Apps, In Apps, Updates) selected. The section provides a summary of net units at the Product level. A Product can be reported as separate lines in your reports due to differences such as territories but will be reported as combined in terms of units in this display since the units are aggregated at the Product level world-wide based on unique product identifier. The “Change” column in the display shows units and percentage change from the prior period (selected day over same day of the prior week, or selected week over prior week). Top Markets Display The Top Markets display is based on the period (specific day or week), category (iOS and Mac OS) and the type (e.g. Free Apps) selected. This section provides a summary of net units for all products at the country (iTunes Storefront) level. The “Change” column in the display shows units and percentage change from the prior period (selected day over same day of the prior week, or selected week over prior week). See Appendix F for iTunes Storefront listing. Apple Inc. iTunes Connect Sales and Trends Guide, App Store Version 5.3  iTunes Connect Sales and Trends Guide, App Store (Version 5.3, August 2012) 9Resources At the bottom left of all pages you will find three links: ■ Fiscal Calendar - Opens a new window that displays Apple’s fiscal calendar ■ User Guide - Provides the most current version of this guide ■ Mobile Guide - Provides the user guide for the iTC Mobile Application. Done Button The “Done” button at the bottom right of all pages takes you to the Dashboard from the Sales view, and to the iTunes Connect Welcome page from the Dashboard. Apple Inc. iTunes Connect Sales and Trends Guide, App Store Version 5.3  iTunes Connect Sales and Trends Guide, App Store (Version 5.3, August 2012) 102.2. Sales View The Sales view allows you to analyze at the specific content level. You can preview the Top 50 products delivered based on transaction volume summarized and sorted descending by Units, and can download the available daily and weekly reports for additional information about all your transactions. You can also download detailed Newsstand reports or contact information for customers that have elected to “opt-in” when purchasing an In-App Purchase subscription. The following is an example of the Sales view. Apple Inc. iTunes Connect Sales and Trends Guide, App Store Version 5.3  iTunes Connect Sales and Trends Guide, App Store (Version 5.3, August 2012) 11Understanding The Sales Preview When you land on the Sales view, the Period presented is the latest daily data available. Using the Period Selection menu, you can preview all available daily and weekly data for all content types in all categories. Once you have selected a period, the Preview will be displayed. The Preview summarizes the data based on the columns displayed, including any promotional transactions indicated with (Promo Indicator). You can hover over the Promo Indicator to see the type of promotion. See Appendix G for Promotional Codes. Autorenewable subscription transactions are indicated with (Subscription Indicator). The preview functionality does not contain the full report. To view or analyze all transactions you must download the full reports. The previews summarize data differently than the reports based on the information available (i.e. the preview may summarize sales at a higher level as the downloaded report has more fields to consider). Apple Inc. iTunes Connect Sales and Trends Guide, App Store Version 5.3  iTunes Connect Sales and Trends Guide, App Store (Version 5.3, August 2012) 123. Downloading, Reading and Understanding Sales and Trends Data 3.1. Downloading Reports You may download the Sales reports from the respective Sales view. To download a report (tab delimited zipped text file), you must select a report period (day of week or week ended) and press the download button to the right of the period selection menu. For a complete listing of fields please see Appendix A, B and M. If you are using Mac OS X the reports will automatically open when downloaded. If you are using a Windows OS you will need to download an application (for example WinZip) to decompress the “.gz” file prior to use. You can then import the tab delimited text file to a database or spreadsheet application (Numbers, MS Excel) and analyze or manipulate your data as needed. Weekly reports cover Monday through Sunday and are available on Mondays. The daily reports represent the 24 hour period in the time zone of the respective storefront (territory). Please refer to Appendix D for the definition of Day and Week. We do not store or regenerate the data after the periods have expired (14 rolling days and 13 rolling weeks); you will need to download and store this data on a regular basis if you intend to use it in the future. Downloading Customer Opt-In Information If your apps have auto-renewable subscriptions, you can download contact information for customers who have elected to “opt-in” to personal information sharing. To download the report (tab delimited zipped text file), you must select a weekly report period and click Opt-In Report next to Download Report. Apple Inc. iTunes Connect Sales and Trends Guide, App Store Version 5.3  iTunes Connect Sales and Trends Guide, App Store (Version 5.3, August 2012) 13To open the encrypted .zip file that is downloaded, you need to use the Opt-In Passkey. To obtain the Opt-In Passkey, click the Opt-In Passkey button in the upper right of the screen. The passkey will be displayed in a lightbox. Copy and paste this value to use it to unpack the .zip file and access the Opt-In Report. You will need to use a decompression tool like Stuff-It Expander or Winzip to open the encrypted file once you have downloaded it. Downloading Newsstand Reports If you have one or more Newsstand apps available for sale, you can download Newsstand reports by clicking Newsstand Detailed. Newsstand reports are also available via auto-ingest. 3.2. Auto-Ingest Tool Apple provides access to a Java based tool to allow you to automate the download of your iTunes Connect Sales and Trends reports. To use the auto-ingest tool, configuration on your part will be required. This tool allows you to automate the retrieval of: •Daily Summary Reports •Weekly Summary Reports •Opt-In Reports •Newsstand Reports As new reports become available we will modify and redeliver the java package or new parameters to use to download new products (i.e. we will modify the script for new features). We will communicate both the anticipated date of the report release and the date that the tool will be able to retrieve reports. You may not alter or disseminate the auto-ingest tool for any reason. We reserve the right to revoke access for usage or distribution beyond its intended use. Auto-Ingest Instructions You must have Java installed on the machine where you are running the auto-ingest tool. The tool will work as expected with Java version 1.6 or above. Follow the steps below to setup the environment for auto-ingestion: Apple Inc. iTunes Connect Sales and Trends Guide, App Store Version 5.3  iTunes Connect Sales and Trends Guide, App Store (Version 5.3, August 2012) 141. Download and save the file Autoingestion.class to the directory where you want the reports delivered. http://www.apple.com/itunesnews/docs/Autoingestion.class.zip 2. To run the Java class file, change the command line directory to the directory where the class file is stored. 3. Invoke the following from the command line: java Autoingestion All items contained within “< >” are variable and will require you to define them. Of the 7 parameters only the date is optional. If you do not put a date in the parameter we will provide you the latest available report (the other parameters are mandatory). You will need to delimit the parameters with a space. Parameters Definitions Variable Value Notes username Your user name The user name you use to log into iTunes Connect password Your password The password you use to log into iTunes Connect vendorid 8####### (your unique number) Vendor ID for the entity which you want to download the report report_type Sales or Newsstand This is the report type you want to download. date_type Daily or Weekly Selecting Weekly will provide you the Weekly version of the report. Selecting Daily will provide you the Daily version of the report. report_subtype Summary, Detailed or Opt-In This is the parameter for the Sales Reports. Note: Detailed can only be used for Newsstand reports. Date (optional) YYYYMMDD This is the date of report you are requesting. If the value for Date parameter is not provided, you will get the latest report available. Example: You access iTunes Connect with user name “john@xyz.com” and your password is “letmein” for company 80012345, and you want to download a sales - daily - summary report for February 4, 2010. You will need to invoke the job by running the following command from the directory where the class file is stored: java Autoingestion john@xyz.com letmein 80012345 Sales Daily Summary 20100204 Newsstand Reports via Auto-Ingest If you are using auto-ingest, you can create the reports using the following auto-ingest parameters: Daily java Autoingestion Newsstand Daily Detailed java Autoingestion N D D java Autoingestion 5 2 1 Apple Inc. iTunes Connect Sales and Trends Guide, App Store Version 5.3  iTunes Connect Sales and Trends Guide, App Store (Version 5.3, August 2012) 15Weekly java Autoingestion Newsstand Weekly Detailed java Autoingestion N W D java Autoingestion 5 1 1 3.3. Reading Reports Report File Names The file names for downloaded reports follow a standard naming convention. Please refer to the matrix below for details. Report Data Report Type Reporting Range Naming Convention Description Sales Summary Daily S_D__ Example: S_D_80000000_20111104 The first letter identifies that the report provides Sales data at a Summary level. Second letter denotes that it is a Daily report. This is followed by the Vendor Account Number and the Date of reporting data ('YYYYMMDD'). Sales Summary Weekly S_W__ Example: S_W_80000000_20111104 The first letter identifies that the report provides Sales data at a Summary level. Second letter denotes that it is a Weekly report. This is followed by the Vendor Account Number and the Date of reporting data ('YYYYMMDD'). Opt_in Summary Weekly O_S_W__ Example: O_S_W_80000000_20111104 The first and second letters identify that the report provides customer Opt-in data at a Summary level. The third letter identifies that it is a Weekly report. This is followed by the Vendor Account Number and the Date of reporting data ('YYYYMMDD'). Newsstand Detailed Daily N_D_D__ Example: N_D_D_80000000_20111104 The first and second letters identify that the report provides customer Newsstand data at a Detailed level. The third letter identifies that it is a Daily report. This is followed by the Vendor Account Number and the Date of reporting data ('YYYYMMDD'). Newsstand Detailed Weekly N_D_W__ Example: N_D_W_80000000_20111104 The first and second letters identify that the report provides customer Newsstand data at a Detailed level. The third letter identifies that it is a Weekly report. This is followed by the Vendor Account Number and the Date of reporting data ('YYYYMMDD'). Apple Inc. iTunes Connect Sales and Trends Guide, App Store Version 5.3  iTunes Connect Sales and Trends Guide, App Store (Version 5.3, August 2012) 16Report Field Names All reports have a header row which contains the field names of each column. The reports present transactions that can be tracked with your SKU and/or the Apple Identifier. For a complete listing of fields please see Appendix A, B and M. Key Field Mapping The following table and screenshots will help you understand which fields in the report were setup by you in iTunes Connect and where they are in the App Store: Reference Field Name In Report Field in iTunes Connect Field in App Store 1 Developer Company Name Displayed after genre 2 Title App Name Displayed at top of product page 3 SKU SKU Number Not displayed on App Store Apple Inc. iTunes Connect Sales and Trends Guide, App Store Version 5.3  iTunes Connect Sales and Trends Guide, App Store (Version 5.3, August 2012) 17Apple Identifier The Apple Identifier is the unique product identifier assigned by Apple. It is always included in each row of your sales reports. We recommend you provide the Apple Identifier of your app whenever you contact us for support so that your request can be expedited. You can also access the Apple Identifier by using the links in the App Store: The menu will offer an option for “Copy Link”. The link will look like the link below. The string of numbers highlighted is the Apple Identifier of the app. http://itunes.apple.com/us/app/remote/id284417350?mt=85 3.4. Understanding Units The reports are designed to provide valuable information about the activity of your product on the App Store. This can result in many lines for a given product. For each product with a unique Apple Identifier and SKU, units are split by: ■ Storefront / Country Code (US, UK) ■ Sales vs. Refunds ■ Product Type ■ Price ■ Promo Code ■ App Version Here are some examples of how units are grouped and displayed in both Preview and downloaded reports. Example 1: If you have one product and you are selling the product in the US, you will see 1 row (1 for US sales) assuming there are no refunds, price changes and promo codes during the period. Example 2: If you are selling 30 products in the US, and 10 of the products have refunds, then the preview and the downloaded report will have 40 rows and you will see a row for sales and a row for refunds. Example 3: If you are selling 30 products in the US, and 5 products have a price change in the middle of the week, then your full report and your previews will have 35 rows and you will see 2 lines per app with a price change. Example 4: If 10 new customers purchase your app and 10 existing customers update to the latest version of your app in the US, then your preview and downloaded report will have 1 row for purchases and 1 row for updates. Example 5: If 10 customers purchase version 1.1 of your product in the US, and those customers then update to version 1.2 of the same product, then your preview and downloaded report will have 2 rows, 1 row for purchases of version 1.1 and 1 row for updates to version 1.2. Apple Inc. iTunes Connect Sales and Trends Guide, App Store Version 5.3  iTunes Connect Sales and Trends Guide, App Store (Version 5.3, August 2012) 184. Contact Us If you have any questions or have difficulties viewing or downloading your sales and trends information, please do not hesitate to contact us. The easiest way to ensure your request is routed correctly is to use the Contact Us module. A Contact Us link is available on all pages as part of the footer. You can also find the Contact Us module on the iTunes Connect Homepage: The link will take you to a page that allows you to select the topic you need help with and will ask a series of questions and provide answers where available. For Sales and Trends inquiries, select the “Sales and Trends” topic. Apple Inc. iTunes Connect Sales and Trends Guide, App Store Version 5.3  iTunes Connect Sales and Trends Guide, App Store (Version 5.3, August 2012) 19Appendix A - Sales Report Field Definitions The definitions apply to Daily and Weekly Reports. Report Field Report Data Type Values Notes Provider CHAR(5) - APPLE Up to 5 Characters The service provider in your reports will typically be Apple Provider Country CHAR(2) - US Up to 2 Characters The service provider country code will typically be US SKU VARCHAR(100) Up to 100 Characters This is a product identifier provided by you when the app is set up ∇ Developer VARCHAR(4000) Up to 4000 Characters You provided this on initial setup . ∇ Title VARCHAR(600) Up to 600 Characters You provided this when setting up the app ∇ Version VARCHAR(100) Up to 100 Characters You provided this when setting up the app ∇ Product Type Identifier VARCHAR(20) Up to 20 Characters This field defines the type of transaction (e.g. initial download, update, etc) – See Appendix E Units DECIMAL(18,2) Up to 18 Characters This is the aggregated number of units Developer Proceeds (per item) DECIMAL(18,2) Up to 18 Characters Your proceeds for each item delivered Begin Date Date Date in MM/DD/YYYY Date of beginning of report End Date Date Date in MM/DD/YYYY Date of end of report Customer Currency CHAR(3) Up to 3 Characters Three character ISO code indicates the currency the customer paid in - See Appendix H Country Code CHAR(2) Up to 2 Characters Two character ISO country code indicates what App Store the purchase occurred in – See Appendix F Currency of Proceeds CHAR(3) Up to 3 Characters Currency your proceeds are earned in – See Appendix H Apple Identifier DECIMAL(18,0) Up to 18 Characters This is Apple's unique identifier. If you have questions about a product, it is best to include this identifier. Customer Price DECIMAL(18,2) Up to 18 Characters Retail Price displayed on the App Store and charged to the customer. Promo Code VARCHAR(10) Up to 10 Characters If the transaction was part of a promotion this field will contain a value. For all non-promotional items this field will be blank - See Appendix G Parent Identifier VARCHAR(100) Up to 100 Characters For In-App Purchases this will be populated with the SKU from the originating app. Subscription VARCHAR(10) Up to 10 Characters This field defines whether an autorenewable subscription purchase is a new purchase or a renewal. See Appendix I. Period VARCHAR(30) Up to 30 Characters This field defines the duration of an auto-renewable subscription purchase. See Appendix I. ∇ Apple generally does not modify this field. What you provided when setting up your app is passed through on the report. Apple Inc. iTunes Connect Sales and Trends Guide, App Store Version 5.3  iTunes Connect Sales and Trends Guide, App Store (Version 5.3, August 2012) 20Appendix B - Opt-In Report Field Definitions The definitions apply to Weekly Opt-In Reports. Report Field Report Data Type Values Notes First Name VARCHAR(100) Up to 100 Characters First Name of Customer Last Name VARCHAR(100) Up to 100 Characters Last Name of Customer Email Address VARCHAR(100) Up to 100 Characters Email Address of Customer Postal Code VARCHAR(50) Up to 50 Characters Postal Code of Customer Apple Identifier DECIMAL(18,0) Up to 18 Characters This is Apple's unique identifier. If you have questions about a product, it is best to include this identifier. Report Start Date DATE Date in MM/DD/YYYY Date of beginning of report Report End Date DATE Date in MM/DD/YYYY Date of end of report Apple Inc. iTunes Connect Sales and Trends Guide, App Store Version 5.3  iTunes Connect Sales and Trends Guide, App Store (Version 5.3, August 2012) 21Appendix C - Apple Fiscal Calendar Monthly Financial Reports are based on Apple’s reporting calendar shown below. Months represent either four (4) or five (5) weeks (the first month of each quarter has an extra week) and the weeks run from Sunday through Saturday. All months start on Sunday and end on Saturday. Monthly reports are also distributed on iTunes Connect and available based on the contractually agreed timeframes. Sales and Trends reports are generated using different time frames and represent near immediate feedback of transactions. Finance Reports are based on customer invoicing and financial processing. Reconciliation between the reports is not recommended due to the timing and reporting differences. Apple Inc. iTunes Connect Sales and Trends Guide, App Store Version 5.3  iTunes Connect Sales and Trends Guide, App Store (Version 5.3, August 2012) 22Appendix D - Definition of Day and Week What is a Day? 12:00:00 AM to 11:59:59 PM in the time zone used for that territory (see table below). What is a Week? Monday 12:00:00 AM to Sunday 11:59:59 PM What time is the report date based on? Territory Time Zone US, Canada, Latin America Pacific Time (PT) Europe, Middle East, Africa, Asia Pacific Central Europe Time (CET) Japan Japan Standard Time (JST) Australia, New Zealand Western Standard Time (WST) When are reports available? Reports are generated after the close of business in the final time zone (which is PT). As such, all reports are generally available by 8:00 AM PT for the prior day or week. Earlier access to reporting for other time zones (where the close of business is earlier) is not available. Apple Inc. iTunes Connect Sales and Trends Guide, App Store Version 5.3  iTunes Connect Sales and Trends Guide, App Store (Version 5.3, August 2012) 23Appendix E – Product Type Identifiers Product Type Identifier Type Description 1 Free or Paid Apps iPhone and iPod Touch, iOS 7 Updates iPhone and iPod Touch, iOS IA1 In Apps Purchase, iOS IA9 In Apps Subscription, iOS IAY In Apps Auto-Renewable Subscription, iOS IAC In Apps Free Subscription, iOS 1F Free or Paid Apps Universal, iOS 7F Updates Universal, iOS 1T Free or Paid Apps iPad, iOS 7T Updates iPad, iOS F1 Free or Paid Apps Mac OS F7 Updates Mac OS FI1 In Apps Mac OS 1E Paid Apps Custom iPhone and iPod Touch, iOS 1EP Paid Apps Custom iPad, iOS 1EU Paid Apps Custom Universal, iOS Dashboard Types Type Product Type Identifier Description Free Apps 1, 1F, 1T, F1 Where price = ‘0’ Paid Apps 1, 1F, 1T, F1 Where price > ‘0’ In Apps IA1, IA9, IAY. FI1 Updates 7, 7F, 7T, F7 Apple Inc. iTunes Connect Sales and Trends Guide, App Store Version 5.3  iTunes Connect Sales and Trends Guide, App Store (Version 5.3, August 2012) 24Appendix F – Country Codes Country Code Country Name Country Code Country Name Country Code Country Name AE United Arab Emirates GD Grenada NG Nigeria AG Antigua and Barbuda GH Ghana NI Nicaragua AI Anguilla GR Greece NL Netherlands AM Armenia GT Guatemala NO Norway AO Angola GY Guyana NZ New Zealand AR Argentina HK Hong Kong OM Oman AT Austria HN Honduras PA Panama AU Australia HR Croatia PE Peru AZ Azerbaijan HU Hungary PH Philippines BB Barbados ID Indonesia PK Pakistan BE Belgium IE Ireland PL Poland BG Bulgaria IL Israel PT Portugal BH Bahrain IN India PY Paraguay BM Bermuda IS Iceland QA Qatar BN Brunei IT Italy RO Romania BO Bolivia JM Jamaica RU Russia BR Brazil JO Jordan SA Saudi Arabia BS Bahamas JP Japan SE Sweden BW Botswana KE Kenya SG Singapore BY Belarus KN St. Kitts and Nevis SI Slovenia BZ Belize KR Republic Of Korea SK Slovakia CA Canada KW Kuwait SN Senegal CH Switzerland KY Cayman Islands SR Suriname CL Chile KZ Kazakstan SV El Salvador CN China LB Lebanon TC Turks and Caicos CO Colombia LC St. Lucia TH Thailand CR Costa Rica LK Sri Lanka TN Tunisia CY Cyprus LT Lithuania TR Turkey CZ Czech Republic LU Luxembourg TT Trinidad and Tobago DE Germany LV Latvia TW Taiwan DK Denmark MD Republic Of Moldova TZ Tanzania DM Dominica MG Madagascar UG Uganda DO Dominican Republic MK Macedonia US United States DZ Algeria ML Mali UY Uruguay EC Ecuador MO Macau UZ Uzbekistan EE Estonia MS Montserrat VC St. Vincent and The Grenadines EG Egypt MT Malta VE Venezuela ES Spain MU Mauritius VG British Virgin Islands FI Finland MX Mexico VN Vietnam FR France MY Malaysia YE Yemen GB United Kingdom NE Niger ZA South Africa Apple Inc. iTunes Connect Sales and Trends Guide, App Store Version 5.3  iTunes Connect Sales and Trends Guide, App Store (Version 5.3, August 2012) 25Appendix G – Promotional Codes The promo code field contains different values depending on the type of promotion. The following definitions describe the possible values that may appear in the field other than null (null means the item is a standard transaction). Only one value is possible per line in the report: Promo Code Description CR - RW Promotional codes where the proceeds have been waived (The customer price will be 0 and the proceeds will be 0). These transactions are the result of iTunes Connect Developer Code redemptions. GP Purchase of a Gift by the giver GR Redemption of a Gift by the receiver EDU Education Store transaction Apple Inc. iTunes Connect Sales and Trends Guide, App Store Version 5.3  iTunes Connect Sales and Trends Guide, App Store (Version 5.3, August 2012) 26Appendix H – Currency Codes Currency Code Currency Country AUD Australian Dollar CAD Canadian Dollar CHF Swiss Franc DKK Danish Kroner EUR European Euro GBP British Pound JPY Japanese Yen MXN Mexican Peso NOK Norwegian Kroner NZD New Zealand Dollar SEK Swedish Kronor USD United States Dollar Apple Inc. iTunes Connect Sales and Trends Guide, App Store Version 5.3  iTunes Connect Sales and Trends Guide, App Store (Version 5.3, August 2012) 27Appendix I - Subscription and Period Field Values The Subscription field indicates whether the auto-renewable subscription purchase is a new purchase or a renewal. Subscription Field Value New Renewal The Period field indicates the duration of the auto-renewable subscription purchase or renewal. Period Field Value 7 Days 1 Month 2 Months 3 Months 6 Months 1 Year Apple Inc. iTunes Connect Sales and Trends Guide, App Store Version 5.3  iTunes Connect Sales and Trends Guide, App Store (Version 5.3, August 2012) 28Appendix J - FAQs What does each column represent in my reports? Please refer to Appendix A and B. I am seeing differences between Financial Reports and Sales and Trends reports, why? The daily and weekly reports are based on customer interaction (clicks) and are coming from real-time systems while the monthly reports are based on settled financial transactions and are coming from our financial systems. There are intentional differences in processing and time-frames between those two types of reports. For example, the weekly reports are from Monday to Sunday, while the Financial Reports are based on the Apple Fiscal Calendar and always end on Saturday. Reconciliation between the reports is not recommended due to the timing and reporting differences. Do weekly reports reconcile with the daily reports? Yes. Both daily and weekly reports are coming from the same system and they are based on customer interaction (clicks). They will reconcile. I see a high volume of sales for a short period of time (could be up to a week) and the sales drop down, what does this mean? It is very common that some items get a high amount of sales for a short period of time and the numbers get back to normal. It is generally due to a particular promotion related with a web blog or a sales campaign that includes an item that might be associated with iTunes or the content. There is also a very common case where a content's sales drop to zero.  In this case, this might be an indication of content being unavailable in iTunes due to number of reasons. I don’t see any sales for a particular item, why? This can be an indication of an item not being available in the store for different reasons. Check the product availability in iTunes Connect and ensure that the latest contracts are agreed to and in place. How can I identify refunds? Sales and Trends reports expose refunds to allow you to monitor refund rate by product. You will see a negative unit value for refund transactions. Why there are refunds on my reports? We will provide a refund if the customer experience was in our opinion unsatisfactory (generally quality issues). One thing you can monitor on your reports is the rate of refunds and the content that is refunded since it is an indication of quality issues with your content. Apple Inc. iTunes Connect Sales and Trends Guide, App Store Version 5.3  iTunes Connect Sales and Trends Guide, App Store (Version 5.3, August 2012) 29Appendix K - Sample Sales Report The following is a sample Sales report to help you interpret its contents. Price fields are dependent on the storefront 1 from which the customer purchases the app, and the price of the app at the time of purchase 2 . (For complete field definitions see Appendix A) Reading the Report The example above is the most likely scenario you will see: ■ SKU – “SKU1” is the SKU attached to this app by the developer. ■ Developer – “Vendor” is the name that the app is sold under on the store ■ Title – “App-1” is the name of the app ■ Product Type Identifier – “1” denotes the type of transaction (initial download) ■ Units – “352” is the number of units sold for a given day/week ■ Developer Proceeds – “3.65” is proceeds, net of commission, you will receive for each sale of the app ■ Customer Currency – “GBP” (Great Britain Pounds) is the currency in which the customer purchased the app ■ Currency of Proceeds – “GBP” (Great Britain Pounds) is the currency in which your proceeds were earned for the app ■ Customer Price – “5.99” is the price paid by the customer for the app Apple Inc. iTunes Connect Sales and Trends Guide, App Store Version 5.3  iTunes Connect Sales and Trends Guide, App Store (Version 5.3, August 2012) 30 1 As new territories are added, storefronts will further differentiate records 2 If you change your price during the reporting period, the report will show multiple price points for the same countryAdditional Reporting Scenarios We have provided some additional scenarios and sample extract to help you further understand your reports. In your reports the Product Type Identifier denotes the type of transaction (See Appendix E for a list of all types). The Product Type Identifier must be taken into account in all of the following scenarios. Scenario 1 (Product Type Identifier=1; Units=16; Developer Proceeds=4.86) This is similar to the first line; the Developer Proceeds value will always be greater than zero for all paid apps and zero for free apps. Scenario 2 (Product Type Identifier=7; Units=1; Developer Proceeds=0) Certain line items will have 0 in the Developer Proceeds field. Even if you only have paid apps on the store, the Developer Proceeds will be 0 for all updates (Product Type Identifier = 7). Scenario 3 (Product Type Identifier=1; Units=-1; Developer Proceeds=7; Customer Price=-9.99) You may see negative units when a customer returns a product. All returns will have a Product Type Identifier of 1 and both Units and Customer Price will be a negative value. Refer to Appendix J for additional information on returns. Apple Inc. iTunes Connect Sales and Trends Guide, App Store Version 5.3  iTunes Connect Sales and Trends Guide, App Store (Version 5.3, August 2012) 31Appendix L – Other Uses Below you will see some sample ideas that the data can be used for on a daily basis. 1. Business Health Monitoring By tracking volume of sales per unit or revenue, the health of your business can be tracked. Sudden drop in sales may indicate issues such as top seller being not available any more. 2. Content Quality Issues By tracking the refunds, you can identify and replace the asset that is being refunded to the customer if the refunds are specific to one or more items. Typical ratio of refunds to overall sales shall not exceed 0.10%. 3. Pricing Issues When organizations get larger, it is always challenging to have fast/efficient communication between the operational teams that are providing the metadata to iTunes and the Management, Marketing, Finance and Business Development team. Tracking pricing will indicate any disconnect between different groups and will provide opportunity to fix issues sooner and minimize the impact. 4. Price Elasticity We believe that careful management of price can increase your sales. By using the reports you can monitor percent change in sales in correlation with a percent change in customer price. If applied correctly this type of analysis will help you set the best price for your product to maximize your revenue. Apple Inc. iTunes Connect Sales and Trends Guide, App Store Version 5.3  iTunes Connect Sales and Trends Guide, App Store (Version 5.3, August 2012) 32Appendix M - Newsstand Report Field Definitions The definitions apply to Newsstand reports. Report Field Report Data Type Values Notes Provider CHAR(5) - APPLE Up to 5 Characters The service provider in your reports will typically be Apple Provider Country CHAR(2) - US Up to 2 Characters The service provider country code will typically be US SKU VARCHAR(100) Up to 100 Characters This is a product identifier provided by you when the app is set up Developer VARCHAR(4000) Up to 4000 Characters You provided this on initial setup. Title VARCHAR(600) Up to 600 Characters You provided this when setting up the app Version VARCHAR(100) Up to 100 Characters You provided this when setting up the app Product Type Identifier VARCHAR(20) Up to 20 Characters This field defines the type of transaction (e.g. initial download, update, etc) – See Appendix E Units DECIMAL(18,2) Up to 18 Characters This is the aggregated number of units Developer Proceeds (per item) DECIMAL(18,2) Up to 18 Characters Your proceeds for each item delivered Customer Currency CHAR(3) Up to 3 Characters Three character ISO code indicates the currency the customer paid in - See Appendix H Country Code CHAR(2) Up to 2 Characters Two character ISO country code indicates what App Store the purchase occurred in – See Appendix F Currency of Proceeds CHAR(3) Up to 3 Characters Currency your proceeds are earned in – See Appendix H Apple Identifier DECIMAL(18,0) Up to 18 Characters This is Apple's unique identifier. If you have questions about a product, it is best to include this identifier. Customer Price DECIMAL(18,2) Up to 18 Characters Retail Price displayed on the App Store and charged to the customer. Promo Code VARCHAR(10) Up to 10 Characters If the transaction was part of a promotion this field will contain a value. For all non-promotional items this field will be blank - See Appendix G Parent Identifier VARCHAR(100) Up to 100 Characters For In-App Purchases this will be populated with the SKU from the originating app. Apple Inc. iTunes Connect Sales and Trends Guide, App Store Version 5.3  iTunes Connect Sales and Trends Guide, App Store (Version 5.3, August 2012) 33Subscription VARCHAR(10) Up to 10 Characters This field defines whether an auto-renewable subscription purchase is a new purchase or a renewal. See Appendix I. Period VARCHAR(30) Up to 30 Characters This field defines the duration of an auto-renewable subscription purchase. See Appendix I. Download Date (PST) TIMESTAMP(0) Date in MM/DD/YYYY Download Date Customer Identifier DECIMAL(18,0) Up to 18 Characters Customer Identification Report Date (Local) DATE Date in MM/DD/YYYY Report Date Sales/Return CHAR(1) Up to 1 character S or R; R is always a refund, R is not a reversal Apple Inc. iTunes Connect Sales and Trends Guide, App Store Version 5.3  iTunes Connect Sales and Trends Guide, App Store (Version 5.3, August 2012) 34 Secure Coding GuideContents Introduction to Secure Coding Guide 7 At a Glance 7 Hackers, Crackers, and Attackers 7 No Platform Is Immune 8 How to Use This Document 9 See Also 10 Types of Security Vulnerabilities 11 Buffer Overflows 11 Unvalidated Input 12 Race Conditions 13 Interprocess Communication 13 Insecure File Operations 13 Access Control Problems 14 Secure Storage and Encryption 15 Social Engineering 16 Avoiding Buffer Overflows and Underflows 17 Stack Overflows 18 Heap Overflows 20 String Handling 22 Calculating Buffer Sizes 25 Avoiding Integer Overflows and Underflows 27 Detecting Buffer Overflows 28 Avoiding Buffer Underflows 29 Validating Input and Interprocess Communication 33 Risks of Unvalidated Input 33 Causing a Buffer Overflow 33 Format String Attacks 34 URLs and File Handling 36 Code Insertion 37 Social Engineering 37 Modifications to Archived Data 38 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 2Fuzzing 39 Interprocess Communication and Networking 40 Race Conditions and Secure File Operations 43 Avoiding Race Conditions 43 Time of Check Versus Time of Use 44 Signal Handling 46 Securing Signal Handlers 46 Securing File Operations 47 Check Result Codes 47 Watch Out for Hard Links 48 Watch Out for Symbolic Links 49 Case-Insensitive File Systems Can Thwart Your Security Model 49 Create Temporary Files Correctly 50 Files in Publicly Writable Directories Are Dangerous 51 Other Tips 57 Elevating Privileges Safely 59 Circumstances Requiring Elevated Privileges 59 The Hostile Environment and the Principle of Least Privilege 60 Launching a New Process 61 Executing Command-Line Arguments 61 Inheriting File Descriptors 61 Abusing Environment Variables 62 Modifying Process Limits 62 File Operation Interference 63 Avoiding Elevated Privileges 63 Running with Elevated Privileges 63 Calls to Change Privilege Level 64 Avoiding Forking Off a Privileged Process 65 authopen 65 launchd 66 Limitations and Risks of Other Mechanisms 67 Factoring Applications 69 Example: Preauthorizing 69 Helper Tool Cautions 71 Authorization and Trust Policies 72 Security in a KEXT 72 Designing Secure User Interfaces 73 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 3 ContentsUse Secure Defaults 73 Meet Users’ Expectations for Security 74 Secure All Interfaces 75 Place Files in Secure Locations 75 Make Security Choices Clear 76 Fight Social Engineering Attacks 78 Use Security APIs When Possible 79 Designing Secure Helpers and Daemons 81 Avoid Puppeteering 81 Use Whitelists 82 Use Abstract Identifiers and Structures 82 Use the Smell Test 83 Treat Both App and Helper as Hostile 83 Run Daemons as Unique Users 84 Start Other Processes Safely 84 Security Development Checklists 86 Use of Privilege 86 Data, Configuration, and Temporary Files 88 Network Port Use 89 Audit Logs 91 Client-Server Authentication 93 Integer and Buffer Overflows 97 Cryptographic Function Use 97 Installation and Loading 98 Use of External Tools and Libraries 100 Kernel Security 101 Third-Party Software Security Guidelines 103 Respect Users’ Privacy 103 Provide Upgrade Information 103 Store Information in Appropriate Places 103 Avoid Requiring Elevated Privileges 104 Implement Secure Development Practices 104 Test for Security 104 Helpful Resources 105 Document Revision History 106 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 4 ContentsGlossary 107 Index 110 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 5 ContentsFigures, Tables, and Listings Avoiding Buffer Overflows and Underflows 17 Figure 2-1 Schematic view of the stack 19 Figure 2-2 Stack after malicious buffer overflow 20 Figure 2-3 Heap overflow 21 Figure 2-4 C string handling functions and buffer overflows 22 Figure 2-5 Buffer overflow crash log 29 Table 2-1 String functions to use and avoid 23 Table 2-2 Avoid hard-coded buffer sizes 25 Table 2-3 Avoid unsafe concatenation 26 Race Conditions and Secure File Operations 43 Table 4-1 C file functions to avoid and to use 55 Elevating Privileges Safely 59 Listing 5-1 Non-privileged process 70 Listing 5-2 Privileged process 71 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 6Secure coding is the practice of writing programs that are resistant to attack by malicious or mischievous people or programs. Secure coding helps protect a user’s data from theft or corruption. In addition, an insecure program can provide accessfor an attacker to take control of a server or a user’s computer, resulting in anything from a denial of service to a single user to the compromise of secrets, loss of service, or damage to the systems of thousands of users. Secure coding is important for all software; if you write any code that runs on Macintosh computers or on iOS devices, from scripts for your own use to commercial software applications, you should be familiar with the information in this document. At a Glance Every program is a potential target. Attackers will try to find security vulnerabilities in your applications or servers. They will then try to use these vulnerabilities to steal secrets, corrupt programs and data, and gain control of computer systems and networks. Your customers’ property and your reputation are at stake. Security is notsomething that can be added to software as an afterthought; just as a shed made out of cardboard cannot be made secure by adding a padlock to the door, an insecure tool or application may require extensive redesign to secure it. You must identify the nature of the threats to your software and incorporate secure coding practices throughout the planning and development of your product. This chapter explains the types of threatsthat yoursoftware may face. Other chaptersin this document describe specific types of vulnerabilities and give guidance on how to avoid them. Hackers, Crackers, and Attackers Contrary to the usage by most news media, within the computer industry the term hacker refers to an expert programmer—one who enjoyslearning about the intricacies of code or an operating system. In general, hackers are not malicious. When most hackers find security vulnerabilities in code, they inform the company or organization that’s responsible for the code so that they can fix the problem. Some hackers—especially if they feel their warnings are being ignored—publish the vulnerabilities or even devise and publish exploits (code that takes advantage of the vulnerability). 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 7 Introduction to Secure Coding GuideThe malicious individuals who break into programs and systems in order to do damage or to steal something are referred to as crackers, attackers, or black hats. Most attackers are not highly skilled, but take advantage of published exploit code and known techniques to do their damage. People (usually, though not always, young men) who use published code (scripts) to attack software and computer systems are sometimes called script kiddies. Attackers may be motivated by a desire to steal money, identities, and othersecretsfor personal gain; corporate secrets for their employer’s or their own use; or state secrets for use by hostile governments or terrorist organizations. Some crackers break into applications or operating systems just to show that they can do it; nevertheless, they can cause considerable damage. Because attacks can be automated and replicated, any weakness, no matter how slight, can be exploited. The large number of insiders who are attacking systems is of importance to security design because, whereas malicious hackers and script kiddies are most likely to rely on remote access to computers to do their dirty work, insiders might have physical access to the computer being attacked. Your software must be resistant to both attacks over a network and attacks by people sitting at the computer keyboard—you cannot rely on firewalls and server passwords to protect you. No Platform Is Immune So far, OS X has not fallen prey to any major, automated attack like the MyDoom virus. There are several reasons for this. One is that OS X is based on open source software such as BSD; many hackers have searched this software over the years looking for security vulnerabilities, so that not many vulnerabilities remain. Another is that the OS X turns off all routable networking services by default. Also, the email and internet clients used most commonly on OS X do not have privileged access to the operating system and are less vulnerable to attack than those used on some other common operating systems. Finally, Apple actively reviewsthe operating system and applications for security vulnerabilities, and issues downloadable security updates frequently. iOS is based on OS X and shares many of its security characteristics. In addition, it is inherently more secure than even OS X because each application is restricted in the files and system resources it can access. Beginning in version 10.7, Mac apps can opt into similar protection. That’s the good news. The bad news is that applications and operating systems are constantly under attack. Every day, black hat hackers discover new vulnerabilities and publish exploit code. Criminals and script kiddies then use that exploit code to attack vulnerable systems. Also, security researchers have found many vulnerabilities on a variety of systems that, if exploited, could have resulted in loss of data, allowing an attacker to steal secrets, or enabling an attacker to run code on someone else’s computer. Introduction to Secure Coding Guide At a Glance 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 8A large-scale, widespread attack is not needed to cause monetary and other damages; a single break-in is sufficient if the system broken into contains valuable information. Although major attacks of viruses or worms get a lot of attention from the media, the destruction or compromising of data on a single computer is what matters to the average user. For your users’sake, you should take every security vulnerability seriously and work to correct known problems quickly. If every Macintosh and iOS developer followsthe advice in this document and other books on electronic security, and if the owner of each Macintosh takes common-sense precautions such as using strong passwords and encrypting sensitive data, then OS X and iOS will maintain their reputationsfor being safe, reliable operating systems, and your company’s products will benefit from being associated with OS X or iOS. How to Use This Document This document assumes that you have already read Security Overview. The document begins with “Types of Security Vulnerabilities” (page 11), which gives a brief introduction to the nature of each of the types of security vulnerability commonly found in software. This chapter provides background information that you should understand before reading the other chapters in the document. If you’re not sure what a race condition is, for example, or why it poses a security risk, this chapter is the place to start. The remaining chapters in the document discuss specific types of security vulnerabilities in some detail. These chapters can be read in any order, or as suggested by the software development checklist in “Security Development Checklists” (page 86). ● “Avoiding Buffer Overflows And Underflows” (page 17) describes the various types of buffer overflows and explains how to avoid them. ● “Validating Input And Interprocess Communication” (page 33) discusses why and how you must validate every type of input your program receives from untrusted sources. ● “Race Conditions and Secure File Operations” (page 43) explains how race conditions occur, discusses ways to avoid them, and describes insecure and secure file operations. ● “Elevating Privileges Safely” (page 59) describes how to avoid running code with elevated privileges and what to do if you can’t avoid it entirely. ● “Designing Secure User Interfaces” (page 73) discusses how the user interface of a program can enhance or compromise security and gives some guidance on how to write a security-enhancing UI. ● “Designing Secure Helpers And Daemons” (page 81) describes how to design helper applications in ways that are conducive to privilege separation. Introduction to Secure Coding Guide How to Use This Document 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 9In addition, the appendix “Security Development Checklists” (page 86) provides a convenient list of tasks that you should perform before shipping an application, and the appendix “Third-Party Software Security Guidelines” (page 103) provides a list of guidelines for third-party applications bundled with OS X. See Also This document concentrates on security vulnerabilities and programming practices of special interest to developers using OS X or iOS. For discussions of secure programming of interest to all programmers, see the following books and documents: ● See Viega and McGraw, Building Secure Software , Addison Wesley, 2002; for a general discussion of secure programming, especially as it relates to C programming and writing scripts. ● SeeWheeler, Secure Programming for Linux andUnixHOWTO, available athttp://www.dwheeler.com/secureprograms/; for discussions ofseveral types ofsecurity vulnerabilities and programming tipsfor UNIX-based operating systems, most of which apply to OS X. ● See Cranor and Garfinkel, Security and Usability: Designing Secure Systems that People Can Use , O’Reilly, 2005; for information on writing user interfaces that enhance security. For documentation of security-related application programming interfaces (APIs) for OS X (and iOS, where noted), see the following Apple documents: ● For an introduction to some security concepts and to learn about the security features available in OS X, see Security Overview. ● For information on secure networking, see Cryptographic Services Guide , Secure Transport Reference and CFNetwork Programming Guide . ● For information on OS X authorization and authentication APIs, see Authentication, Authorization, and Permissions Guide , Authorization Services Programming Guide , Authorization Services C Reference , and Security Foundation Framework Reference . ● If you are using digital certificates for authentication, see Cryptographic Services Guide , Certificate, Key, and Trust Services Reference (iOS version available) and Certificate, Key, and Trust Services Programming Guide . ● For secure storage of passwords and other secrets, see Cryptographic Services Guide , Keychain Services Reference (iOS version available) and Keychain Services Programming Guide . For information about security in web application design, visit http://www.owasp.org/. Introduction to Secure Coding Guide See Also 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 10Most software security vulnerabilities fall into one of a small set of categories: ● buffer overflows ● unvalidated input ● race conditions ● access-control problems ● weaknesses in authentication, authorization, or cryptographic practices This chapter describes the nature of each type of vulnerability. Buffer Overflows A buffer overflow occurs when an application attempts to write data past the end (or, occasionally, past the beginning) of a buffer. Buffer overflows can cause applications to crash, can compromise data, and can provide an attack vector for further privilege escalation to compromise the system on which the application is running. Books on software security invariably mention buffer overflows as a major source of vulnerabilities. Exact numbers are hard to come by, but as an indication, approximately 20% of the published exploits reported by the United States Computer Emergency Readiness Team (US-CERT) for 2004 involved buffer overflows. Any application or system software that takes input from the user, from a file, or from the network has to store that input, at least temporarily. Except in special cases, most application memory isstored in one of two places: ● stack—A part of an application’s addressspace thatstores data that isspecific to a single call to a particular function, method, block, or other equivalent construct. ● heap—General purpose storage for an application. Data stored in the heap remains available as long as the application is running (or until the application explicitly tells the operating system that it no longer needs that data). Class instances, data allocated with malloc, core foundation objects, and most other application data resides on the heap. (Note, however, that the local variables that actually point to the data are stored in the stack.) 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 11 Types of Security VulnerabilitiesBuffer overflow attacks generally occur by compromising either the stack, the heap, or both. For more information, read “Avoiding Buffer Overflows And Underflows” (page 17) Unvalidated Input As a general rule, you should check all input received by your program to make sure that the data isreasonable. For example, a graphics file can reasonably contain an image that is 200 by 300 pixels, but cannot reasonably contain an image that is 200 by -1 pixels. Nothing prevents a file from claiming to contain such an image, however (apart from convention and common sense). A naive program attempting to read such a file would attempt to allocate a buffer of an incorrect size, leading to the potential for a heap overflow attack or other problem. For this reason, you must check your input data carefully. This process is commonly known as input validation or sanity checking. Any input received by your program from an untrusted source is a potential target for attack. (In this context, an ordinary user is an untrusted source.) Examples of input from an untrusted source include (but are not restricted to): ● text input fields ● commands passed through a URL used to launch the program ● audio, video, or graphics files provided by users or other processes and read by the program ● command line input ● any data read from an untrusted server over a network ● any untrusted data read from a trusted server over a network (user-submitted HTML or photos on a bulletin board, for example) Hackers look at every source of input to the program and attempt to pass in malformed data of every type they can imagine. If the program crashes or otherwise misbehaves, the hacker then triesto find a way to exploit the problem. Unvalidated-input exploits have been used to take control of operating systems, steal data, corrupt users’ disks, and more. One such exploit was even used to “jail break” iPhones. “Validating Input And Interprocess Communication” (page 33) describes common types of input-validation vulnerabilities and what to do about them. Types of Security Vulnerabilities Unvalidated Input 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 12Race Conditions A race condition exists when changes to the order of two or more events can cause a change in behavior. If the correct order of execution is required for the proper functioning of the program, this is a bug. If an attacker can take advantage of the situation to insert malicious code, change a filename, or otherwise interfere with the normal operation of the program, the race condition is a security vulnerability. Attackers can sometimes take advantage of small time gaps in the processing of code to interfere with the sequence of operations, which they then exploit. For more information about race conditions and how to prevent them, read “Race Conditions and Secure File Operations” (page 43). Interprocess Communication Separate processes—either within a single program or in two different programs—sometimes have to share information. Common methods include using shared memory or using some messaging protocol, such as Sockets, provided by the operating system. These messaging protocols used for interprocess communication are often vulnerable to attack; thus, when writing an application, you must always assume that the process at the other end of your communication channel could be hostile. For more information on how to perform secure interprocess communication, read “Validating Input And Interprocess Communication” (page 33). Insecure File Operations In addition to time-of-check–time-of-use problems, many other file operations are insecure. Programmers often make assumptions about the ownership, location, or attributes of a file that might not be true. For example, you might assume that you can always write to a file created by your program. However, if an attacker can change the permissions or flags on that file after you create it, and if you fail to check the result code after a write operation, you will not detect the fact that the file has been tampered with. Examples of insecure file operations include: ● writing to or reading from a file in a location writable by another user ● failing to make the right checks for file type, device ID, links, and other settings before using a file ● failing to check the result code after a file operation ● assuming that if a file has a local pathname, it has to be a local file These and other insecure file operations are discussed in more detail in “Securing File Operations” (page 47). Types of Security Vulnerabilities Race Conditions 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 13Access Control Problems Access control is the process of controlling who is allowed to do what. This ranges from controlling physical access to a computer—keeping your servers in a locked room, for example—to specifying who has access to a resource (a file, for example) and what they are allowed to do with that resource (such as read only). Some access control mechanisms are enforced by the operating system,some by the individual application orserver, some by a service (such as a networking protocol) in use. Many security vulnerabilities are created by the careless or improper use of access controls, or by the failure to use them at all. Much of the discussion of security vulnerabilities in the software security literature is in terms of privileges, and many exploits involve an attacker somehow gaining more privileges than they should have. Privileges, also called permissions, are access rights granted by the operating system, controlling who is allowed to read and write files, directories, and attributes of files and directories (such as the permissions for a file), who can execute a program, and who can perform other restricted operations such as accessing hardware devices and making changes to the network configuration. File permissions and access control in OS X are discussed in File System Programming Guide . Of particular interest to attackers is the gaining of root privileges, which refers to having the unrestricted permission to perform any operation on the system. An application running with root privileges can access everything and change anything. Many security vulnerabilities involve programming errors that allow an attacker to obtain root privileges. Some such exploits involve taking advantage of buffer overflows or race conditions, which in some special circumstances allow an attacker to escalate their privileges. Others involve having access to system files that should be restricted or finding a weakness in a program—such as an application installer—that is already running with root privileges. For this reason, it’s important to always run programs with as few privileges as possible. Similarly, when it is necessary to run a program with elevated privileges, you should do so for as short a time as possible. Much access control is enforced by applications, which can require a user to authenticate before granting authorization to perform an operation. Authentication can involve requesting a user name and password, the use of a smart card, a biometric scan, or some other method. If an application calls the OS X Authorization Services application interface to authenticate a user, it can automatically take advantage of whichever authentication method is available on the user’s system. Writing your own authentication code is a less secure alternative, as it might afford an attacker the opportunity to take advantage of bugs in your code to bypass your authentication mechanism, or it might offer a less secure authentication method than the standard one used on the system. Authorization and authentication are described further in Security Overview. Digital certificates are commonly used—especially over the Internet and with email—to authenticate users and servers, to encrypt communications, and to digitally sign data to ensure that it has not been corrupted and was truly created by the entity that the user believes to have created it. Incorrect or careless use of digital certificates can lead to security vulnerabilities. For example, a server administration program shipped with a Types of Security Vulnerabilities Access Control Problems 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 14standard self-signed certificate, with the intention that the system administrator would replace it with a unique certificate. However, many system administrators failed to take this step, with the result that an attacker could decrypt communication with the server. [CVE-2004-0927] It’s worth noting that nearly all access controls can be overcome by an attacker who has physical access to a machine and plenty of time. For example, no matter what you set a file’s permissions to, the operating system cannot prevent someone from bypassing the operating system and reading the data directly off the disk. Only restricting access to the machine itself and the use of robust encryption techniques can protect data from being read or corrupted under all circumstances. The use of access controls in your program is discussed in more detail in “Elevating Privileges Safely” (page 59). Secure Storage and Encryption Encryption can be used to protect a user’s secrets from others, either during data transmission or when the data is stored. (The problem of how to protect a vendor’s data from being copied or used without permission is not addressed here.) OS X provides a variety of encryption-based security options, such as ● FileVault ● the ability to create encrypted disk images ● keychain ● certificate-based digital signatures ● encryption of email ● SSL/TLS secure network communication ● Kerberos authentication The list of security options in iOS includes ● passcode to prevent unauthorized use of the device ● data encryption ● the ability to add a digital signature to a block of data ● keychain ● SSL/TLS secure network communication Types of Security Vulnerabilities Secure Storage and Encryption 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 15Each service has appropriate uses, and each haslimitations. For example, FileVault, which encryptsthe contents of a user’s root volume (in OS X v10.7 and later) or home directory (in earlier versions), is a very important security feature for shared computers or computers to which attackers might gain physical access, such as laptops. However, it is not very helpful for computers that are physically secure but that might be attacked over the network while in use, because in that case the home directory is in an unencrypted state and the threat is from insecure networks or shared files. Also, FileVault is only as secure as the password chosen by the user—if the userselects an easily guessed password, or writesit down in an easily found location, the encryption is useless. It is a serious mistake to try to create your own encryption method or to implement a published encryption algorithm yourself unless you are already an expert in the field. It is extremely difficult to write secure, robust encryption code that generates unbreakable ciphertext, and it is almost always a security vulnerability to try. For OS X, if you need cryptographic services beyond those provided by the OS X user interface and high-level programming interfaces, you can use the open-source CSSM Cryptographic Services Manager. See the documentation provided with the Open Source security code, which you can download at http://developer.apple.com/darwin/projects/security/. For iOS, the development APIs should provide all the services you need. For more information about OS X and iOS security features, read Authentication, Authorization, and Permissions Guide . Social Engineering Often the weakest link in the chain ofsecurity features protecting a user’s data and software isthe user himself. As developers eliminate buffer overflows, race conditions, and othersecurity vulnerabilities, attackersincreasingly concentrate on fooling users into executing malicious code or handing over passwords, credit-card numbers, and other private information. Tricking a user into giving up secrets or into giving access to a computer to an attacker is known as social engineering. For example, in February of 2005, a large firm that maintains credit information, Social Security numbers, and other personal information on virtually all U.S. citizens revealed that they had divulged information on at least 150,000 people to scam artists who had posed as legitimate businessmen. According to Gartner (www.gartner.com), phishing attacks cost U.S. banks and credit card companies about $1.2 billion in 2003, and this number is increasing. They estimate that between May 2004 and May 2005, approximately 1.2 million computer users in the United States suffered losses caused by phishing. Software developers can counter such attacks in two ways: through educating their users, and through clear and well-designed user interfaces that give users the information they need to make informed decisions. For more advice on how to design a user interface that enhances security, see “Designing Secure User Interfaces” (page 73). Types of Security Vulnerabilities Social Engineering 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 16Buffer overflows, both on the stack and on the heap, are a major source of security vulnerabilities in C, Objective-C, and C++ code. This chapter discusses coding practicesthat will avoid buffer overflow and underflow problems, lists tools you can use to detect buffer overflows, and provides samples illustrating safe code. Every time your program solicits input (whether from a user, from a file, over a network, or by some other means), there is a potential to receive inappropriate data. For example, the input data might be longer than what you have reserved room for in memory. When the input data islonger than will fit in the reserved space, if you do not truncate it, that data will overwrite other data in memory. When this happens, it is called a buffer overflow. If the memory overwritten contained data essential to the operation of the program, this overflow causes a bug that, being intermittent, might be very hard to find. If the overwritten data includes the address of other code to be executed and the user has done this deliberately, the user can point to malicious code that your program will then execute. Similarly, when the input data is or appearsto be shorter than the reserved space (due to erroneous assumptions, incorrect length values, or copying raw data as a C string), this is called a buffer underflow. This can cause any number of problems from incorrect behavior to leaking data that is currently on the stack or heap. Although most programming languages check input againststorage to prevent buffer overflows and underflows, C, Objective-C, and C++ do not. Because many programs link to C libraries, vulnerabilities in standard libraries can cause vulnerabilities even in programs written in “safe” languages. For thisreason, even if you are confident that your code isfree of buffer overflow problems, you should limit exposure by running with the least privileges possible. See “Elevating Privileges Safely” (page 59) for more information on this topic. Keep in mind that obvious forms of input, such as strings entered through dialog boxes, are not the only potential source of malicious input. For example: 1. Buffer overflowsin one operating system’s help system could be caused by maliciously prepared embedded images. 2. A commonly-used media player failed to validate a specific type of audio files, allowing an attacker to execute arbitrary code by causing a buffer overflow with a carefully crafted audio file. [ 1 CVE-2006-1591 2 CVE-2006-1370] There are two basic categories of overflow: stack overflows and heap overflows. These are described in more detail in the sections that follow. 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 17 Avoiding Buffer Overflows and UnderflowsStack Overflows In most operating systems, each application has a stack (and multithreaded applications have one stack per thread). This stack contains storage for locally scoped data. The stack is divided up into units called stack frames. Each stack frame contains all data specific to a particular call to a particular function. This data typically includes the function’s parameters, the complete set of local variables within that function, and linkage information—that is, the address of the function call itself, where execution continues when the function returns). Depending on compiler flags, it may also contain the address of the top of the next stack frame. The exact content and order of data on the stack depends on the operating system and CPU architecture. Each time a function is called, a new stack frame is added to the top of the stack. Each time a function returns, the top stack frame is removed. At any given point in execution, an application can only directly access the data in the topmost stack frame. (Pointers can get around this, but it is generally a bad idea to do so.) This design makes recursion possible because each nested call to a function gets its own copy of local variables and parameters. Avoiding Buffer Overflows and Underflows Stack Overflows 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 18Figure 2-1 illustrates the organization of the stack. Note that this figure is schematic only; the actual content and order of data put on the stack depends on the architecture of the CPU being used. See OS X ABI Function Call Guide for descriptions of the function-calling conventions used in all the architectures supported by OS X. Figure 2-1 Schematic view of the stack Function A Function B Function C Function A data Parameters for call to function B Function A return address Function B data Parameters for call to function C Function B return address Function C data Space for parameters for next subroutine call Function C return address In general, an application should check all input data to make sure it is appropriate for the purpose intended (for example, making sure that a filename is of legal length and contains no illegal characters). Unfortunately, in many cases, programmers do not bother, assuming that the user will not do anything unreasonable. This becomes a serious problem when the application stores that data into a fixed-size buffer. If the user is malicious (or opens a file that contains data created by someone who is malicious), he or she might provide data that is longer than the size of the buffer. Because the function reserves only a limited amount of space on the stack for this data, the data overwrites other data on the stack. As shown in Figure 2-2, a clever attacker can use this technique to overwrite the return address used by the function, substituting the address of his own code. Then, when function C completes execution, rather than returning to function B, it jumps to the attacker’s code. Avoiding Buffer Overflows and Underflows Stack Overflows 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 19Because the application executes the attacker’s code, the attacker’s code inherits the user’s permissions. If the user islogged on as an administrator (the default configuration in OS X), the attacker can take complete control of the computer, reading data from the disk, sending emails, and so forth. (In iOS, applications are much more restricted in their privileges and are unlikely to be able to take complete control of the device.) Figure 2-2 Stack after malicious buffer overflow Function A Function B Function C Function A data Parameters for call to function B Function A return address Function B data Parameters for call to function C Function B return address Function C data Space for parameters for next subroutine call Function C return address Parameter overflow Address of attackerʼs code In addition to attacks on the linkage information, an attacker can also alter program operation by modifying local data and function parameters on the stack. For example, instead of connecting to the desired host, the attacker could modify a data structure so that your application connects to a different (malicious) host. Heap Overflows As mentioned previously, the heap is used for all dynamically allocated memory in your application. When you use malloc, new, or equivalent functions to allocate a block of memory or instantiate an object, the memory that backs those pointers is allocated on the heap. Avoiding Buffer Overflows and Underflows Heap Overflows 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 20Because the heap is used to store data but is not used to store the return address value of functions and methods, and because the data on the heap changes in a nonobvious way as a program runs, it is less obvious how an attacker can exploit a buffer overflow on the heap. To some extent, it is this nonobviousness that makes heap overflows an attractive target—programmers are less likely to worry about them and defend against them than they are for stack overflows. Figure 2-1 illustrates a heap overflow overwriting a pointer. Figure 2-3 Heap overflow Buffer overflow Data Buffer Data Pointer Data Data Data Data In general, exploiting a buffer overflow on the heap is more challenging than exploiting an overflow on the stack. However, many successful exploits have involved heap overflows. There are two ways in which heap overflows are exploited: by modifying data and by modifying objects. An attacker can exploit a buffer overflow on the heap by overwriting critical data, either to cause the program to crash or to change a value that can be exploited later (overwriting a stored user ID to gain additional access, for example). Modifying this data is known as a non-control-data attack. Much of the data on the heap is generated internally by the program rather than copied from user input;such data can be in relatively consistent locations in memory, depending on how and when the application allocates it. Avoiding Buffer Overflows and Underflows Heap Overflows 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 21An attacker can also exploit a buffer overflow on the heap by overwriting pointers. In many languages such as C++ and Objective-C, objects allocated on the heap contain tables of function and data pointers. By exploiting a buffer overflow to change such pointers, an attacker can potentially substitute different data or even replace the instance methods in a class object. Exploiting a buffer overflow on the heap might be a complex, arcane problem to solve, but crackers thrive on just such challenges. For example: 1. A heap overflow in code for decoding a bitmap image allowed remote attackersto execute arbitrary code. 2. A heap overflow vulnerability in a networking server allowed an attacker to execute arbitrary code by sending an HTTP POST request with a negative “Content-Length” header. [ 1 CVE-2006-0006 2 CVE-2005-3655] String Handling Strings are a common form of input. Because many string-handling functions have no built-in checks for string length, strings are frequently the source of exploitable buffer overflows. Figure 2-4 illustrates the different ways three string copy functions handle the same over-length string. Figure 2-4 C string handling functions and buffer overflows L A R G E R \0 L A R G E L A R G \0 Char destination[5]; char *source = “LARGER”; strcpy(destination, source); strncpy(destination, source, sizeof(destination)); strlcpy(destination, source, sizeof(destination)); As you can see, the strcpy function merely writes the entire string into memory, overwriting whatever came after it. The strncpy function truncates the string to the correct length, but without the terminating null character. When this string is read, then, all of the bytes in memory following it, up to the next null character, might be read as part of the string. Although this function can be used safely, it is a frequent source of programmer Avoiding Buffer Overflows and Underflows String Handling 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 22mistakes, and thus is regarded as moderately unsafe. To safely use strncpy, you must either explicitly zero the last byte of the buffer after calling strncpy or pre-zero the buffer and then pass in a maximum length that is one byte smaller than the buffer size. Only the strlcpy function is fully safe, truncating the string to one byte smaller than the buffer size and adding the terminating null character. Table 2-1 summarizes the common C string-handling routines to avoid and which to use instead. Table 2-1 String functions to use and avoid Don’t use these functions Use these instead strcat strlcat strcpy strlcpy strncat strlcat strncpy strlcpy snprintf or asprintf (See note) sprintf vsnprintf or vasprintf (See note) vsprintf fgets (See note) gets Avoiding Buffer Overflows and Underflows String Handling 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 23Security Note for snprintf and vsnprintf: The functions snprintf, vsnprintf, and variants are dangerous if used incorrectly. Although they do behave functionally like strlcat and similar in that they limit the bytes written to n-1, the length returned by these functions is the length that would have been printed if n were infinite . For this reason, you must not use this return value to determine where to null-terminate the string or to determine how many bytes to copy from the string at a later time. Security Note for fgets: Although the fgets function provides the ability to read a limited amount of data, you must be careful when using it. Like the other functions in the “safer” column, fgets alwaysterminatesthe string. However, unlike the other functionsin that column, it takes a maximum number of bytes to read, not a buffer size. In practical terms, this means that you must always pass a size value that is one fewer than the size of the buffer to leave room for the null termination. If you do not, the fgets function will dutifully terminate the string past the end of your buffer, potentially overwriting whatever byte of data follows it. You can also avoid string handling buffer overflows by using higher-level interfaces. ● If you are using C++, the ANSI C++ string class avoids buffer overflows, though it doesn’t handle non-ASCII encodings (such as UTF-8). ● If you are writing code in Objective-C, use the NSString class. Note that an NSString object has to be converted to a C string in order to be passed to a C routine, such as a POSIX function. ● If you are writing code in C, you can use the Core Foundation representation of a string, referred to as a CFString, and the string-manipulation functions in the CFString API. The Core Foundation CFString is “toll-free bridged” with its Cocoa Foundation counterpart, NSString. This means that the Core Foundation type is interchangeable in function or method calls with its equivalent Foundation object. Therefore, in a method where you see an NSString * parameter, you can pass in a value of type CFStringRef, and in a function where you see a CFStringRef parameter, you can pass in an NSString instance. This also applies to concrete subclasses of NSString. See CFString Reference , Foundation Framework Reference , and Carbon-Cocoa IntegrationGuide formore details on using these representations of strings and on converting between CFString objects and NSString objects. Avoiding Buffer Overflows and Underflows String Handling 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 24Calculating Buffer Sizes When working with fixed-length buffers, you should always use sizeof to calculate the size of a buffer, and then make sure you don’t put more data into the buffer than it can hold. Even if you originally assigned a static size to the buffer, either you or someone else maintaining your code in the future might change the buffer size but fail to change every case where the buffer is written to. The first example, Table 2-2, shows two ways of allocating a character buffer 1024 bytes in length, checking the length of an input string, and copying it to the buffer. Table 2-2 Avoid hard-coded buffer sizes Instead of this: Do this: #define BUF_SIZE 1024 ... char buf[BUF_SIZE]; ... if (size < BUF_SIZE) { ... } char buf[1024]; ... if (size <= 1023) { ... } char buf[1024]; ... if (size < sizeof(buf)) { ... } char buf[1024]; ... if (size < 1024) { ... } The two snippets on the left side are safe as long as the original declaration of the buffer size is never changed. However, if the buffer size gets changed in a later version of the program without changing the test, then a buffer overflow will result. The two snippets on the right side show safer versions of this code. In the first version, the buffer size is set using a constant that is set elsewhere, and the check uses the same constant. In the second version, the buffer is set to 1024 bytes, but the check calculates the actual size of the buffer. In either of these snippets, changing the original size of the buffer does not invalidate the check. TTable 2-3, shows a function that adds an .ext suffix to a filename. Avoiding Buffer Overflows and Underflows Calculating Buffer Sizes 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 25Table 2-3 Avoid unsafe concatenation Instead of this: Do this: { char file[MAX_PATH]; ... addsfx(file, sizeof(file)); ... } static *suffix = ".ext"; size_t addsfx(char *buf, uint size) { size_t ret = strlcat(buf, suffix, size); if (ret >= size) { fprintf(stderr, "Buffer too small....\n"); } return ret; } { char file[MAX_PATH]; ... addsfx(file); ... } static *suffix = ".ext"; char *addsfx(char *buf) { return strcat(buf, suffix); } Both versions use the maximum path length for a file as the buffer size. The unsafe version in the left column assumes that the filename does not exceed this limit, and appends the suffix without checking the length of the string. The safer version in the right column uses the strlcat function, which truncates the string if it exceeds the size of the buffer. Important: You should always use an unsigned variable (such as size_t) when calculating sizes of buffers and of data going into buffers. Because negative numbers are stored as large positive numbers, if you use signed variables, an attacker might be able to cause a miscalculation in the size of the buffer or data by writing a large number to your program. See “Avoiding Integer Overflows And Underflows” (page 27) for more information on potential problems with integer arithmetic. For a further discussion of this issue and a list of more functions that can cause problems, see Wheeler, Secure Programming for Linux and Unix HOWTO (http://www.dwheeler.com/secure-programs/). Avoiding Buffer Overflows and Underflows Calculating Buffer Sizes 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 26Avoiding Integer Overflows and Underflows If the size of a buffer is calculated using data supplied by the user, there is the potential for a malicious user to enter a number that is too large for the integer data type, which can cause program crashes and other problems. In two’s-complement arithmetic (used forsigned integer arithmetic by most modern CPUs), a negative number is represented by inverting all the bits of the binary number and adding 1. A 1 in the most-significant bit indicates a negative number. Thus, for 4-byte signed integers, 0x7fffffff = 2147483647, but 0x80000000 = -2147483648 Therefore, int 2147483647 + 1 = - 2147483648 If a malicious user specifies a negative number where your program is expecting only unsigned numbers, your program might interpret it as a very large number. Depending on what that number is used for, your program might attempt to allocate a buffer of thatsize, causing the memory allocation to fail or causing a heap overflow if the allocation succeeds. In an early version of a popular web browser, for example, storing objects into a JavaScript array allocated with negative size could overwrite memory. [CVE-2004-0361] In other cases, if you use signed values to calculate buffer sizes and test to make sure the data is not too large for the buffer, a sufficiently large block of data will appear to have a negative size, and will therefore pass the size test while overflowing the buffer. Depending on how the buffer size is calculated, specifying a negative number could result in a buffer too small for its intended use. For example, if your program wants a minimum buffer size of 1024 bytes and adds to that a number specified by the user, an attacker might cause you to allocate a buffer smaller than the minimum size by specifying a large positive number, as follows: 1024 + 4294966784 = 512 0x400 + 0xFFFFFE00 = 0x200 Also, any bits that overflow past the length of an integer variable (whether signed or unsigned) are dropped. For example, when stored in a 32-bit integer, 2**32 == 0. Because it is not illegal to have a buffer with a size of 0, and because malloc(0) returns a pointer to a small block, your code might run without errors if an attacker specifies a value that causes your buffer size calculation to be some multiple of 2**32. In other words, for any values of n and m where (n * m) mod 2**32 == 0, allocating a buffer of size n*m results in a valid pointer to a buffer of some very small (and architecture-dependent) size. In that case, a buffer overflow is assured. Avoiding Buffer Overflows and Underflows Avoiding Integer Overflows and Underflows 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 27To avoid such problems, when performing buffer math, you should always include checks to make sure no integer overflow occurred. A common mistake when performing these tests is to check the result of the multiplication or other operation: size_t bytes = n * m; if (bytes < n || bytes < m) { /* BAD BAD BAD */ ... /* allocate "bytes" space */ } Unfortunately, the C language specification allows the compiler to optimize out such tests [CWE-733, CERT VU#162289]. Thus, the only correct way to test for integer overflow is to divide the maximum allowable result by the multiplier and comparing the result to the multiplicand or vice-versa. If the result is smaller than the multiplicand, the product of those two values would cause an integer overflow. For example: size_t bytes = n * m; if (n > 0 && m > 0 && SIZE_MAX/n >= m) { ... /* allocate "bytes" space */ } Detecting Buffer Overflows To test for buffer overflows, you should attempt to enter more data than is asked for wherever your program accepts input. Also, if your program accepts data in a standard format, such as graphics or audio data, you should attempt to pass it malformed data. This process is known as fuzzing. If there are buffer overflows in your program, it will eventually crash. (Unfortunately, it might not crash until some time later, when it attempts to use the data that was overwritten.) The crash log might provide some clues that the cause of the crash was a buffer overflow. If, for example, you enter a string containing the Avoiding Buffer Overflows and Underflows Detecting Buffer Overflows 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 28uppercase letter “A” several times in a row, you might find a block of data in the crash log that repeats the number 41, the ASCII code for “A” (see Figure 2-2). If the program is trying to jump to a location that is actually an ASCII string, that’s a sure sign that a buffer overflow was responsible for the crash. Figure 2-5 Buffer overflow crash log Exception: EXC_BAD_ACCESS (0x0001) Codes: KERN_INVALID_ADDRESS (0x0001) at 0x41414140 Thread 0 Crashed: Thread 0 crashed with PPC Thread State 64: srr0: 0x0000000041414140 srr1: 0x000000004200f030 vrsave: 0x0000000000000000 cr: 0x48004242 xer: 0x0000000020000007 1r: 0x0000000041414141 ctr: 0x000000009077401c r0: 0x0000000041414141 r1: 0x00000000bfffe660 r2: 0x0000000000000000 r3: 000000000000000001 r4: 0x0000000000000041 r5: 0x00000000bfffdd50 r6: 0x0000000000000052 r7: 0x00000000bfffe638 r8: 0x0000000090774028 r9: 0x00000000bfffddd8 r10: 0x00000000bfffe380 r11: 0x0000000024004248 r12: 0x000000009077401c r13: 0x00000000a365c7c0 r14: 0x0000000000000100 r15: 0x0000000000000000 r16: 0x00000000a364c75c r17: 0x00000000a365c75c r18: 0x00000000a365c75c r19: 0x00000000a366c75c r20: 0x0000000000000000 r21: 0x0000000000000000 r22: 0x00000000a365c75c r23: 0x000000000034f5b0 r24: 0x00000000a3662aa4 r25: 0x000000000054c840 r26: 0x00000000a3662aa4 r27: 0x0000000000002f44 r28: 0x000000000034c840 r29: 0x0000000041414141 r30: 0x0000000041414141 r31: 0x0000000041414141 If there are any buffer overflows in your program, you should always assume that they are exploitable and fix them. It is much harder to prove that a buffer overflow is not exploitable than to just fix the bug. Also note that, although you can test for buffer overflows, you cannot test for the absence of buffer overflows; it is necessary, therefore, to carefully check every input and every buffer size calculation in your code. For more information on fuzzing, see “Fuzzing” (page 39) in “Validating Input And Interprocess Communication” (page 33). Avoiding Buffer Underflows Fundamentally, buffer underflows occur when two parts of your code disagree about the size of a buffer or the data in that buffer. For example, a fixed-length C string variable might have room for 256 bytes, but might contain a string that is only 12 bytes long. Buffer underflow conditions are not always dangerous; they become dangerous when correct operation depends upon both parts of your code treating the data in the same way. This often occurs when you read the buffer to copy it to another block of memory, to send it across a network connection, and so on. There are two broad classes of buffer underflow vulnerabilities: short writes, and short reads. Avoiding Buffer Overflows and Underflows Avoiding Buffer Underflows 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 29A short write vulnerability occurs when a short write to a buffer fails to fill the buffer completely. When this happens, some of the data that was previously in the buffer is still present after the write. If the application later performs an operation on the entire buffer (writing it to disk or sending it over the network, for example), that existing data comes along for the ride. The data could be random garbage data, but if the data happens to be interesting, you have an information leak. Further, when such an underflow occurs, if the values in those locations affect program flow, the underflow can potentially cause incorrect behavior up to and including allowing you to skip past an authentication or authorization step by leaving the existing authorization data on the stack from a previous call by another user, application, or other entity. Short write example (systemcall): For example, consider a UNIX system call that requires a command data structure, and includes an authorization token in that data structure. Assume that there are multiple versions of the data structure, with different lengths, so the system call takes both the structure and the length. Assume that the authorization token is fairly far down in the structure. Suppose a malicious application passesin a command structure, and passes a size that encompasses the data up to, but not including, the authorization token. The kernel’s system call handler calls copyin, which copies a certain number of bytes from the application into the data structure in the kernel’s address space. If the kernel does not zero-fill that data structure, and if the kernel does not check to see if the size is valid, there is a narrow possibility that the stack might still contain the previous caller’s authorization token at the same address in kernel memory. Thus, the attacker is able to perform an operation that should have been disallowed. A short read vulnerability occurs when a read from a buffer fails to read the complete contents of a buffer. If the program then makes decisions based on that short read, any number of erroneous behaviors can result. This usually occurs when a C string function is used to read from a buffer that does not actually contain a valid C string. A C string is defined as a string containing a series of bytes that ends with a null terminator. By definition, it cannot contain any null bytes prior to the end of the string. As a result, C-string-based functions, such as strlen, strlcpy, and strdup, copy a string until the first null terminator, and have no knowledge of the size of the original source buffer. By contrast, strings in other formats (a CFStringRef object, a Pascal string, or a CFDataRef blob) have an explicit length and can contain null bytes at arbitrary locations in the data. If you convert such a string into a C string and then evaluate that C string, you get incorrect behavior because the resulting C string effectively ends at the first null byte. Avoiding Buffer Overflows and Underflows Avoiding Buffer Underflows 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 30Short read example (SSL verification): An example of a short read vulnerability occurred in many SSL stacks a few years ago. By applying for an SSL cert for a carefully crafted subdomain of a domain that you own, you could effectively create a certificate that was valid for arbitrary domains. Consider a subdomain in the form targetdomain.tld[null_byte].yourdomain.tld. Because the certificate signing request contains a Pascalstring, assuming that the certificate authority interprets it correctly, the certificate authority would contact the owner of yourdomain.tld and would ask for permission to deliver the certificate. Because you own the domain, you would agree to it. You would then have a certificate that is valid for the rather odd-looking subdomain in question. When checking the certificate for validity, however, many SSL stacksincorrectly converted that Pascal string into a C string without any validity checks. When this happened, the resulting C string contained only the targetdomain.tld portion. The SSL stack then compared that truncated version with the domain the user requested, and interpreted the certificate as being valid for the targeted domain. In some cases, it was even possible to construct wildcard certificatesthat were valid for every possible domain in such browsers (*.com[null].yourdomain.tld would match every .com address, for example). If you obey the following rules, you should be able to avoid most underflow attacks: ● Zero-fill all buffers before use. A buffer that contains only zeros cannot contain stale sensitive information. ● Always check return values and fail appropriately. ● If a call to an allocation or initialization function fails (AuthorizationCopyRights, for example), do not evaluate the resulting data, as it could be stale. ● Use the value returned from read system calls and other similar calls to determine how much data was actually read. Then either: ● Use that result to determine how much data is present instead of using a predefined constant or ● fail if the function did not return the expected amount of data. ● Display an error and fail if a write call, printf call, or other output call returns without writing all of the data, particularly if you might later read that data back. ● When working with data structures that contain length information, always verify that the data is the size you expected. ● Avoid converting non-C strings (CFStringRef objects, NSString objects, Pascal strings, and so on) into C strings if possible. Instead, work with the strings in their original format. If this is not possible, always perform length checks on the resulting C string or check for null bytes in the source data. Avoiding Buffer Overflows and Underflows Avoiding Buffer Underflows 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 31● Avoid mixing buffer operations and string operations. If this is not possible, always perform length checks on the resulting C string or check for null bytes in the source data. ● Save files in a fashion that prevents malicious tampering or truncation. (See “Race Conditions and Secure File Operations” (page 43) for more information.) ● Avoid integer overflows and underflows. (See “Calculating Buffer Sizes” (page 25) for details.) Avoiding Buffer Overflows and Underflows Avoiding Buffer Underflows 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 32A major, and growing, source of security vulnerabilities is the failure of programs to validate all input from outside the program—that is, data provided by users, from files, over the network, or by other processes. This chapter describes some of the ways in which unvalidated input can be exploited, and some coding techniques to practice and to avoid. Risks of Unvalidated Input Any time your program accepts input from an uncontrolled source, there is a potential for a user to pass in data that does not conform to your expectations. If you don’t validate the input, it might cause problems ranging from program crashes to allowing an attacker to execute his own code. There are a number of ways an attacker can take advantage of unvalidated input, including: ● Buffer overflows ● Format string vulnerabilities ● URL commands ● Code insertion ● Social engineering Many Apple security updates have been to fix input vulnerabilities, including a couple of vulnerabilities that hackers used to “jailbreak” iPhones. Input vulnerabilities are common and are often easily exploitable, but are also usually easily remedied. Causing a Buffer Overflow If your application takesinput from a user or other untrusted source, itshould never copy data into a fixed-length buffer without checking the length and truncating it if necessary. Otherwise, an attacker can use the input field to cause a buffer overflow. See “Avoiding Buffer Overflows And Underflows” (page 17) to learn more. 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 33 Validating Input and Interprocess CommunicationFormat String Attacks If you are taking input from a user or other untrusted source and displaying it, you need to be careful that your display routines do not processformatstringsreceived from the untrusted source. For example, in the following code the syslog standard C library function is used to write a received HTTP request to the system log. Because the syslog function processes format strings, it will process any format strings included in the input packet: /* receiving http packet */ int size = recv(fd, pktBuf, sizeof(pktBuf), 0); if (size) { syslog(LOG_INFO, "Received new HTTP request!"); syslog(LOG_INFO, pktBuf); } Many formatstrings can cause problemsfor applications. For example,suppose an attacker passesthe following string in the input packet: "AAAA%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%n" This string retrieves eight items from the stack. Assuming that the format string itself is stored on the stack, depending on the structure of the stack, this might effectively move the stack pointer back to the beginning of the format string. Then the %n token would cause the print function to take the number of bytes written so far and write that value to the memory address stored in the next parameter, which happens to be the format string. Thus, assuming a 32-bit architecture, the AAAA in the format string itself would be treated as the pointer value 0x41414141, and the value at that address would be overwritten with the number 76. Doing this will usually cause a crash the next time the system has to access that memory location, but by using a string carefully crafted for a specific device and operating system, the attacker can write arbitrary data to any location. See the manual page for printf(3) for a full description of format string syntax. To prevent format string attacks, make sure that no input data is ever passed as part of a format string. To fix this, just include your own format string in each such function call. For example, the call printf(buffer) may be subject to attack, but the call printf("%s", buffer) is not. In the second case, all characters in the buffer parameter—including percent signs (%)—are printed out rather than being interpreted as formatting tokens. Validating Input and Interprocess Communication Risks of Unvalidated Input 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 34This situation can be made more complicated when a string is accidentally formatted more than once. In the following example, the informativeTextWithFormat argument of the NSAlert method alertWithMessageText:defaultButton:alternateButton:otherButton:informativeTextWithFormat: calls the NSString method stringWithFormat:GetLocalizedString rather than simply formatting the message string itself. As a result, the string is formatted twice, and the data from the imported certificate is used as part of the format string for the NSAlert method: alert = [NSAlert alertWithMessageText:"Certificate Import Succeeded" defaultButton:"OK" alternateButton:nil otherButton:nil informativeTextWithFormat:[NSString stringWithFormat: @"The imported certificate \"%@\" has been selected in the certificate pop-up.", [selectedCert identifier]]]; [alert setAlertStyle:NSInformationalAlertStyle]; [alert runModal]; Instead, the string should be formatted only once, as follows: [alert informativeTextWithFormat:@"The imported certificate \"%@\" has been selected in the certificate pop-up.", [selectedCert identifier]]; The following commonly-used functions and methods are subject to format-string attacks: ● Standard C ● printf and other functions listed on the printf(3) manual page ● scanf and other functions listed on the scanf(3) manual page ● syslog and vsyslog ● Carbon ● CFStringCreateWithFormat ● CFStringCreateWithFormatAndArguments ● CFStringAppendFormat ● AEBuildDesc Validating Input and Interprocess Communication Risks of Unvalidated Input 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 35● AEBuildParameters ● AEBuildAppleEvent ● Cocoa ● [NSString stringWithFormat:] and other NSString methods that take formatted strings as arguments ● [NSString initWithFormat:] and other NSStringmethodsthattake formatstrings as arguments ● [NSMutableString appendFormat:] ● [NSAlert alertWithMessageText:defaultButton:alternateButton:otherButton:informativeTextWithFormat:] ● [NSPredicate predicateWithFormat:] and [NSPredicate predicateWithFormat:arguments:] ● [NSException raise:format:] and [NSException raise:format:arguments:] ● NSRunAlertPanel and other Application Kit functions that create or return panels or sheets URLs and File Handling If your application has registered a URL scheme, you have to be careful about how you process commands sent to your application through the URL string. Whether you make the commands public or not, hackers will try sending commandsto your application. If, for example, you provide a link or linksto launch your application from your web site, hackers will look to see what commands you’re sending and will try every variation on those commands they can think of. You must be prepared to handle, or to filter out, any commands that can be sent to your application, not only those commands that you would like to receive. For example, if you accept a command that causes your application to send credentials back to your web server, don’t make the function handler general enough so that an attacker can substitute the URL of their own web server. Here are some examples of the sorts of commands that you should not accept: ● myapp://cmd/run?program=/path/to/program/to/run ● myapp://cmd/set_preference?use_ssl=false ● myapp://cmd/sendfile?to=evil@attacker.com&file=some/data/file ● myapp://cmd/delete?data_to_delete=my_document_ive_been_working_on ● myapp://cmd/login_to?server_to_send_credentials=some.malicious.webserver.com In general, don’t accept commands that include arbitrary URLs or complete pathnames. Validating Input and Interprocess Communication Risks of Unvalidated Input 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 36If you accept text or other data in a URL command that you subsequently include in a function or method call, you could be subject to a format string attack (see “Format String Attacks” (page 34)) or a buffer overflow attack (see “Causing a Buffer Overflow” (page 33)). If you accept pathnames, be careful to guard againststrings that might redirect a call to another directory; for example: myapp://use_template?template=/../../../../../../../../some/other/file Code Insertion Unvalidated URL commands and textstringssometimes allow an attacker to insert code into a program, which the program then executes. For example, if your application processes HTML and Javascript when displaying text, and displays strings received through a URL command, an attacker could send a command something like this: myapp://cmd/adduser='>"> Similarly, HTML and other scripting languages can be inserted through URLs, text fields, and other data inputs, such as command lines and even graphics or audio files. You should either not execute scripts in data from an untrusted source, or you should validate all such data to make sure it conforms to your expectations for input. Never assume that the data you receive is well formed and valid; hackers and malicious users will try every sort of malformed data they can think of to see what effect it has on your program. Social Engineering Social engineering—essentially tricking the user—can be used with unvalidated input vulnerabilities to turn a minor annoyance into a major problem. For example, if your program accepts a URL command to delete a file, but first displays a dialog requesting permission from the user, you might be able to send a long-enough string to scroll the name of the file to be deleted past the end of the dialog. You could trick the user into thinking he was deleting something innocuous, such as unneeded cached data. For example: myapp://cmd/delete?file=cached data that is slowing down your system.,realfile The user then might see a dialog with the text “Are you sure you want to delete cached data that is slowing down your system.” The name of the real file, in this scenario, is out of sight below the bottom of the dialog window. When the user clicks the “OK” button, however, the user’s real data is deleted. Other examples of social engineering attacks include tricking a user into clicking on a link in a malicious web site or following a malicious URL. For more information about social engineering, read “Designing Secure User Interfaces” (page 73). Validating Input and Interprocess Communication Risks of Unvalidated Input 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 37Modifications to Archived Data Archiving data, also known as object graph serialization, refers to converting a collection of interconnected objects into an architecture-independent stream of bytes that preserves the identity of and the relationships between the objects and values. Archives are used for writing data to a file, transmitting data between processes or across a network, or performing other types of data storage or exchange. For example, in Cocoa, you can use a coder object to create and read from an archive, where a coder object is an instance of a concrete subclass of the abstract class NSCoder. Object archives are problematic from a security perspective for several reasons. First, an object archive expands into an object graph that can contain arbitrary instances of arbitrary classes. If an attacker substitutes an instance of a different class than you were expecting, you could get unexpected behavior. Second, because an application must know the type of data stored in an archive in order to unarchive it, developers typically assume that the values being decoded are the same size and data type as the values they originally coded. However, when the data is stored in an insecure manner before being unarchived, this is not a safe assumption. If the archived data is not stored securely, it is possible for an attacker to modify the data before the application unarchives it. If your initWithCoder: method does not carefully validate all the data it’s decoding to make sure it is well formed and does not exceed the memory space reserved for it, then by carefully crafting a corrupted archive, an attacker can cause a buffer overflow or trigger another vulnerability and possibly seize control of the system. Third, some objects return a different object during unarchiving (see the NSKeyedUnarchiverDelegate method unarchiver:didDecodeObject:) or when they receive the message awakeAfterUsingCoder:. NSImage is one example of such a class—it may register itself for a name when unarchived, potentially taking the place of an image the application uses. An attacker might be able to take advantage of this to insert a maliciously corrupt image file into an application. It’s worth keeping in mind that, even if you write completely safe code, there mightstill be security vulnerabilities in libraries called by your code. Specifically, the initWithCoder: methods of the superclasses of your classes are also involved in unarchiving. To be completely safe, you should avoid using archived data as a serialization format for data that could potentially be stored or transmitted in an insecure fashion or that could potentially come from an untrusted source. Note that nib files are archives, and these cautions apply equally to them. A nib file loaded from a signed application bundle should be trustable, but a nib file stored in an insecure location is not. Validating Input and Interprocess Communication Risks of Unvalidated Input 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 38See “Risks of Unvalidated Input” (page 33) for more information on the risks of reading unvalidated input, “Securing File Operations” (page 47) for techniques you can use to keep your archive files secure, and the other sections in this chapter for details on validating input. Fuzzing Fuzzing, or fuzz testing, is the technique of randomly or selectively altering otherwise valid data and passing it to a program to see what happens. If the program crashes or otherwise misbehaves, that’s an indication of a potential vulnerability that might be exploitable. Fuzzing is a favorite tool of hackers who are looking for buffer overflows and the other types of vulnerabilities discussed in this chapter. Because it will be employed by hackers against your program, you should use it first, so you can close any vulnerabilities before they do. Although you can never prove that your program is completely free of vulnerabilities, you can at least get rid of any that are easy to find this way. In this case, the developer’s job is much easier than that of the hacker. Whereas the hacker has to not only find input fields that might be vulnerable, but also must determine the exact nature of the vulnerability and then craft an attack that exploits it, you need only find the vulnerability, then look at the source code to determine how to close it. You don’t need to prove that the problem is exploitable—just assume that someone will find a way to exploit it, and fix it before they get an opportunity to try. Fuzzing is best done with scripts orshort programsthat randomly vary the input passed to a program. Depending on the type of input you’re testing—text field, URL, data file, and so forth—you can try HTML, javascript, extra long strings, normally illegal characters, and so forth. If the program crashes or does anything unexpected, you need to examine the source code that handles that input to see what the problem is, and fix it. For example, if your program asksfor a filename, you should attempt to enter a string longer than the maximum legal filename. Or, if there is a field that specifies the size of a block of data, attempt to use a data block larger than the one you indicated in the size field. The most interesting valuesto try when fuzzing are usually boundary values. For example, if a variable contains a signed integer, try passing the maximum and minimum values allowed for a signed integer of thatsize, along with 0, 1, and -1. If a data field should contain a string with no fewer than 1 byte and no more than 42 bytes, try zero bytes, 1 byte, 42 bytes, and 43 bytes. And so on. In addition to boundary values, you should also try values that are way, way outside the expected values. For example, if your application is expecting an image that is up to 2,000 pixels by 3,000 pixels, you might modify the size fields to claim that the image is 65,535 pixels by 65,535 pixels. Using large values can uncover integer overflow bugs (and in some cases, NULL pointer handling bugs when a memory allocation fails). See “Avoiding Integer Overflows And Underflows” (page 27) in “Avoiding Buffer Overflows And Underflows” (page 17) for more information about integer overflows. Validating Input and Interprocess Communication Fuzzing 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 39Inserting additional bytes of data into the middle or end of a file can also be a useful fuzzing technique in some cases. For example, if a file’s header indicates that it contains 1024 bytes after the header, the fuzzer could add a 1025th byte. The fuzzer could add an additional row or column of data in an image file. And so on. Interprocess Communication and Networking When communicating with another process, the most important thing to remember isthat you cannot generally verify that the other process has not been compromised. Thus, you must treat it as untrusted and potentially hostile. All interprocess communication is potentially vulnerable to attacks if you do not properly validate input, avoid race conditions, and perform any other tests that are appropriate when working with data from a potentially hostile source. Above and beyond these risks, however,some forms of interprocess communication have specific risksinherent to the communication mechanism. This section describes some of those risks. Mach messaging When working with Mach messaging, it is important to never give the Mach task port of your process to any other. If you do, you are effectively allowing that process to arbitrarily modify the address space your process, which makes it trivial to compromise your process. Instead, you should create a Mach port specifically for communicating with a given client. Note: Mach messaging in OS X is not a supported API. No backwards compatibility guarantees are made for applications that use it anyway. Remote procedure calls (RPC) and Distributed Objects: If your application uses remote procedure calls or Distributed Objects, you are implicitly saying that you fully trust whatever processis at the other end of the connection. That process can call arbitrary functions within your code, and may even be able to arbitrarily overwrite portions of your code with malicious code. For thisreason, you should avoid using remote procedure calls or DistributedObjects when communicating with potentially untrusted processes, and in particular, you should never use these communication technologies across a network boundary. Shared Memory: If you intend to share memory across applications, be careful to allocate any memory on the heap in page-aligned, page-sized blocks. If you share a block of memory that is not a whole page (or worse, if you share some portion of your application’s stack), you may be providing the process at the other end Validating Input and Interprocess Communication Interprocess Communication and Networking 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 40with the ability to overwrite portions of your code,stack, or other data in waysthat can produce incorrect behavior, and may even allow injection of arbitrary code. In addition to these risks, some forms of shared memory can also be subject to race condition attacks. Specifically, memory mapped files can be replaced with other files between when you create the file and when you open it. See “Securing File Operations” (page 47) for more details. Finally, named shared memory regions and memory mapped files can be accessed by any other process running as the user. For this reason, it is not safe to use non-anonymous shared memory for sending highly secret information between processes. Instead, allocate your shared memory region prior to creating the child processthat needsto share that region, then pass IPC_PRIVATE asthe key for shmget to ensure that the shared memory identifier is not easy to guess. Note: Shared memory regions are detached if you call exec or other similar functions. If you need to pass data in a secure way across an exec boundary, you must pass the shared memory ID to the child process. Ideally, you should do this using a secure mechanism, such as a pipe created using a call to pipe. After the last child process that needs to use a particular shared memory region is running, the process that created the region should call shmctl to remove the shared memory region. Doing so ensures that no further processes can attach to that region even if they manage to guess the region ID. shmctl(id, IPC_RMID, NULL); Signals: A signal, in this context, is a particular type of content-free message sent from one process to another in a UNIX-based operating system such as OS X. Any program can register a signal handler function to perform specific operations upon receiving a signal. In general, it is not safe to do a significant amount of work in a signal handler. There are only a handful of library functions and system callsthat are safe to use in a signal handler (referred to as async-signal-safe calls), and this makes it somewhat difficult to safely perform work inside a call. More importantly, however, as a programmer, you are not in control of when your application receives a signal. Thus, if an attacker can cause a signal to be delivered to your process (by overflowing a socket buffer, for example), the attacker can cause your signal handler code to execute at any time, between any two lines of code in your application. This can be problematic if there are certain places where executing that code would be dangerous. For example, in 2004, a signal handler race condition was found in open-source code present in many UNIX-based operating systems. This bug made it possible for a remote attacker to execute arbitrary code Validating Input and Interprocess Communication Interprocess Communication and Networking 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 41or to stop the FTP daemon from working by causing it to read data from a socket and execute commands while it was still running as the root user. [CVE-2004-0794] For this reason, signal handlers should do the minimum amount of work possible, and should perform the bulk of the work at a known location within the application’s main program loop. For example, in an application based on Foundation or Core Foundation, you can create a pair of connected sockets by calling socketpair, call setsockopt to set the socket to non-blocking, turn one end into a CFStream object by calling CFStreamCreatePairWithSocket, and then schedule that stream on your run loop. Then, you can install a minimal signal handler that uses the write system call (which is async-signal-safe according to POSIX.1) to write data into the other socket. When the signal handler returns, your run loop will be woken up by data on the other socket, and you can then handle the signal at your convenience. Important: If you are writing to a socket in a signal handler and reading from it in a run loop on your main program thread, you must set the socket to non-blocking. If you do not, it is possible to cause your application to hang by sending it too many signals. The queue for a socket is of finite size. When it fills up, if the socket is set to non-blocking, the write call fails, and the global variable errno is set to EAGAIN. If the socket is blocking, however, the write call blocks until the queue empties enough to write the data. If a write call in a signal handler blocks, this prevents the signal handler from returning execution to the run loop. If that run loop is responsible for reading data from the socket, the queue will never empty, the write call will never unblock, and your application will basically hang (at least until the write call isinterrupted by anothersignal). Validating Input and Interprocess Communication Interprocess Communication and Networking 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 42When working with shared data, whether in the form of files, databases, network connections,shared memory, or other forms of interprocess communication, there are a number of easily made mistakesthat can compromise security. This chapter describes many such pitfalls and how to avoid them. Avoiding Race Conditions A race condition exists when changes to the order of two or more events can cause a change in behavior. If the correct order of execution is required for the proper functioning of the program, this is a bug. If an attacker can take advantage of the situation to insert malicious code, change a filename, or otherwise interfere with the normal operation of the program, the race condition is a security vulnerability. Attackers can sometimes take advantage of small time gaps in the processing of code to interfere with the sequence of operations, which they then exploit. OS X, like all modern operating systems, is a multitasking OS; that is, it allows multiple processes to run or appear to run simultaneously by rapidly switching among them on each processor. The advantagesto the user are many and mostly obvious; the disadvantage, however, is that there is no guarantee that two consecutive operations in a given process are performed without any other process performing operations between them. In fact, when two processes are using the same resource (such as the same file), there is no guarantee that they will access that resource in any particular order unless both processes explicitly take steps to ensure it. For example, if you open a file and then read from it, even though your application did nothing else between these two operations, some other process might alter the file after the file was opened and before it was read. If two different processes (in the same or different applications) were writing to the same file, there would be no way to know which one would write first and which would overwrite the data written by the other. Such situations cause security vulnerabilities. There are two basic types of race condition that can be exploited: time of check–time of use (TOCTOU), and signal handling. 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 43 Race Conditions and Secure File OperationsTime of Check Versus Time of Use It is fairly common for an application to need to check some condition before undertaking an action. For example, it might check to see if a file exists before writing to it, or whether the user has access rights to read a file before opening it for reading. Because there is a time gap between the check and the use (even though it might be a fraction of a second), an attacker can sometimes use that gap to mount an attack. Thus, this is referred to as a time-of-check–time-of-use problem. Temporary Files A classic example isthe case where an application writestemporary filesto publicly accessible directories. You can set the file permissions of the temporary file to prevent another user from altering the file. However, if the file already exists before you write to it, you could be overwriting data needed by another program, or you could be using a file prepared by an attacker, in which case it might be a hard link or symbolic link, redirecting your output to a file needed by the system or to a file controlled by the attacker. To prevent this, programs often check to make sure a temporary file with a specific name does not already exist in the target directory. If such a file exists, the application deletes it or chooses a new name for the temporary file to avoid conflict. If the file does not exist, the application opensthe file for writing, because the system routine that opens a file for writing automatically creates a new file if none exists. An attacker, by continuously running a program that creates a new temporary file with the appropriate name, can (with a little persistence and some luck) create the file in the gap between when the application checked to make sure the temporary file didn’t exist and when it opens it for writing. The application then opensthe attacker’sfile and writesto it (remember, the system routine opens an existing file if there is one, and creates a new file only if there is no existing file). The attacker’s file might have different access permissions than the application’s temporary file, so the attacker can then read the contents. Alternatively, the attacker might have the file already open. The attacker could replace the file with a hard link or symbolic link to some other file (either one owned by the attacker or an existing system file). For example, the attacker could replace the file with a symbolic link to the system password file, so that after the attack, the system passwords have been corrupted to the point that no one, including the system administrator, can log in. For a real-world example, in a vulnerability in a directory server, a server script wrote private and public keys into temporary files, then read those keys and put them into a database. Because the temporary files were in a publicly writable directory, an attacker could have created a race condition by substituting the attacker’s own files (or hard links or symbolic links to the attacker’s files) before the keys were reread, thus causing the script to insert the attacker’s private and public keys instead. After that, anything Race Conditions and Secure File Operations Avoiding Race Conditions 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 44encrypted or authenticated using those keys would be under the attacker’s control. Alternatively, the attacker could have read the private keys, which can be used to decrypt encrypted data. [CVE-2005-2519] Similarly, if an application temporarily relaxes permissions on files or folders in order to perform some operation, an attacker might be able to create a race condition by carefully timing his or her attack to occur in the narrow window in which those permissions are relaxed. To learn more about creating temporary files securely, read “Create Temporary Files Correctly” (page 50). Interprocess Communication Time-of-check–time-of-use problems do not have to involve files, of course. They can apply to any data storage or communications mechanism that does not perform operations atomically. Suppose, for example, that you wrote a program designed to automatically count the number of people entering a sports stadium for a game. Each turnstile talks to a web service running on a server whenever someone walks through. Each web service instance inherently runs as a separate process. Each time a turnstile sends a signal, an instance of the web service starts up, retrievesthe gate count from a database, increments it by one, and writes it back to the database. Thus, multiple processes are keeping a single running total. Now suppose two people enter different gates at exactly the same time. The sequence of events might then be as follows: 1. Server process A receives a request from gate A. 2. Server process B receives a request from gate B. 3. Server process A reads the number 1000 from the database. 4. Server process B reads the number 1000 from the database. 5. Server process A increments the gate count by 1 so that Gate == 1001. 6. Server process B increments the gate count by 1 so that Gate == 1001. 7. Server process A writes 1001 as the new gate count. 8. Server process B writes 1001 as the new gate count. Because server process B read the gate count before process A had time to increment it and write it back, both processesread the same value. After process A incrementsthe gate count and writesit back, process B overwrites the value of the gate count with the same value written by process A. Because of this race condition, one of the two people entering the stadium was not counted. Since there might be long lines at each turnstile, this condition might occur many times before a big game, and a dishonest ticket clerk who knew about this undercount could pocket some of the receipts with no fear of being caught. Other race conditions that can be exploited, like the example above, involve the use of shared data or other interprocess communication methods. If an attacker can interfere with important data after it is written and before it isre-read, he orshe can disrupt the operation of the program, alter data, or do other Race Conditions and Secure File Operations Avoiding Race Conditions 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 45mischief. The use of non-thread-safe calls in multithreaded programs can result in data corruption. If an attacker can manipulate the program to cause two such threads to interfere with each other, it may be possible to mount a denial-of-service attack. In some cases, by using such a race condition to overwrite a buffer in the heap with more data than the buffer can hold, an attacker can cause a buffer overflow. As discussed in “Avoiding Buffer Overflows And Underflows” (page 17), buffer overflows can be exploited to cause execution of malicious code. The solution to race conditions involving shared data is to use a locking mechanism to prevent one process from changing a variable until another is finished with it. There are problems and hazards associated with such mechanisms, however, and they must be implemented carefully. And, of course, locking mechanisms only apply to processes that participate in the locking scheme. They cannot prevent an untrusted application from modifying the data maliciously. For a full discussion, see Wheeler, Secure Programming for Linux and Unix HOWTO, at http://www.dwheeler.com/secure-programs/. Time-of-check–time-of-use vulnerabilities can be prevented in different ways, depending largely on the domain of the problem. When working with shared data, you should use locking to protect that data from other instances of your code. When working with data in publicly writable directories, you should also take the precautions described in “Files In Publicly Writable Directories Are Dangerous” (page 51). Signal Handling Because signal handlers execute code at arbitrary times, they can be used to cause incorrect behavior. In daemons running as root, running the wrong code at the wrong time can even cause privilege escalation. “Securing Signal Handlers” (page 46) describes this problem in more detail. Securing Signal Handlers Signal handlers are another common source of race conditions. Signalsfrom the operating system to a process or between two processes are used for such purposes as terminating a process or causing it to reinitialize. If you include signal handlers in your program, they should not make any system calls and should terminate as quickly as possible. Although there are certain system calls that are safe from within signal handlers, writing a safe signal handler that does so is tricky. The best thing to do is to set a flag that your program checks periodically, and do no other work within the signal handler. Thisis because the signal handler can be interrupted by a new signal before it finishes processing the first signal, leaving the system in an unpredictable state or, worse, providing a vulnerability for an attacker to exploit. Race Conditions and Secure File Operations Securing Signal Handlers 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 46For example, in 1997, a vulnerability wasreported in a number of implementations of the FTP protocol in which a user could cause a race condition by closing an FTP connection. Closing the connection resulted in the near-simultaneous transmission of two signals to the FTP server: one to abort the current operation, and one to log out the user. The race condition occurred when the logout signal arrived just before the abort signal. When a user logged onto an FTP server as an anonymous user, the server would temporarily downgrade its privilegesfrom root to nobody so that the logged-in user had no privilegesto write files. When the user logged out, however, the server reassumed root privileges. If the abort signal arrived at just the right time, it would abort the logout procedure after the server had assumed root privileges but before it had logged out the user. The user would then be logged in with root privileges, and could proceed to write files at will. An attacker could exploit this vulnerability with a graphical FTP client simply by repeatedly clicking the “Cancel” button. [CVE-1999-0035] For a brief introduction to signal handlers, see the Little Unix Programmers Group site at http://users.actcom.co.il/~choo/lupg/tutorials/signals/signals-programming.html. For a discourse on how signal handler race conditions can be exploited,see the article by Michal Zalewski at http://www.bindview.com/Services/razor/Papers/2001/signals.cfm. Securing File Operations Insecure file operations are a major source of security vulnerabilities. In some cases, opening or writing to a file in an insecure fashion can give attackers the opportunity to create a race condition (see “Time of Check Versus Time of Use” (page 44)). Often, however, insecure file operations give an attacker the ability to read confidential information, perform a denial of service attack, take control of an application, or even take control of the entire system. This section discusses what you should do to make your file operations more secure. Check Result Codes Always check the result codes of every routine that you call. Be prepared to handle the situation if the operation fails. Most file-based security vulnerabilities could have been avoided if the developers of the programs had checked result codes. Some common mistakes are listed below. When writing to files or changing file permissions A failure when change permissions on a file or to open a file for writing can be caused by many things, including: ● Insufficient permissions on the file or enclosing directory. Race Conditions and Secure File Operations Securing File Operations 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 47● The immutable flag (set with the chflags utility or the chflags system call). ● A network volume becoming unavailable. ● An external drive getting unplugged. ● A drive failure. Depending on the nature of your software, any one of these could potentially be exploited if you do not properly check error codes. See the manual pages for the chflags, chown, and chgrp commands and the chflags and chown functions for more information. When removing files Although the rm command can often ignore permissions if you pass the -f flag, it can still fail. For example, you can’t remove a directory that has anything inside it. If a directory is in a location where other users have access to it, any attempt to remove the directory might fail because another process might add new files while you are removing the old ones. The safest way to fix this problem is to use a private directory that no one else has access to. If that’s not possible, check to make sure the rm command succeeded and be prepared to handle failures. Watch Out for Hard Links A hard link is a second name for a file—the file appears to be in two different locations with two different names. If a file has two (or more) hard links and you check the file to make sure that the ownership, permissions, and so forth are all correct, but fail to check the number of links to the file, an attacker can write to or read from the file through their own link in their own directory. Therefore, among other checks before you use a file, you should check the number of links. Do not, however, simply fail if there’s a second link to a file, because there are some circumstances where a link is okay or even expected. For example, every directory islinked into at least two placesin the hierarchy—the directory name itself and the special . record from the directory that links back to itself. Also, if that directory contains other directories, each of those subdirectories contains a .. record that points to the outer directory. You need to anticipate such conditions and allow for them. Even if the link is unexpected, you need to handle the situation gracefully. Otherwise, an attacker can cause denial of service just by creating a link to the file. Instead, you should notify the user of the situation, giving them as much information as possible so they can try to track down the source of the problem. Race Conditions and Secure File Operations Securing File Operations 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 48Watch Out for Symbolic Links A symbolic link is a special type of file that contains a path name. Symbolic links are more common than hard links. Functions that follow symbolic links automatically open, read, or write to the file whose path name is in the symbolic link file rather than the symbolic link file itself. Your application receives no notification that a symbolic link was followed; to your application, it appears as if the file addressed is the one that was used. An attacker can use a symbolic link, for example, to cause your application to write the contents intended for a temporary file to a critical system file instead, thus corrupting the system. Alternatively, the attacker can capture data you are writing or can substitute the attacker’s data for your own when you read the temporary file. In general, you should avoid functions,such as chown and stat, that follow symbolic links(see Table 4-1 (page 55) for alternatives). As with hard links, your program should evaluate whether a symbolic link is acceptable, and if not, should handle the situation gracefully. Case-Insensitive File Systems Can Thwart Your Security Model In OS X, any partition (including the boot volume) can be either case-sensitive, case-insensitive but case-preserving, or, for non-boot volumes, case-insensitive. For example, HFS+ can be either case-sensitive or case-insensitive but case-preserving. FAT32 is case-insensitive but case-preserving. FAT12, FAT16, and ISO-9660 (without extensions) are case-insensitive. An application that is unaware of the differences in behavior between these volume formats can cause serious security holes if you are not careful. In particular: ● If your program uses its own permission model to provide or deny access (for example, a web server that allows access only to files within a particular directory), you must either enforce this with a chroot jail or be vigilant about ensuring that you correctly identify paths even in a case-insensitive world. Among other things, this meansthat you should ideally use a whitelisting scheme rather than a blacklisting scheme (with the default behavior being “deny”). If this is not possible, for correctness, you must compare each individual path part against your blacklist using case-sensitive or case-insensitive comparisons, depending on what type of volume the file resides on. For example, if your program has a blacklist that prevents users from uploading or downloading the file /etc/ssh_host_key, if your software is installed on a case-insensitive volume, you must also reject someone who makes a request for /etc/SSH_host_key, /ETC/SSH_HOST_KEY, or even /ETC/ssh_host_key. ● If your program periodically accesses a file on a case-sensitive volume using the wrong mix of uppercase and lowercase letters, the open call will fail... until someone creates a second file with the name your program is actually asking for. Race Conditions and Secure File Operations Securing File Operations 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 49If someone creates such a file, your application will dutifully load data from the wrong file. If the contents of that file affect your application’s behavior in some important way, this represents a potential attack vector. This also presents a potential attack vector if that file is an optional part of your application bundle that gets loaded by dyld when your application is launched. Create Temporary Files Correctly The temporary directories in OS X are shared among multiple users. This requires that they be writable by multiple users. Any time you work on files in a location to which others have read/write access, there’s the potential for the file to be compromised or corrupted. The following list explains how to create temporary files using APIs at various layers of OS X. POSIX Layer In general, you should always use the mkstemp function to create temporary files at the POSIX layer. The mkstemp function guarantees a unique filename and returns a file descriptor, thus allowing you skip the step of checking the open function result for an error, which might require you to change the filename and call open again. If you must create a temporary file in a public directory manually, you can use the open function with the O_CREAT and O_EXCL flags set to create the file and obtain a file descriptor. The O_EXCL flag causes this function to return an error if the file already exists. Be sure to check for errors before proceeding. After you’ve opened the file and obtained a file descriptor, you can safely use functions that take file descriptors, such as the standard C functions write and read, for as long as you keep the file open. See the manual pages for open(2), mkstemp(3), write(2), and read(2) for more on these functions, and see Wheeler, Secure Programming for Linux and Unix HOWTO for advantages and shortcomings to using these functions. Carbon To find the default location to store temporary files, you can call the FSFindFolder function and specify a directory type of kTemporaryFolderType. This function checks to see whether the UID calling the function owns the directory and, if not, returns the user home directory in ~/Library. Therefore, this function returns a relatively safe place to store temporary files. Thislocation is not assecure as a directory that you created and that is accessible only by your program. The FSFindFolder function is documented in Folder Manager Reference . If you’ve obtained the file reference of a directory (from the FSFindFolder function, for example), you can use the FSRefMakePath function to obtain the directory’s path name. However, be sure to check the function result, because if the FSFindFolder function fails, it returns a null string. If you don’t Race Conditions and Secure File Operations Securing File Operations 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 50check the function result, you might end up trying to create a temporary file with a pathname formed by appending a filename to a null string. Cocoa There are no Cocoa methods that create a file and return a file descriptor. However, you can call the standard C open function from an Objective-C program to obtain a file descriptor (see “Working With Publicly Writable Files Using POSIX Calls” (page 54)). Or you can call the mkstemp function to create a temporary file and obtain a file descriptor. Then you can use the NSFileHandle method initWithFileDescriptor: to initialize a file handle, and other NSFileHandle methods to safely write to or read from the file. Documentation for the NSFileHandle class is in Foundation Framework Reference . To obtain the path to the default location to store temporary files (stored in the $TMPDIR environment variable), you can use the NSTemporaryDirectory function, which calls the FSFindFolder and FSRefMakePath functions for you (see “Working With Publicly Writable Files Using Carbon” (page 55)). Note that NSTemporaryDirectory can return /tmp under certain circumstances such as if you link on a pre-OS X v10.3 development target. Therefore, if you’re using NSTemporaryDirectory, you either have to be sure that using /tmp is suitable for your operation or, if not, you should consider that an error case and create a more secure temporary directory if that happens. The changeFileAttributes:atPath: method in the NSFileManager class is similar to chmod or chown, in that it takes a file path rather than a file descriptor. You shouldn’t use this method if you’re working in a public directory or a user’s home directory. Instead, call the fchown or fchmod function (see Table 4-1 (page 55)). You can call the NSFileHandle class’s fileDescriptor method to get the file descriptor of a file in use by NSFileHandle. In addition, when working with temporary files, you should avoid the writeToFile:atomically methods of NSString and NSData. These are designed to minimize the risk of data loss when writing to a file, but do so in a way that is not recommended for use in directories that are writable by others. See “Working With Publicly Writable Files Using Cocoa” (page 56) for details. Files in Publicly Writable Directories Are Dangerous Files in publicly writable directories must be treated as inherently untrusted. An attacker can delete the file and replace it with another file, replace it with a symbolic link to another file, create the file ahead of time, and so on. There are ways to mitigate each of these attacks to some degree, but the best way to prevent them is to not read or write files in a publicly writable directory in the first pace. If possible, you should create a subdirectory with tightly controlled permissions, then write your files inside that subdirectory. If you must work in a directory to which your process does not have exclusive access, however, you must check to make sure a file does not exist before you create it. You must also verify that the file you intend to read from or write to is the same file that you created. Race Conditions and Secure File Operations Securing File Operations 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 51To this end, you should always use routines that operate on file descriptors rather than pathnames wherever possible, so that you can be certain you’re always dealing with the same file. To do this, pass the O_CREAT and O_EXCL flags to the open system call. This creates a file, but fails if the file already exists. Note: If you cannot use file descriptors directly for some reason, you should explicitly create files as a separate step from opening them. Although this does not prevent someone from swapping in a new file between those operations, at least it narrows the attack window by making it possible to detect if the file already exists. Before you create the file, however, you should first set your process’s file creation mask (umask). The file creation mask is a bitmask that alters the default permissions of all new files and directories created by your process. This bitmask is typically specified in octal notation, which means that it must begin with a zero (not 0x). For example, if you set the file creation mask to 022, any new files created by your process will have rw-r--r-- permissions because the write permission bits are masked out. Similarly, any new directories will have rw-r-xr-x permissions. Note: New files never have the execute bit set. Directories, however, do. Therefore, you should generally mask out execute permission when masking out read permission unless you have a specific reason to allow users to traverse a directory without seeing its contents. To limit access to any new files or directories so that only the user can access them, set the file creation mask to 077. You can also mask out permissions in such a way that they apply to the user, though this is rare. For example, to create a file that no one can write or execute, and that only the user can read, you could set the file creation mask to 0377. This is not particularly useful, but it is possible. There are several ways to set the file creation mask: In C code: In C code, you can set the file creation mask globally using the umask system call. You can also passthe file creation mask to the open or mkdir system call when creating a file or directory. Race Conditions and Secure File Operations Securing File Operations 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 52Note: For maximum portability when writing C code, you should always create your masks using the file mode constants defined in . For example: umask(S_IRWXG|S_IRWXO); In shell scripts: In shell scripts, you set the file creation mask by using the umask shell builtin. This is documented in the manual pages for sh or csh. For example: umask 0077; As an added security bonus, when a process calls another process, the new processinheritsthe parent process’s file creation mask. Thus, if your process starts another process that creates a file without resetting the file creation mask, that file similarly will not be accessible to other users on the system. This is particularly useful when writing shell scripts. For more information on the file creation mask,see the manual page for umask and Viega and McGraw, Building Secure Software , Addison Wesley, 2002. For a particularly lucid explanation of the use of a file creation mask, see http://web.archive.org/web/20090517063338/http://www.sun.com/bigadmin/content/submitted/umask_permissions.html?. Before you read a file (but after opening it), make sure it has the owner and permissions you expect (using fstat). Be prepared to fail gracefully (rather than hanging) if it does not. Here are some guidelines to help you avoid time-of-check–time-of-use vulnerabilities when working with files in publicly writable directories. For more detailed discussions, especially for C code, see Viega and McGraw, Building Secure Software , Addison Wesley, 2002, and Wheeler, Secure Programming for Linux and Unix HOWTO, available at http://www.dwheeler.com/secure-programs/. ● If at all possible, avoid creating temporary files in a shared directory, such as /tmp, or in directories owned by the user. If anyone else has access to your temporary file, they can modify its content, change its ownership or mode, or replace it with a hard or symbolic link. It’s much safer to either not use a temporary file at all (use some other form of interprocess communication) or keep temporary files in a directory you create and to which only your process (acting as your user) has access. ● If your file must be in a shared directory, give it a unique (and randomly generated) filename (you can use the C function mkstemp to do this), and never close and reopen the file. If you close such a file, an attacker can potentially find it and replace it before you reopen it. Race Conditions and Secure File Operations Securing File Operations 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 53Here are some public directories that you can use: ● ~/Library/Caches/TemporaryItems When you use this subdirectory, you are writing to the user’s own home directory, not some other user’s directory or a system directory. If the user’s home directory has the default permissions, it can be written to only by that user and root. Therefore, this directory is not as susceptible to attack from outside, nonprivileged users as some other directories might be. ● /var/run This directory is used for process ID (pid) files and other system files needed just once per startup session. This directory is cleared out each time the system starts up. ● /var/db This directory is used for databases accessible to system processes. ● /tmp This directory is used for general shared temporary storage. It is cleared out each time the system starts up. ● /var/tmp This directory is used for general shared temporary storage. Although you should not count on data stored in this directory being permanent, unlike /tmp, the /var/tmp directory is currently not cleared out on reboot. For maximum security, you should always create temporary subdirectories within these directories, set appropriate permissions on those subdirectories, and then write files into those subdirectories. The following sections give some additional hints on how to follow these principles when you are using POSIX-layer C code, Carbon, and Cocoa calls. Working with Publicly Writable Files Using POSIX Calls If you need to open a preexisting file to modify it or read from it, you should check the file’s ownership, type, and permissions, and the number of links to the file before using it. To safely opening a file for reading, for example, you can use the following procedure: 1. Call the open function and save the file descriptor. Pass the O_NOFOLLOW to ensure that it does not follow symbolic links. 2. Using the file descriptor, call the fstat function to obtain the stat structure for the file you just opened. 3. Check the user ID (UID) and group ID (GID) of the file to make sure they are correct. Race Conditions and Secure File Operations Securing File Operations 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 544. Check the file's mode flags to make sure that it is a normal file, not a FIFO, device file, or other special file. Specifically, if the stat structure is named st, then the value of (st.st_mode & S_IFMT) should be equal to S_IFREG. 5. Check the read, write, and execute permissions for the file to make sure they are what you expect. 6. Check that there is only one hard link to the file. 7. Pass around the open file descriptor for later use rather than passing the path. Note that you can avoid all the status checking by using a secure directory instead of a public one to hold your program’s files. Table 4-1 shows some functions to avoid—and the safer equivalent functions to use—in order to avoid race conditions when you are creating files in a public directory. Table 4-1 C file functions to avoid and to use Functions to avoid Functions to use instead open returns a file descriptor; creates a file and returns an error if the file already exists when the O_CREAT and O_EXCL options are used fopen returns a file pointer; automatically creates the file if it does not exist but returns no error if the file does exist chmod takes a file path fchmod takes a file descriptor fchown takes a file descriptor and does not follow symbolic links chown takes a file path and follows symbolic links lstat takes a file path but does not follow symbolic links; fstat takes a file descriptor and returns information about an open file stat takes a file path and follows symbolic links mkstemp creates a temporary file with a unique name, opens it for reading and writing, and returns a file descriptor mktemp creates a temporary file with a unique name and returns a file path; you need to open the file in another call Working with Publicly Writable Files Using Carbon If you are using the Carbon File Manager to create and open files, you should be aware of how the File Manager accesses files. ● The file specifier FSSpec structure uses a path to locate files, not a file descriptor. Functions that use an FSSpec file specifier are deprecated and should not be used in any case. Race Conditions and Secure File Operations Securing File Operations 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 55● The file reference FSRef structure uses a path to locate files and should be used only if your files are in a safe directory, not in a publicly accessible directory. These functions include FSGetCatalogInfo, FSSetCatalogInfo, FSCreateFork, and others. ● The File Manager creates and opensfilesin separate operations. The create operation failsif the file already exists. However, none of the file-creation functions return a file descriptor. If you’ve obtained the file reference of a directory (from the FSFindFolder function, for example), you can use the FSRefMakePath function to obtain the directory’s path name. However, be sure to check the function result, because if the FSFindFolder function fails, it returns a null string. If you don’t check the function result, you might end up trying to create a temporary file with a pathname formed by appending a filename to a null string. Working with Publicly Writable Files Using Cocoa The NSString and NSData classes have writeToFile:atomically methods designed to minimize the risk of data loss when writing to a file. These methods write first to a temporary file, and then, when they’re sure the write is successful, they replace the written-to file with the temporary file. This is not always an appropriate thing to do when working in a public directory or a user’s home directory, because there are a number of path-based file operationsinvolved. Instead, initialize an NSFileHandle object with an existing file descriptor and use NSFileHandle methods to write to the file, as mentioned above. The following code, for example, usesthe mkstemp function to create a temporary file and obtain a file descriptor, which it then usesto initialize NSFileHandle: fd = mkstemp(tmpfile); // check return for -1, which indicates an error NSFileHandle *myhandle = [[NSFileHandle alloc] initWithFileDescriptor:fd]; Working with Publicly Writable Files in Shell Scripts Scripts must follow the same general rules as other programs to avoid race conditions. There are a few tips you should know to help make your scripts more secure. First, when writing a script, set the temporary directory ($TMPDIR) environment variable to a safe directory. Even if your script doesn’t directly create any temporary files, one or more of the routines you call might create one, which can be a security vulnerability if it’s created in an insecure directory. See the manual pages for setenv and setenv for information on changing the temporary directory environment variable. For the same reason, set your process’ file code creation mask (umask) to restrict access to any files that might be created by routines run by your script (see “Securing File Operations” (page 47) for more information on the umask). Race Conditions and Secure File Operations Securing File Operations 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 56It’s also a good idea to use the dtruss command on a shell script so you can watch every file access to make sure that no temporary files are created in an insecure location. See the manual pages for dtrace and dtruss for more information. Do not redirect output using the operators > or >> to a publicly writable location. These operators do not check to see whether the file already exists, and they follow symbolic links. Instead, pass the -d flag to the mktemp command to create a subdirectory to which only you have access. It’s important to check the result to make sure the command succeeded. if you do all your file operations in this directory, you can be fairly confident that no one with less than root access can interfere with your script. For more information, see the manual page for mktemp. Do not use the test command (or its left bracket ([) equivalent) to check for the existence of a file or other statusinformation for the file before writing to it. Doing so alwaysresultsin a race condition; that is, it is possible for an attacker to create, write to, alter, or replace the file before you start writing. See the manual page for test for more information. For a more in-depth look at security issues specific to shell scripts, read “Shell Script Security” in Shell Scripting Primer. Other Tips Here are a few additional things to be aware of when working with files: ● Before you attempt a file operation, make sure it is safe to perform the operation on that file. For example, before attempting to read a file (but after opening it), you should make sure that it is not a FIFO or a device special file. ● Just because you can write to a file, that doesn’t mean you should write to it. For example, the fact that a directory exists doesn’t mean you created it, and the fact that you can append to a file doesn’t mean you own the file or no one else can write to it. ● OS X can perform file operations on files in several different file systems. Some operations can be done only on certain systems. For example, certain file systems honor setuid files when executed from them and some don’t. Be sure you know what file system you’re working with and what operations can be carried out on that system. ● Local pathnames can point to remote files. For example, the path /volumes/foo might actually be someone’s FTP server rather than a locally-mounted volume. Just because you’re accessing something by a pathname, that does not guarantee that it’s local or that it should be accessed. ● A user can mount a file system anywhere they have write access and own the directory. In other words, almost anywhere a user can create a directory, they can mount a file system on top of it. Because this can be done remotely, an attacker running as root on a remote system could mount a file system into your home directory. Files in that file system would appear to be files in your home directory owned by root. Race Conditions and Secure File Operations Securing File Operations 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 57For example, /tmp/foo might be a local directory, or it might be the root mount point of a remotely mounted file system. Similarly, /tmp/foo/bar might be a local file, or it might have been created on another machine and be owned by root over there. Therefore, you can’t trust files based only on ownership, and you can’t assume that setting the UID to 0 was done by someone you trust. To tell whether the file is mounted locally, use the fstat call to check the device ID. If the device ID is different from that of files you know to be local, then you’ve crossed a device boundary. ● Remember that users can read the contents of executable binariesjust as easily asthe contents of ordinary files. For example, the user can run strings(1) to quickly see a list of (ostensibly) human-readable strings in your executable. ● When you fork a new process, the child process inherits all the file descriptors from the parent unless you set the close-on-exec flag. If you fork and execute a child process and drop the child process’ privileges so its real and effective IDs are those of some other user (to avoid running that process with elevated privileges), then that user can use a debugger to attach the child process. They can then run arbitrary code from that running process. Because the child process inherited all the file descriptors from the parent, the user now has access to every file opened by the parent process. See “Inheriting File Descriptors” (page 61) for more information on this type of vulnerability. Race Conditions and Secure File Operations Securing File Operations 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 58By default, applications run as the currently logged in user. Different users have different rights when it comes to accessing files, changing systemwide settings, and so on, depending on whether they are admin users or ordinary users. Some tasks require additional privileges above and beyond what even an admin user can do by default. An application or other process with such additional rights is said to be running with elevated privileges. Running code with root or administrative privileges can intensify the dangers posed by security vulnerabilities. This chapter explains the risks, provides alternatives to privilege elevation, and describes how to elevating privileges safely when you can’t avoid it. Note: Elevating privileges is not allowed in applications submitted to the Mac App Store (and is not possible in iOS). Circumstances Requiring Elevated Privileges Regardless of whether a user is logged in as an administrator, a program might have to obtain administrative or root privileges in order to accomplish a task. Examples of tasks that require elevated privileges include: ● manipulating file permissions, ownership ● creating, reading, updating, or deleting system and user files ● opening privileged ports (those with port numbers less than 1024) for TCP and UDP connections ● opening raw sockets ● managing processes ● reading the contents of virtual memory ● changing system settings ● loading kernel extensions If you have to perform a task that requires elevated privileges, you must be aware of the fact that running with elevated privileges means that if there are any security vulnerabilities in your program, an attacker can obtain elevated privileges as well, and would then be able to perform any of the operations listed above. 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 59 Elevating Privileges SafelyThe Hostile Environment and the Principle of Least Privilege Any program can come under attack, and probably will. By default, every process runs with the privileges of the user or process that started it. Therefore, if a user has logged on with restricted privileges, your program should run with those restricted privileges. This effectively limits the amount of damage an attacker can do, even if he successfully hijacks your program into running malicious code. Do not assume that the user islogged in with administrator privileges; you should be prepared to run a helper application with elevated privileges if you need them to accomplish a task. However, keep in mind that, if you elevate your process’s privileges to run asroot, an attacker can gain those elevated privileges and potentially take over control of the whole system. Note: Although in certain circumstances it’s possible to mount a remote attack over a network, for the most part the vulnerabilities discussed here involve malicious code running locally on the target computer. If an attacker uses a buffer overflow or othersecurity vulnerability (see “Types of Security Vulnerabilities” (page 11)) to execute code on someone else’s computer, they can generally run their code with whatever privileges the logged-in user has. If an attacker can gain administrator privileges, they can elevate to root privileges and gain accessto any data on the user’s computer. Therefore, it is good security practice to log in as an administrator only when performing the rare tasks that require admin privileges. Because the default setting for OS X is to make the computer’s owner an administrator, you should encourage your usersto create a separate non-admin login and to use that for their everyday work. In addition, if possible, you should not require admin privileges to install your software. The idea of limiting risk by limiting access goes back to the “need to know” policy followed by government security agencies (no matter what your security clearance, you are not given access to information unless you have a specific need to know that information). In software security, this policy is often termed “the principle of least privilege,” first formally stated in 1975: “Every program and every user of the system should operate using the leastset of privileges necessary to complete the job.”(Saltzer,J.H. AND Schroeder, M.D.,“The Protection of Information in Computer Systems,” Proceedings of the IEEE , vol. 63, no. 9, Sept 1975.) In practical terms, the principle of least privilege means you should avoid running asroot, or—if you absolutely must run asroot to perform some task—you should run a separate helper application to perform the privileged task (see “Factoring Applications” (page 69)). By running with the least privilege possible, you: ● Limit damage from accidents and errors, including maliciously introduced accidents and errors ● Reduce interactions of privileged components, and therefore reduce unintentional, unwanted, and improper uses of privilege (side effects) Elevating Privileges Safely The Hostile Environment and the Principle of Least Privilege 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 60Keep in mind that, even if your code is free of errors, vulnerabilities in any libraries your code links in can be used to attack your program. For example, no program with a graphical user interface should run with privileges because the large number of libraries used in any GUI application makes it virtually impossible to guarantee that the application has no security vulnerabilities. There are a number of ways an attacker can take advantage of your program if you run as root. Some possible approaches are described in the following sections. Launching a New Process Because any new process runs with the privileges of the process that launched it, if an attacker can trick your process into launching his code, the malicious code runs with the privileges of your process. Therefore, if your process is running with root privileges and is vulnerable to attack, the attacker can gain control of the system. There are many ways an attacker can trick your code into launching malicious code, including buffer overflows, race conditions, and social engineering attacks (see “Types of Security Vulnerabilities” (page 11)). Executing Command-Line Arguments Because all command-line arguments, including the program name (argv(0)), are under the control of the user, you should not use the command line to execute any program without validating every parameter, including the name. If you use the command line to re-execute your own code or execute a helper program, for example, a malicious user might have substituted his own code with that program name, which you are now executing with your privileges. Inheriting File Descriptors When you create a new process, the child process inherits its own copy of the parent process’s file descriptors (see the manual page for fork(2)). Therefore, if you have a handle on a file, network socket, shared memory, or other resource that’s pointed to by a file descriptor and you fork off a child process, you must be careful to either close the file descriptor or you must make sure that the child process cannot be tampered with. Otherwise, a malicious user can use the subprocess to tamper with the resources referenced by the file descriptors. For example, if you open a password file and don’t close it before forking a process, the new subprocess has access to the password file. To set a file descriptor so that it closes automatically when you execute a new process (such as by using the execve system call), use the fcntl(2) command to set the close-on-exec flag. You mustset thisflag individually for each file descriptor; there’s no way to set it for all. Elevating Privileges Safely The Hostile Environment and the Principle of Least Privilege 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 61Abusing Environment Variables Most libraries and utilities use environment variables. Sometimes environment variables can be attacked with buffer overflows or by inserting inappropriate values. If your program links in any libraries or calls any utilities, your program is vulnerable to attacks through any such problematic environment variables. If your program is running as root, the attacker might be able to bring down or gain control of the whole system in this way. Examples of environment variables in utilities and libraries that have been attacked in the past include: 1. The dynamic loader: LD_LIBRARY_PATH, DYLD_LIBRARY_PATH are often misused, causing unwanted side effects. 2. libc: MallocLogFile 3. Core Foundation: CF_CHARSET_PATH 4. perl: PERLLIB, PERL5LIB, PERL5OPT [ 2 CVE-2005-2748 (corrected in Apple Security Update 2005-008) 3 CVE-2005-0716 (corrected in Apple Security Update 2005-003) 4 CVE-2005-4158] Environment variables are also inherited by child processes. If you fork off a child process, your parent process should validate the values of all environment variables before it uses them in case they were altered by the child process (whether inadvertently or through an attack by a malicious user). Modifying Process Limits You can use the setrlimit call to limit the consumption of system resources by a process. For example, you can set the largest size of file the process can create, the maximum amount of CPU time the process can consume, and the maximum amount of physical memory a process may use. These process limits are inherited by child processes. In order to prevent an attacker from taking advantage of open file descriptors, programsthat run with elevated privileges often close all open file descriptors when they start up. However, if an attacker can use setrlimit to alter the file descriptor limit, he can fool the program into leaving some of the files open. Those files are then vulnerable. Similarly, a vulnerability was reported for a version of Linux that made it possible for an attacker, by decreasing the maximum file size, to limit the size of the /etc/passwd and /etc/shadow files. Then, the next time a utility accessed one of these files, it truncated the file, resulting in a loss of data and denial of service. [CVE-2002-0762] Elevating Privileges Safely The Hostile Environment and the Principle of Least Privilege 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 62File Operation Interference If you’re running with elevated privileges in order to write or read files in a world-writable directory or a user’s directory, you must be aware of time-of-check–time-of-use problems; see “Time of Check Versus Time of Use” (page 44). Avoiding Elevated Privileges In many cases, you can accomplish your task without needing elevated privileges. For example, suppose you need to configure the environment (add a configuration file to the user’s home directory or modify a configuration file in the user’s home directory) for your application. You can do this from an installer running asroot (the installer command requires administrative privileges;see the manual page for installer(8)). However, if you have the application configure itself, or check whether configuration is needed when it starts up, then you don’t need to run as root at all. An example of using an alternate design in order to avoid running with elevated privileges is given by the BSD ps command, which displaysinformation about processesthat have controlling terminals. Originally, BSD used the setgid bit to run the ps command with a group ID of kmem, which gave it privilegesto read kernel memory. More recent implementations of the ps command use the sysctl utility to read the information it needs, removing the requirement that ps run with any special privileges. Running with Elevated Privileges If you do need to run code with elevated privileges, there are several approaches you can take: ● You can run a daemon with elevated privileges that you call on when you need to perform a privileged task. The preferred method of launching a daemon is to use the launchd daemon (see “launchd” (page 66)). It is easier to use launchd to launch a daemon and easier to communicate with a daemon than it is to fork your own privileged process. ● You can use the authopen command to read, create, or update a file (see “authopen” (page 65)). ● You can set the setuid and setgid bitsfor the executable file of your code, and set the owner and group of the file to the privilege level you need; for example, you can set the owner to root and the group to wheel. Then when the code is executed, it runs with the elevated privileges of its owner and group rather than with the privileges of the process that executed it. (See the “Permissions” section in the “Security Concepts” chapter in Security Overview.) This technique is often used to execute the privileged code in a factored application (see “Factoring Applications” (page 69)). As with other privileged code, you must be very sure that there are no vulnerabilities in your code and that you don’t link in any libraries or call any utilities that have vulnerabilities. Elevating Privileges Safely Avoiding Elevated Privileges 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 63If you fork off a privileged process, you should terminate it as soon as it has accomplished its task (see “Factoring Applications” (page 69)). Although architecturally thisis often the bestsolution, it is very difficult to do correctly, especially the first time you try. Unless you have a lot of experience with forking off privileged processes, you might want to try one of the other solutions first. ● You can use a BSD system call to change privilege level (see “Calls to Change Privilege Level” (page 64)). These commands have confusing semantics. You must be careful to use them correctly, and it’s very important to check the return values of these calls to make sure they succeeded. Note that in general, unless your process was initially running as root, it cannot elevate its privilege with these calls. However, a process running as root can discard (temporarily or permanently) those privileges. Any process can change from acting on behalf of one group to another (within the set of groups to which it belongs). Calls to Change Privilege Level There are several commands you can use to change the privilege level of a program. The semantics of these commands are tricky, and vary depending on the operating system on which they’re used. Important: If you are running with both a group ID (GID) and user ID (UID) that are different from those of the user, you have to drop the GID before dropping the UID. Once you’ve changed the UID, you may no longer have sufficient privileges to change the GID. Important: As with every security-related operation, you must check the return values of your calls to setuid, setgid, and related routines to make sure they succeeded. Otherwise you might still be running with elevated privileges when you think you have dropped privileges. For more information on permissions,see the “Permissions”section in the “Security Concepts” chapter in Security Overview. For information on setuid and related commands, see Setuid Demystified by Chen, Wagner, and Dean (Proceedings of the 11th USENIX Security Symposium, 2002), available at http://www.usenix.org/publications/library/proceedings/sec02/full_papers/chen/chen.pdf and the manual pages for setuid(2), setreuid(2), setregid(2), and setgroups(2). The setuid(2)manual page includesinformation about seteuid, setgid, and setegid as well. Here are some notes on the most commonly used system calls for changing privilege level: Elevating Privileges Safely Calls to Change Privilege Level 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 64● The setuid function sets the real and effective user IDs and the saved user ID of the current process to a specified value. The setuid function is the most confusing of the UID-setting system calls. Not only does the permission required to use this call differ among different UNIX-based systems, but the action of the call differs among different operating systems and even between privileged and unprivileged processes. If you are trying to set the effective UID, you should use the seteuid function instead. ● The setreuid function modifies the real UID and effective UID, and in some cases, the saved UID. The permission required to use this call differs among different UNIX-based systems, and the rule by which the saved UID is modified is complicated. For this function as well, if your intent is to set the effective UID, you should use the seteuid function instead. ● The seteuid function sets the effective UID, leaving the real UID and saved UID unchanged. In OS X, the effective user ID may be set to the value of the real user ID or of the saved set-user-ID. (In some UNIX-based systems, thisfunction allows you to set the EUID to any of the real UID,saved UID, or EUID.) Of the functions available on OS X that set the effective UID, the seteuid function is the least confusing and the least likely to be misused. ● The setgid function acts similarly to the setuid function, except that it sets group IDs rather than user IDs. It suffers from the same shortcomings as the setuid function; use the setegid function instead. ● The setregid function acts similarly to the setreuid function, with the same shortcomings; use the setegid function instead. ● The setegid function sets the effective GID. This function is the preferred call to use if you want to set the EGID. Avoiding Forking Off a Privileged Process There are a couple of functions you might be able to use to avoid forking off a privileged helper application. The authopen command lets you obtain temporary rights to create, read, or update a file. You can use the launchd daemon to start a process with specified privileges and a known environment. authopen When you run the authopen command, you provide the pathname of the file that you want to access. There are options for reading the file, writing to the file, and creating a new file. Before carrying out any of these operations, the authopen command requests authorization from the system security daemon, which authenticates the user (through a password dialog or other means) and determines whether the user has sufficient rights to carry out the operation. See the manual page for authopen(1) for the syntax of this command. Elevating Privileges Safely Avoiding Forking Off a Privileged Process 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 65launchd Starting with OS X v10.4, the launchd daemon is used to launch daemons and other programs automatically, without user intervention. (If you need to support systems running versions of the OS earlier than OS X v10.4, you can use startup items.) The launchd daemon can launch both systemwide daemons and per-user agents, and can restart those daemons and agents after they quit if they are still needed. You provide a configuration file that tells launchd the level of privilege with which to launch your routine. You can also use launchd to launch a privileged helper. By factoring your application into privileged and unprivileged processes, you can limit the amount of code running as the root user (and thus the potential attack surface). Be sure that you do not request higher privilege than you actually need, and always drop privilege or quit execution as soon as possible. There are several reasons to use launchd in preference to writing a daemon running as the root user or a factored application that forks off a privileged process: ● Because launchd launches daemons on demand, your daemon needs not worry about whether other services are available yet. When it makes a request for one of those services, the service gets started automatically in a manner that is transparent to your daemon. ● Because launchd itself runs as the root user, if your only reason for using a privileged process is to run a daemon on a low-numbered port, you can let launchd open that port on your daemon’s behalf and pass the open socket to your daemon, thus eliminating the need for your code to run as the root user. ● Because launchd can launch a routine with elevated privileges, you do not have to set the setuid or setgid bits for the helper tool. Any routine that has the setuid or setgid bit set is likely to be a target for attack by malicious users. ● A privileged routine started by launchd runs in a controlled environment that can’t be tampered with. If you launch a helper tool that has the setuid bit set, it inherits much of the launching application’s environment, including: ● Open file descriptors (unless their close-on-exec flag is set). ● Environment variables (unless you use posix_spawn, posix_spawnp, or an exec variant that takes an explicit environment argument). ● Resource limits. ● The command-line arguments passed to it by the calling process. ● Anonymous shared memory regions (unattached, but available to reattach, if desired). ● Mach port rights. There are probably others. It is much safer to use launchd, which completely controls the launch environment. Elevating Privileges Safely Avoiding Forking Off a Privileged Process 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 66● It’s much easier to understand and verify the security of a protocol between your controlling application and a privileged daemon than to handle the interprocess communication needed for a process you forked yourself. When you fork a process, it inheritsits environment from your application, including file descriptors and environment variables, which might be used to attack the process (see “The Hostile Environment and the Principle of Least Privilege” (page 60)). You can avoid these problems by using launchd to launch a daemon. ● It’s easier to write a daemon and launch it with launchd than to write factored code and fork off a separate process. ● Because launchd is a critical system component, it receives a lot of peer review by in-house developers at Apple. It is less likely to contain security vulnerabilities than most production code. ● The launchd.plist file includes key-value pairs that you can use to limit the system services—such as memory, number of files, and cpu time—that the daemon can use. For more information on launchd, see the manual pages for launchd, launchctl, and launchd.plist, and Daemons and Services Programming Guide . For more information about startup items, see Daemons and Services Programming Guide . Limitations and Risks of Other Mechanisms In addition to launchd, the following lesser methods can be used to obtain elevated privileges. In each case, you must understand the limitations and risks posed by the method you choose. ● setuid If an executable's setuid bit is set, the program runs as whatever user owns the executable regardless of which process launches it. There are two approaches to using setuid to obtain root (or another user’s) privileges while minimizing risk: ● Launch your program with root privileges, perform whatever privileged operations are necessary immediately, and then permanently drop privileges. ● Launch a setuid helper tool that runs only as long as necessary and then quits. If the operation you are performing needs a group privilege or user privilege other than root, you should launch your program or helper tool with that privilege only, not with root privilege, to minimize the damage if the program is hijacked. It’s important to note that if you are running with both a group ID (GID) and user ID (UID) that are different from those of the user, you have to drop the GID before dropping the UID. Once you’ve changed the UID, you can no longer change the GID. As with every security-related operation, you must check the return values of your calls to setuid, setgid, and related routines to make sure they succeeded. Elevating Privileges Safely Limitations and Risks of Other Mechanisms 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 67For more information about the use of the setuid bit and related routines, see “Elevating Privileges Safely” (page 59). ● SystemStarter When you put an executable in the /Library/StartupItems directory, it is started by the SystemStarter program at boot time. Because SystemStarter runs with root privileges, you can start your program with any level of privilege you wish. Be sure to use the lowest privilege level that you can use to accomplish your task, and to drop privilege as soon as possible. Startup items run daemons with root privilege in a single global session; these processes serve all users. For OS X v10.4 and later, the use of startup items is deprecated; use the launchd daemon instead. For more information on startup items and startup item privileges,see “Startup Items” in Daemons and Services Programming Guide . ● AuthorizationExecWithPrivilege The Authorization Services API provides the AuthorizationExecWithPrivilege function, which launches a privileged helper as the root user. Although this function can execute any process temporarily with root privileges, it is not recommended except for installersthat have to be able to run from CDs and self-repairing setuid tools. See Authorization Services Programming Guide for more information. ● xinetd In earlier versions of OS X, the xinetd daemon was launched with root privileges at system startup and subsequently launched internetservices daemons when they were needed. The xinetd.conf configuration file specified the UID and GID of each daemon started and the port to be used by each service. Starting with OS X v10.4, you should use launchd to perform the services formerly provided by xinetd. SeeDaemonsandServicesProgrammingGuide forinformation about convertingfromxinetdtolaunchd. See the manual pages for xinetd(8) and xinetd.conf(5) for more information about xinetd. ● Other If you are using some other method to obtain elevated privilege for your process, you should switch to one of the methods described here and follow the cautions described in this chapter and in “Elevating Privileges Safely” (page 59). Elevating Privileges Safely Limitations and Risks of Other Mechanisms 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 68Factoring Applications If you’ve read this far and you’re still convinced you need to factor your application into privileged and nonprivileged processes, this section provides some tips and sample code. In addition, see Authorization Services Programming Guide for more advice on the use of Authorization Services and the proper way to factor an application. As explained in the Authorization Services documentation, it is very important that you check the user’s rights to perform the privileged operation, both before and after launching your privileged helper tool. Your helper tool, owned by root and with the setuid bit set, has sufficient privileges to perform whatever task it has to do. However, if the user doesn’t have the rights to perform this task, you shouldn’t launch the tool and—if the tool gets launched anyway—the tool should quit without performing the task. Your nonprivileged process should first use Authorization Services to determine whether the user is authorized and to authenticate the user if necessary (this is called preauthorizing ; see Listing 5-1 (page 70)). Then launch your privileged process. The privileged process then should authorize the user again, before performing the task that requires elevated privileges; see Listing 5-2 (page 71). As soon as the task is complete, the privileged process should terminate. In determining whether a user has sufficient privileges to perform a task, you should use rights that you have defined and put into the policy database yourself. If you use a right provided by the system or by some other developer, the user might be granted authorization for that right by some other process, thus gaining privileges to your application or access to data that you did not authorize or intend. For more information about policies and the policy database, (see the section “The Policy Database” in the “Authorization Concepts” chapter of Authorization Services Programming Guide ). In the code samples shown here, the task that requires privilege is killing a process that the user does not own. Example: Preauthorizing If a user tries to kill a process that he doesn’t own, the application has to make sure the user is authorized to do so. The following numbered items correspond to comments in the code sample: 1. If the process is owned by the user, and the process is not the window server or the login window, go ahead and kill it. 2. Call the permitWithRight method to determine whether the user has the right to kill the process. The application must have previously added this right—in this example, called com.apple.processkiller.kill—to the policy database. The permitWithRight method handles the interaction with the user (such as an authentication dialog). If this method returns 0, it completed without an error and the user is considered preauthorized. 3. Obtain the authorization reference. 4. Create an external form of the authorization reference. 5. Create a data object containing the external authorization reference. Elevating Privileges Safely Factoring Applications 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 696. Pass this serialized authorization reference to the setuid tool that will kill the process (Listing 5-2 (page 71)). Listing 5-1 Non-privileged process if (ownerUID == _my_uid && ![[contextInfo processName] isEqualToString:@"WindowServer"] && ![[contextInfo processName] isEqualToString:@"loginwindow"]) { [self killPid:pid withSignal:signal]; // 1 } else { SFAuthorization *auth = [SFAuthorization authorization]; if (![auth permitWithRight:"com.apple.proccesskiller.kill" flags: kAuthorizationFlagDefaults|kAuthorizationFlagInteractionAllowed| kAuthorizationFlagExtendRights|kAuthorizationFlagPreAuthorize]) // 2 { AuthorizationRef authRef = [auth authorizationRef]; // 3 AuthorizationExternalForm authExtForm; OSStatus status = AuthorizationMakeExternalForm(authRef, &authExtForm);// 4 if (errAuthorizationSuccess == status) { NSData *authData = [NSData dataWithBytes: authExtForm.bytes length: kAuthorizationExternalFormLength]; // 5 [_agent killProcess:pid signal:signal authData: authData]; // 6 } } } The external tool is owned by root and has its setuid bit set so that it runs with root privileges. It imports the externalized authorization rights and checks the user’s authorization rights again. If the user has the rights, the tool killsthe process and quits. The following numbered items correspond to commentsin the code sample: 1. Convert the external authorization reference to an authorization reference. 2. Create an authorization item array. 3. Create an authorization rights set. Elevating Privileges Safely Factoring Applications 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 704. Call the AuthorizationCopyRights function to determine whether the user has the right to kill the process. You pass this function the authorization reference. If the credentials issued by the Security Server when it authenticated the user have not yet expired, this function can determine whether the user is authorized to kill the process without reauthentication. If the credentials have expired, the Security Server handles the authentication (for example, by displaying a password dialog). (You specify the expiration period for the credentials when you add the authorization right to the policy database.) 5. If the user is authorized to do so, kill the process. 6. If the user is not authorized to kill the process, log the unsuccessful attempt. 7. Release the authorization reference. Listing 5-2 Privileged process AuthorizationRef authRef = NULL; OSStatus status = AuthorizationCreateFromExternalForm( (AuthorizationExternalForm *)[authData bytes], &authRef); // 1 if ((errAuthorizationSuccess == status) && (NULL != authRef)) { AuthorizationItem right = {"com.apple.proccesskiller.kill", 0L, NULL, 0L}; // 2 AuthorizationItemSet rights = {1, &right}; // 3 status = AuthorizationCopyRights(authRef, &rights, NULL, kAuthorizationFlagDefaults | kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights, NULL); // 4 if (errAuthorizationSuccess == status) kill(pid, signal); // 5 else NSLog(@"Unauthorized attempt to signal process %d with %d", pid, signal); // 6 AuthorizationFree(authRef, kAuthorizationFlagDefaults); // 7 } Helper Tool Cautions If you write a privileged helper tool, you need to be very careful to examine your assumptions. For example, you should always check the results of function calls; it is dangerousto assume they succeeded and to proceed on that assumption. You must be careful to avoid any of the pitfalls discussed in this document, such as buffer overflows and race conditions. Elevating Privileges Safely Factoring Applications 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 71If possible, avoid linking in any extra libraries. If you do have to link in a library, you must not only be sure that the library has no security vulnerabilities, but also that it doesn’t link in any other libraries. Any dependencies on other code potentially open your code to attack. In order to make your helper tool as secure as possible, you should make it as short as possible—have it do only the very minimum necessary and then quit. Keeping it short makes it less likely that you made mistakes, and makes it easier for others to audit your code. Be sure to get a security review from someone who did not help write the tool originally. An independent reviewer is less likely to share your assumptions and more likely to spot vulnerabilities that you missed. Authorization and Trust Policies In addition to the basic permissions provided by BSD, the OS X Authorization Services API enables you to use the policy database to determine whether an entity should have access to specific features or data within your application. Authorization Services includes functions to read, add, edit, and delete policy database items. You should define your own trust policies and put them in the policy database. If you use a policy provided by the system or by some other developer, the user might be granted authorization for a right by some other process, thus gaining privileges to your application or access to data that you did not authorize or intend. Define a different policy for each operation to avoid having to give broad permissions to users who need only narrow privileges. For more information about policies and the policy database, see the section “The Policy Database” in the “Authorization Concepts” chapter of Authorization Services Programming Guide . Authorization Services does not enforce access controls; rather, it authenticates users and lets you know whether they have permission to carry out the action they wish to perform. It is up to your program to either deny the action or carry it out. Security in a KEXT Because kernel extensions have no user interface, you cannot call Authorization Servicesto obtain permissions that you do not already have. However, in portions of your code that handle requests from user space, you can determine what permissions the calling process has, and you can evaluate access control lists (ACLs; see the section “ACLs” in the “Security Concepts” section of Security Overview). In OS X v10.4 and later, you can also use the Kernel Authorization (Kauth) subsystem to manage authorization. For more information on Kauth, see Technical Note TN2127, Kernel Authorization (http://developer.apple.com/technotes/tn2005/tn2127.html). Elevating Privileges Safely Authorization and Trust Policies 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 72The user is often the weak link in the security of a system. Many security breaches have been caused by weak passwords, unencrypted filesleft on unprotected computers, and successfulsocial engineering attacks. Therefore, it is vitally important that your program’s user interface enhance security by making it easy for the user to make secure choices and avoid costly mistakes. In a social engineering attack, the user is tricked into either divulging secret information or running malicious code. For example, the Melissa virus and the Love Letter worm each infected thousands of computers when users downloaded and opened files sent in email. This chapter discusses how doing things that are contrary to user expectations can cause a security risk, and gives hints for creating a user interface that minimizes the risk from social engineering attacks. Secure human interface design is a complex topic affecting operating systems as well as individual programs. This chapter gives only a few hints and highlights. For an extensive discussion of this topic, see Cranor and Garfinkel, Security and Usability: Designing Secure Systems that People Can Use , O’Reilly, 2005. There is also an interesting weblog on this subject maintained by researchers at the University of California at Berkeley (http://usablesecurity.com/). Use Secure Defaults Most users use an application’s default settings and assume that they are secure. If they have to make specific choices and take multiple actions in order to make a program secure, few will do so. Therefore, the default settings for your program should be as secure as possible. For example: ● If your program launches other programs, it should launch them with the minimum privileges they need to run. ● If your program supports optionally connecting by SSL, the checkbox should be checked by default. ● If your program displays a user interface that requires the user to decide whether to perform a potentially dangerous action, the default option should be the safe choice. If there is no safe choice, there should be no default. (See “UI Element Guidelines: Controls” in OS X Human Interface Guidelines.) And so on. 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 73 Designing Secure User InterfacesThere is a common belief that security and convenience are incompatible. With careful design, this does not have to be so. In fact, it is very important that the user not have to sacrifice convenience for security, because many users will choose convenience in thatsituation. In many cases, a simpler interface is more secure, because the user is less likely to ignore security features and less likely to make mistakes. Whenever possible, you should make security decisions for your users: in most cases, you know more about security than they do, and if you can’t evaluate the evidence to determine which choice is most secure, the chances are your users will not be able to do so either. For a detailed discussion of this issue and a case study, see the article “Firefox and the Worry-Free Web” in Cranor and Garfinkel, Security and Usability: Designing Secure Systems that People Can Use . Meet Users’ Expectations for Security If your program handles data that the user expects to be kept secret, make sure that you protect that data at all times. That means not only keeping it in a secure location or encrypting it on the user’s computer, but not handing it off to another program unless you can verify that the other program will protect the data, and not transmitting it over an insecure network. If for some reason you cannot keep the data secure, you should make this situation obvious to users and give them the option of canceling the insecure operation. Important: The absence of an indication that an operation is secure is not a good way to inform the user that the operation is insecure. A common example of this is any web browser that adds a lock icon (usually small and inconspicuous) on web pages that are protected by SSL/TLS or some similar protocol. The user has to notice that this icon is not present (or that it’s in the wrong place, in the case of a spoofed web page) in order to take action. Instead, the program should prominently display some indication for each web page or operation that is not secure. The user must be made aware of when they are granting authorization to some entity to act on their behalf or to gain access to their files or data. For example, a program might allow users to share files with other users on remote systems in order to allow collaboration. In this case, sharing should be off by default. If the user turns it on, the interface should make clear the extent to which remote users can read from and write to files on the local system. If turning on sharing for one file also lets remote users read any other file in the same folder, for example, the interface must make this clear before sharing is turned on. In addition, as long as sharing is on, there should be some clear indication that it is on, lest users forget that their files are accessible by others. Designing Secure User Interfaces Meet Users’ Expectations for Security 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 74Authorization should be revocable: if a user grants authorization to someone, the user generally expects to be able to revoke that authorization later. Whenever possible, your program should not only make this possible, it should make it easy to do. If for some reason it will not be possible to revoke the authorization, you should make that clear before granting the authorization. You should also make it clear that revoking authorization cannot reverse damage already done (unless your program provides a restore capability). Similarly, any other operation that affects security but that cannot be undone should either not be allowed or the user should be made aware of the situation before they act. For example, if all files are backed up in a central database and can’t be deleted by the user, the user should be aware of that fact before they record information that they might want to delete later. As the user’s agent, you must carefully avoid performing operations that the user does not expect or intend. For example, avoid automatically running code if it performsfunctionsthat the user has not explicitly authorized. Secure All Interfaces Some programs have multiple user interfaces, such as a graphical user interface, a command-line interface, and an interface for remote access. If any of these interfaces require authentication (such as with a password), then all the interfaces should require it. Furthermore, if you require authentication through a command line or remote interface, be sure the authentication mechanism is secure—don’t transmit passwords in cleartext, for example. Place Files in Secure Locations Unless you are encrypting all output, the location where you save files has important security implications. For example: ● FileVault can secure the root volume (or the user’s home folder prior to OS X v10.7), but not other locations where the user might choose to place files. ● Folder permissions can be set in such a way that others can manipulate their contents. You should restrict the locations where users can save files if they contain information that must be protected. If you allow the user to select the location to save files, you should make the security implications of a particular choice clear; specifically, they must understand that, depending on the location of a file, it might be accessible to other applications or even remote users. Designing Secure User Interfaces Secure All Interfaces 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 75Make Security Choices Clear Most programs, upon detecting a problem or discrepancy, display a dialog box informing the user of the problem. Often this approach does not work, however. For one thing, the user might not understand the warning or its implications. For example, if the dialog warns the user that the site to which they are connecting has a certificate whose name does not match the name of the site, the user is unlikely to know what to do with that information, and is likely to ignore it. Furthermore, if the program puts up more than a few dialog boxes, the user is likely to ignore all of them. To solve this problem, when giving the user a choice that has security implications, make the potential consequences of each choice clear. The user should never be surprised by the results of an action. The choice given to the user should be expressed in terms of consequences and trade-offs, not technical details. For example, a choice of encryption methods should be based on the level of security (expressed in simple terms,such asthe amount of time it might take to break the encryption) versusthe time and disk space required to encrypt the data, rather than on the type of algorithm and the length of the key to be used. If there are no practical differences of importance to the user (as when the more secure encryption method is just as efficient as the less-secure method), just use the most secure method and don’t give the user the choice at all. Be sensitive to the fact that few users are security experts. Give as much information—in clear, nontechnical terms—as necessary for them to make an informed decision. In some cases, it might be best not to give them the option of changing the default behavior. For example, most users don’t know what a digital certificate is, let alone the implications of accepting a certificate signed by an unknown authority. Therefore, it is probably not a good idea to let the user permanently add an anchor certificate (a certificate that is trusted for signing other certificates) unless you can be confident that the user can evaluate the validity of the certificate. (Further, if the user is a security expert, they’ll know how to add an anchor certificate to the keychain without the help of your application anyway.) If you are providing security features, you should make their presence clear to the user. For example, if your mail application requires the user to double click a small icon in order to see the certificate used to sign a message, most users will never realize that the feature is available. In an often-quoted but rarely applied monograph, Jerome Saltzer and Michael Schroeder wrote “It is essential that the human interface be designed for ease of use, so that users routinely and automatically apply the protection mechanisms correctly. Also, to the extent that the user’s mental image of his protection goals matchesthe mechanisms he must use, mistakes will be minimized. If he must translate hisimage of his protection needs into a radically different specification language, he will make errors.” (Saltzer and Schroeder, “The Protection of Information in Computer Systems,” Proceedings of the IEEE 63:9, 1975.) Designing Secure User Interfaces Make Security Choices Clear 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 76For example, you can assume the user understandsthat the data must be protected from unauthorized access; however, you cannot assume the user has any knowledge of encryption schemes or knows how to evaluate password strength. In this case, your program should present the user with choices like the following: ● “Is your computer physically secure, or is it possible that an unauthorized user will have physical access to the computer?” ● “Is your computer connected to a network?” From the user’s answers, you can determine how best to protect the data. Unless you are providing an “expert” mode, do not ask the user questions like the following: ● “Do you want to encrypt your data, and if so, with which encryption scheme?” ● “How long a key should be used?” ● “Do you want to permit SSH access to your computer?” These questions don’t correspond with the user’s view of the problem. Therefore, the user’s answers to such questions are likely to be erroneous. In this regard, it is very important to understand the user’s perspective. Very rarely is an interface thatseemssimple or intuitive to a programmer actually simple or intuitive to average users. To quote Ka-Ping Yee (User Interaction Design for Secure Systems, at http://www.eecs.berkeley.edu/Pubs/TechRpts/2002/CSD-02-1184.pdf): In order to have a chance of using a system safely in a world of unreliable and sometimes adversarial software, a user needs to have confidence in all of the following statements: ● Things don’t become unsafe all by themselves. (Explicit Authorization) ● I can know whether things are safe. (Visibility) ● I can make things safer. (Revocability) ● I don’t choose to make things unsafe. (Path of Least Resistance) ● I know what I can do within the system. (Expected Ability) ● I can distinguish the things that matter to me. (Appropriate Boundaries) ● I can tell the system what I want. (Expressiveness) ● I know what I’m telling the system to do. (Clarity) ● The system protects me from being fooled. (Identifiability, Trusted Path) For additional tips, read “Dialogs” in OS X Human Interface Guidelines and “Alerts, Action Sheets, and Modal Views” in iOS Human Interface Guidelines. Designing Secure User Interfaces Make Security Choices Clear 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 77Fight Social Engineering Attacks Social engineering attacks are particularly difficult to fight. In a social engineering attack, the attacker fools the user into executing attack code or giving up private information. A common form of social engineering attack is referred to as phishing . Phishing refers to the creation of an official-looking email or web page that fools the user into thinking they are dealing with an entity with which they are familiar,such as a bank with which they have an account. Typically, the user receives an email informing them that there is something wrong with their account, and instructing them to click on a link in the email. The link takes them to a web page that spoofs a real one; that is, it includes icons, wording, and graphical elements that echo those the user is used to seeing on a legitimate web page. The user is instructed to enter such information as their social security number and password. Having done so, the user has given up enough information to allow the attacker to access the user’s account. Fighting phishing and other social engineering attacks is difficult because the computer’s perception of an email or web page is fundamentally different from that of the user. For example, consider an email containing a link to http://scamsite.example.com/ but in which the link’s text says Apple Web Store. From the computer’s perspective, the URL links to a scam site, but from the user’s perspective, it links to Apple’s online store. The user cannot easily tell that the link does not lead to the location they expect until they see the URL in their browser; the computer similarly cannot determine that the link’s text is misleading. To further complicate matters, even when the user looks at the actual URL, the computer and user may perceive the URL differently. The Unicode characterset includes many charactersthat look similar or identical to common English letters. For example, the Russian glyph that is pronounced like “r” looks exactly like an English “p” in many fonts, though it has a different Unicode value. These characters are referred to as homographs. When web browsers began to support internationalized domain names (IDN), some phishers set up websites that looked identical to legitimate ones, using homographs in their web addresses to fool users into thinking the URL was correct. Some creative techniques have been tried for fighting social engineering attacks, including trying to recognize URLsthat are similar to, but not the same as, well-known URLs, using private email channelsfor communications with customers, using emailsigning, and allowing usersto see messages only if they come from known, trusted sources. All of these techniques have problems, and the sophistication ofsocial engineering attacksisincreasing all the time. For example, to foil the domain name homograph attack, many browsers display internationalized domain names IDN) in an ASCII format called “Punycode.” For example, an impostor website with the URL http://www.apple.com/ that uses a Roman script for all the characters except for the letter “a”, for which it uses a Cyrillic character, is displayed as http://www.xn--pple-43d.com. Designing Secure User Interfaces Fight Social Engineering Attacks 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 78Different browsers use different schemes when deciding which internationalized domain names to show and which ones to translate. For example, Safari uses this form when a URL contains characters in two or more scripts that are not allowed in the same URL, such as Cyrillic characters and traditional ASCII characters. Other browsers consider whether the characterset is appropriate for the user’s default language. Still others maintain a whitelist of registries that actively prevent such spoofing and use punycode for domains from all other registries. For a more in-depth analysis of the problem, more suggested approaches to fighting it, and some case studies, see Security and Usability: Designing Secure Systems that People Can Use by Cranor and Garfinkel. To learn more aboutsocial engineering techniquesin general, read The Art of Deception: Controlling the Human Element of Security by Mitnick, Simon, and Wozniak. Use Security APIs When Possible One way to avoid adding security vulnerabilities to your code is to use the available security APIs whenever possible. The Security Interface Framework API provides a number of user interface viewsto support commonly performed security tasks. iOS Note: The Security Interface Framework is not available in iOS. In iOS, applications are restricted in their use of the keychain, and it is not necessary for the user to create a new keychain or change keychain settings. The Security Interface Framework API provides the following views: ● TheSFAuthorizationView class implements an authorization view in a window. An authorization view is a lock icon and accompanying text that indicates whether an operation can be performed. When the user clicks a closed lock icon, an authorization dialog displays. Once the user is authorized, the lock icon appears open. When the user clicksthe open lock, Authorization Servicesrestricts access again and changes the icon to the closed state. ● The SFCertificateView and SFCertificatePanel classes display the contents of a certificate. ● The SFCertificateTrustPanel class displays and optionally lets the user edit the trust settings in a certificate. ● The SFChooseIdentityPanel class displays a list of identities in the system and lets the user select one. (In this context, identity refers to the combination of a private key and its associated certificate.) ● The SFKeychainSavePanel class adds an interface to an application that lets the user save a new keychain. The user interface is nearly identical to that used for saving a file. The difference is that this class returns a keychain in addition to a filename and lets the user specify a password for the keychain. Designing Secure User Interfaces Use Security APIs When Possible 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 79● The SFKeychainSettingsPanel class displays an interface that lets the user change keychain settings. Documentation for the Security Interface framework is in Security Interface Framework Reference . Designing Secure User Interfaces Use Security APIs When Possible 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 80Privilege separation is a common technique for making applications more secure. By breaking up an application into functional units that each require fewer privileges, you can make it harder to do anything useful with any single part of that application if someone successfully compromises it. However, without proper design, a privilege-separated app is not significantly more secure than a non-privilege-separated app. For proper security, each part of the app must treat other parts of the app as untrusted and potentially hostile. To that end, this chapter provides dos and don’ts for designing a helper app. There are two different ways that you can perform privilege separation: ● Creating a pure computation helper to isolate risky operations. Thistechnique requiresthe main application to be inherently suspicious of any data that the helper returns, but does not require that the helper be suspicious of the application. ● Creating a helper or daemon to perform tasks without granting the application the right to perform them. This requires not only that the main application not trust the helper, but also that the helper not trust the main application. The techniques used for securing the two types of helpers differ only in the level of paranoia required by the helper. Avoid Puppeteering When a helper application is so tightly controlled by the main application that it does not make any decisions by itself, thisis called puppeteering. Thisisinherently bad design because if the application gets compromised, the attacker can then control the helper similarly, in effect taking over pulling the helper’s “strings”. This completely destroys the privilege separation boundary. Therefore, unless you are creating a pure computation helper, splitting code into a helper application that simply does whatever the main app tells it to do is usually not a useful division of labor. In general, a helper must be responsible for deciding whether or not to perform a particular action. If you look at the actions that an application can perform with and without privilege separation, those lists should be different; if they are not, then you are not gaining anything by separating the functionality out into a separate helper. 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 81 Designing Secure Helpers and DaemonsFor example, consider a helper that downloads help content for a word processor. If the helper fetches any arbitrary URL that the word processor sends it, the helper can be trivially exploited to send arbitrary data to an arbitrary server. For example, an attacker who took control of the browser could tell the helper to access the URL http://badguy.example.com/saveData?hereIsAnEncodedCopyOfTheUser%27sData. The subsections that follow describe solutions for this problem. Use Whitelists One way to fix this is with whitelists. The helper should include a specific list of resources that it can access. For example, this helper could include: ● A host whitelist that includes only the domain example.org. Requests to URLs in that domain would succeed, but the attacker could not cause the helper to access URLs in a different domain. ● An allowed path prefix whitelist. The attacker would not be able to use cross-site scripting on the example.org bulletin board to redirect the request to another location. (This applies mainly to apps using a web UI.) You can also avoid this by handling redirection manually. ● An allowed file type whitelist. This could limit the helper to the expected types of files. (Note that file type whitelists are more interesting for helpers that access files on the local hard drive.) ● A whitelist of specific URIs to which GET or POST operations are allowed. Use Abstract Identifiers and Structures A second way to avoid puppeteering is by abstracting away the details of the request itself, using data structures and abstract identifiers instead of providing URIs, queries, and paths. A trivial example of thisis a help system. Instead of the app passing a fully-formed URI for a help search request, it might pass a flag field whose value tells the helper to “search by name” or “search by title” and a string value containing the search string. This flag field is an example of an abstract identifier; it tells the helper what to do without telling it how to do it. Taken one step further, when the helper returns a list of search results, instead of returning the names and URIs for the result pages, it could return the names and an opaque identifier (which may be an index into the last set of search results). By doing so, the application cannot access arbitrary URIs because it never interacts with the actual URIs directly. Similarly, if you have an application that works with project files that reference other files, in the absence of API to directly support this, you can use a temporary exception to give a helper access to all files on the disk. To make this more secure, the helpershould provide access only to filesthat actually appear in the user-opened Designing Secure Helpers and Daemons Avoid Puppeteering 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 82project. The helper might do this by requiring the application to request files by some arbitrary identifier generated by the helper rather than by name or path. This makes it harder for the application to ask the helper to open arbitrary files. This can further be augmented with sniffing, as described in “Use the Smell Test” (page 83). The same concept can be extended to other areas. For example, if the application needs to change a record in a database, the helper could send the record as a data structure, and the app could send back the altered data structure along with an indication of which values need to change. The helper could then verify the correctness of the unaltered data before modifying the remaining data. Passing the data abstractly also allows the helper to limit the application’s access to other database tables. It also allows the helper to limit what kinds of queries the application can perform in ways that are more fine-grained than would be possible with the permissions system that most databases provide. Use the Smell Test If a helper application has access to files that the main application cannot access directly, and if the main application asks the helper to retrieve the contents of that file, it is useful for the helper to perform tests on the file before sending the data to ensure that the main application has not substituted a symbolic link to a different file. In particular, it is useful to compare the file extension with the actual contents of the file to see whether the bytes on disk make sense for the apparent file type. This technique is called file type sniffing. For example, the first few bytes of any image file usually provide enough information to determine the file type. If the first four bytes are JFIF, the file is probably a JPEG image file. If the first four bytes are GIF8, the file is probably a GIF image file. If the first four bytes are MM.* or II*., the file is probably a TIFF file. And so on. If the request passes this smell test, then the odds are good that the request is not malicious. Treat Both App and Helper as Hostile Because the entire purpose of privilege separation is to prevent an attacker from being able to do anything useful after compromising one part of an application, both the helper and the app must assume that the other party is potentially hostile. This means each piece must: ● Avoid buffer overflows (“Avoiding Buffer Overflows And Underflows” (page 17)). ● Validate all input from the other side (“Validating Input And Interprocess Communication” (page 33)). ● Avoid insecure interprocess communication mechanisms (“Validating Input And Interprocess Communication” (page 33)) ● Avoid race conditions (“Avoiding Race Conditions” (page 43)). Designing Secure Helpers and Daemons Treat Both App and Helper as Hostile 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 83● Treat the contents of any directory or file to which the other process has write access as fundamentally untrusted (“Securing File Operations” (page 47)). This list potentially includes: ● The entire app container directory. ● Preference files. ● Temporary files. ● User files. And so on. If you follow these design principles, you will make it harder for an attacker to do anything useful if he or she compromises your app. Run Daemons as Unique Users For daemonsthatstart with elevated privileges and then drop privileges, you should always use a locally unique user ID for your program. If you use some standard UID such as _unknown or nobody, then any other process running with thatsame UID can interact with your program, either directly through interprocess communication, or indirectly by altering configuration files. Thus, if someone hijacks another daemon on the same server, they can then interfere with your daemon; or, conversely, ifsomeone hijacks your daemon, they can use it to interfere with other daemons on the server. You can use Open Directory services to obtain a locally unique UID. Note that UIDs from 0 through 500 are reserved for use by the system. Note: You should generally avoid making security decisions based on the user’s ID or name for two reasons: ● Many APIs for determining the user ID and user name are inherently untrustworthy because they return the value of the USER. ● Someone could trivially make a copy of your app and change the string to a different value, then run the app. Start Other Processes Safely When it comes to security, not all APIs for running external tools are created equal. In particular: Avoid the POSIX system(3) function. Its simplicity makes it a tempting choice, but also makes it much more dangerous than other functions. When you use system, you become responsible for completely sanitizing the entire command, which means protecting any characters that are treated as special by the shell. You are Designing Secure Helpers and Daemons Run Daemons as Unique Users 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 84responsible for understanding and correctly using the shell’s quoting rules, knowing which characters are interpreted within each type of quotation marks, and so on. This is no small feat even for expert shell script programmers, and is strongly inadvisable for everyone else. Bluntly put, you will get it wrong. Set up your own environment correctly ahead of time. Many APIs search for the tool you want to run in locations specified by the PATH environment variable. If an attacker can modify that variable, the attacker can potentially trick your app into starting a different tool and running it as the current user. You can avoid this problem by either explicitly setting the PATH environment variable yourself or by avoiding variants of exec(3) or posix_spawn(2) that use the PATH environment variable to search for executables. Use absolute paths where possible, or relative paths if absolute paths are not available. By explicitly specifying a path to an executable rather than just its name, the PATH environment variable is not consulted when the OS determines which tool to run. For more information about environment variables and shell special characters, read Shell Scripting Primer. Designing Secure Helpers and Daemons Start Other Processes Safely 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 85This appendix presents a set of security audit checklists that you can use to help reduce the security vulnerabilities of your software. These checklists are designed to be used during software development. If you read this section all the way through before you start coding, you may avoid many security pitfalls that are difficult to correct in a completed program. Note that these checklists are not exhaustive; you might not have any of the potential vulnerabilities discussed here and still have insecure code. Also, as the author of the code, you are probably too close to the code to be fully objective, and thus may overlook certain flaws. For this reason, it’s very important that you have your code reviewed for security problems by an independent reviewer. A security expert would be best, but any competent programmer, if aware of what to look for, might find problems that you may have missed. In addition, whenever the code is updated or changed in any way, including to fix bugs, it should be checked again for security problems. Important: All code should have a security audit before being released. Use of Privilege This checklist is intended to determine whether your code ever runs with elevated privileges, and if it does, how best to do so safely. Note that it’s best to avoid running with elevated privileges if possible; see “Avoiding Elevated Privileges” (page 63). 1. Reduce privileges whenever possible. If you are using privilege separation with sandboxing or other privilege-limiting techniques, you should be careful to ensure that your helper tools are designed to limit the damage that they can cause if the main application gets compromised, and vice-versa. Read “Designing Secure Helpers And Daemons” (page 81) to learn how. Also, for daemons that start with elevated privileges and then drop privileges, you should always use a locally unique user ID for your program. See “Run Daemons As Unique Users” (page 84) to learn more. 2. Use elevated privileges sparingly, and only in privileged helpers. In most cases, a program can get by without elevated privileges, butsometimes a program needs elevated privileges to perform a limited number of operations, such as writing files to a privileged directory or opening a privileged port. 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 86 Security Development ChecklistsIf an attacker finds a vulnerability that allows execution of arbitrary code, the attacker’s code runs with the same privilege as the running code, and can take complete control of the computer if that code has root privileges. Because of this risk, you should avoid elevating privileges if at all possible. If you must run code with elevated privileges, here are some rules: ● Never run your main process as a different user. Instead, create a separate helper tool that runs with elevated privileges. ● Your helper tool should do as little as possible. ● Your helper tool should restrict what you can ask it to do as much as possible. ● Your helper tool should either drop the elevated privileges or stop executing as soon as possible. Important: If all or most of your code runs with root or other elevated privileges, or if you have complex code that performs multiple operations with elevated privileges, then your program could have a serious security vulnerability. You should seek help in performing a security audit of your code to reduce your risk. See “Elevating Privileges Safely” (page 59) and “Designing Secure Helpers And Daemons” (page 81) for more information. 3. Use launchd when possible. If you are writing a daemon or other process that runs with elevated privileges, you should always use launchd to start it. (To learn why other mechanisms are not recommended, read “Limitations And Risks Of Other Mechanisms” (page 67).) For more information on launchd,see the manual pagesfor launchd, launchctl, and launchd.plist, and Daemons and Services Programming Guide . For more information about startup items, see Daemons and Services Programming Guide . For more information on ipfw, see the ipfw manual page. 4. Avoid using sudo programmatically. If authorized to do so in the sudoers file, a user can use sudo to execute a command as root. The sudo command is intended for occasional administrative use by a user sitting at the computer and typing into the Terminal application. Its use in scripts or called from code is not secure. After executing the sudo command—which requires authenticating by entering a password—there is a five-minute period (by default) during which the sudo command can be executed without further authentication. It’s possible for another process to take advantage of this situation to execute a command as root. Further, there is no encryption or protection of the command being executed. Because sudo is used to execute privileged commands, the command arguments often include user names, passwords, and other information that should be kept secret. A command executed in this way by a script or other code can expose confidential data to possible interception and compromise. Security Development Checklists Use of Privilege 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 875. Minimize the amount of code that must be run with elevated privileges. Ask yourself approximately how many lines of code need to run with elevated privileges. If this answer is either “all” or is a difficult number to compute, then it will be very difficult to perform a security review of your software. If you can’t determine how to factor your application to separate out the code that needs privileges, you are strongly encouraged to seek assistance with your project immediately. If you are an ADC member, you are encouraged to ask for help from Apple engineers with factoring your code and performing a security audit. If you are not an ADC member, see the ADC membership page at http://developer.apple.com/programs/. 6. Never run a GUI application with elevated privileges. You should never run a GUI application with elevated privileges. Any GUI application linksin many libraries over which you have no control and which, due to their size and complexity, are very likely to contain security vulnerabilities. In this case, your application runs in an environment set by the GUI, not by your code. Your code and your user’s data can then be compromised by the exploitation of any vulnerabilities in the libraries or environment of the graphical interface. Data, Configuration, and Temporary Files Some security vulnerabilities are related to reading or writing files. This checklist is intended to help you find any such vulnerabilities in your code. 1. Be careful when working with files in untrusted locations. If you write to any directory owned by the user, then there is a possibility that the user will modify or corrupt your files. Similarly, if you write temporary files to a publicly writable place (for example, /tmp, /var/tmp, /Library/Caches or another specific place with this characteristic), an attacker may be able to modify your files before the next time you read them. If your code reads and writes files (and in particular if it uses files for interprocess communication), you should put those files in a safe directory to which only you have write access. For more information about vulnerabilities associated with writing files, and how to minimize the risks, see “Time of Check Versus Time of Use” (page 44). 2. Avoid untrusted configuration files, preference files, or environment variables. In many cases, the user can control environment variables, configuration files, and preferences. If you are executing a program for the user with elevated privileges, you are giving the user the opportunity to perform operations that they cannot ordinarily do. Therefore, you should ensure that the behavior of your privileged code does not depend on these things. Security Development Checklists Data, Configuration, and Temporary Files 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 88This means: ● Validate all input, whether directly from the user or through environment variables, configuration files, preferences files, or other files. In the case of environment variables, the effect might not be immediate or obvious; however the user might be able to modify the behavior of your program or of other programs or system calls. ● Make sure that file paths do not contain wildcard characters, such as ../ or ~, which an attacker can use to switch the current directory to one under the attacker’s control. ● Explicitly set the privileges, environment variables, and resources available to the running process, rather than assuming that the process has inherited the correct environment. 3. Load kernel extensions carefully (or not at all). A kernel extension is the ultimate privileged code—it has access to levels of the operating system that cannot be touched by ordinary code, even running as root. You must be extremely careful why, how, and when you load a kernel extension to guard against being fooled into loading the wrong one. It’s possible to load a root kit if you’re notsufficiently careful. (A root kit is malicious code that, by running in the kernel, can not only take over control of the system but can cover up all evidence of its own existence.) To make sure that an attacker hasn’t somehow substituted his or her own kernel extension for yours, you should always store kernel extensions in secure locations. You may, if desired, use code signing or hashes to further verify their authenticity, but this does not remove the need to protect the extension with appropriate permissions. (Time-of-check vs. time-of-use attacks are still possible.) Note that in recent versions of OS X, this is partially mitigated by the KEXT loading system, which refuses to load any kext binary whose owner is not root or whose group is not wheel. In general, you should avoid writing kernel extensions (see “Keep Out” in Kernel Programming Guide ). However, if you must use a kernel extension, use the facilities built into OS X to load your extension and be sure to load the extension from a separate privileged process. See “Elevating Privileges Safely” (page 59) to learn more about the safe use of root access. See Kernel Programming Guide for more information on writing and loading kernel extensions. For help on writing device drivers, see I/O Kit Fundamentals. Network Port Use This checklist is intended to help you find vulnerabilities related to sending and receiving information over a network. If your project does not contain any tool or application that sends or receives information over a network, skip to “Audit Logs” (page 91) (for servers) or “Integer and Buffer Overflows” (page 97) for all other products. 1. Use assigned port numbers. Security Development Checklists Network Port Use 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 89Port numbers 0 through 1023 are reserved for use by certain services specified by the Internet Assigned Numbers Authority (IANA; see http://www.iana.org/). On many systems including OS X, only processes running asroot can bind to these ports. It is notsafe, however, to assume that any communications coming over these privileged ports can be trusted. It’s possible that an attacker has obtained root access and used it to bind to a privileged port. Furthermore, on some systems, root access is not needed to bind to these ports. You should also be aware that if you use the SO_REUSEADDR socket option with UDP, it is possible for a local attacker to hijack your port. Therefore, you should always use port numbers assigned by the IANA, you should always check return codes to make sure you have connected successfully, and you should check that you are connected to the correct port. Also, as always, never trust input data, even if it’s coming over a privileged port. Whether data is being read from a file, entered by a user, or received over a network, you must validate all input. See “Validating Input And Interprocess Communication” (page 33) for more information about validating input. 2. Choose an appropriate transport protocol. Lower-level protocols, such as UDP, provide higher performance for some types of traffic, but are easier to spoof than higher-level protocols, such as TCP. Note that if you’re using TCP, you still need to worry about authenticating both ends of the connection, but there are encryption layers you can add to increase security. 3. Use existing authentication services when authentication is needed. If you’re providing a free and nonconfidential service, and do not process user input, then authentication is not necessary. On the other hand, if any secret information is being exchanged, the user is allowed to enter data that your program processes, or there is any reason to restrict user access, then you should authenticate every user. OS X provides a variety of secure network APIs and authorization services, all of which perform authentication. You should always use these services rather than creating your own authentication mechanism. For one thing, authentication is very difficult to do correctly, and dangerous to get wrong. If an attacker breaks your authentication scheme, you could compromise secrets or give the attacker an entry to your system. The only approved authorization mechanism for networked applications is Kerberos; see “Client-Server Authentication” (page 93). For more information on secure networking, see Secure Transport Reference and CFNetwork Programming Guide . 4. Verify access programmatically. UI limitations do not protect your service from attack. If your service provides functionality that should only be accessible to certain users, that service must perform appropriate checks to determine whether the current user is authorized to access that functionality. Security Development Checklists Network Port Use 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 90If you do not do this, then someone sufficiently familiar with your service can potentially perform unauthorized operations by modifying URLs, sending malicious Apple events, and so on. 5. Fail gracefully. If a server is unavailable, either because of some problem with the network or because the server is under a denial of service attack, your client application should limit the frequency and number of retries and should give the user the opportunity to cancel the operation. Poorly-designed clientsthat retry connectionstoo frequently and too insistently, or that hang while waiting for a connection, can inadvertently contribute to—or cause their own—denial of service. 6. Design your service to handle high connection volume. Your daemon should be capable of surviving a denial of service attack without crashing or losing data. In addition, you should limit the total amount of processor time, memory, and disk space each daemon can use, so that a denial of service attack on any given daemon does not result in denial of service to every process on the system. You can use the ipfwfirewall program to control packets and traffic flow for internet daemons. For more information on ipfw, see the ipfw(8) manual page. See Wheeler, Secure Programming for Linux and Unix HOWTO, available at http://www.dwheeler.com/secure-programs/, for more advice on dealing with denial of service attacks. 7. Design hash functions carefully. Hash tables are often used to improve search performance. However, when there are hash collisions(where two items in the list have the same hash result), a slower (often linear) search must be used to resolve the conflict. If it is possible for a user to deliberately generate different requeststhat have the same hash result, by making many such requests an attacker can mount a denial of service attack. It is possible to design hash tables that use complex data structures such as trees in the collision case. Doing so can significantly reduce the damage caused by these attacks. Audit Logs It’s very important to audit attempts to connect to a server or to gain authorization to use a secure program. If someone is attempting to attack your program, you should know what they are doing and how they are doing it. Furthermore, if your program is attacked successfully, your audit log is the only way you can determine what happened and how extensive the security breach was. This checklist is intended to help you make sure you have an adequate logging mechanism in place. Security Development Checklists Audit Logs 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 91Important: Don’t log confidential data, such as passwords, which could then be read later by a malicious user. 1. Audit attempts to connect. Your daemon orsecure program should audit connection attempts(both successful attempts and failures). Note that an attacker can attempt to use the audit log itself to create a denial of service attack; therefore, you should limit the rate of entering audit messages and the total size of the log file. You also need to validate the input to the log itself, so that an attacker can’t enter special characters such as the newline character that you might misinterpret when reading the log. See Wheeler, Secure Programming for Linux and Unix HOWTO for some advice on audit logs. 2. Use the libbsm auditing library where possible. The libbsm auditing library is part of the TrustedBSD project, which in turn is a set of trusted extensions to the FreeBSD operating system. Apple has contributed to this project and has incorporated the audit library into the Darwin kernel of the OS X operating system. (This library is not available in iOS.) You can use the libbsm auditing library to implement auditing of your program for login and authorization attempts. This library gives you a lot of control over which events are audited and how to handle denial of service attacks. The libbsm project is located at http://www.opensource.apple.com/darwinsource/Current/bsm/. For documentation of the BSM service, see the “Auditing Topics” chapter in Sun Microsystems’ System Administration Guide: Security Services located at http://docs.sun.com/app/docs/doc/806- 4078/6jd6cjs67?a=view. 3. If you cannot use libbsm, be careful when writing audit trails. When using audit mechanisms other than libbsm, there are a number of pitfalls you should avoid, depending on what audit mechanism you are using: ● syslog Prior to the implementation of the libbsm auditing library, the standard C library function syslog was most commonly used to write data to a log file. If you are using syslog, consider switching to libbsm, which gives you more options to deal with denial of service attacks. If you want to stay with syslog, be sure your auditing code is resistant to denial of service attacks, as discussed in step 1. ● Custom log file If you have implemented your own custom logging service, consider switching to libbsm to avoid inadvertently creating a security vulnerability. In addition, if you use libbsm your code will be more easily maintainable and will benefit from future enhancements to the libbsm code. If you stick with your own custom logging service, you must make certain that it is resistant to denial of service attacks (see step 1) and that an attacker can’t tamper with the contents of the log file. Security Development Checklists Audit Logs 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 92Because your log file must be either encrypted or protected with access controlsto prevent tampering, you must also provide tools for reading and processing your log file. Finally, be sure your custom logging code is audited for security vulnerabilities. Client-Server Authentication If any private or secret information is passed between a daemon and a client process, both ends of the connection should be authenticated. This checklist is intended to help you determine whether your daemon’s authentication mechanism is safe and adequate. If you are not writing a daemon, skip to “Integer and Buffer Overflows” (page 97). 1. Do not store, validate, or modify passwords yourself. It’s a very bad idea to store, validate, or modify passwords yourself, as it’s very hard to do so securely, and OS X and iOS provide secure facilities for just that purpose. ● In OS X, you can use the keychain to store passwords and Authorization Services to create, modify, delete, and validate user passwords (see Keychain Services Programming Guide and Authorization Services Programming Guide ). ● In OS X, if you have access to an OS X Server setup, you can use Open Directory (see Open Directory Programming Guide ) to store passwords and authenticate users. ● On an iOS device, you can use the keychain to store passwords. iOS devices authenticate the application that is attempting to obtain a keychain item rather than asking the user for a password. By storing data in the keychain, you also ensure that they remain encrypted in any device backups. 2. Never send passwords over a network connection in cleartext form. You should never assume that an unencrypted network connection issecure. Information on an unencrypted network can be intercepted by any individual or organization between the client and the server. Even an intranet, which does not go outside of your company, is not secure. A large percentage of cyber crime is committed by company insiders, who can be assumed to have accessto a network inside a firewall. OS X provides APIs for secure network connections; see Secure Transport Reference and CFNetwork Programming Guide for details. 3. Use server authentication as an anti-spoofing measure. Although server authentication is optional in the SSL/TLS protocols, you should always do it. Otherwise, an attacker might spoof your server, injuring your users and damaging your reputation in the process. 4. Use reasonable pasword policies. ● Password strength Security Development Checklists Client-Server Authentication 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 93In general, it is better to provide the user with a meansto evaluate the strength of a proposed password rather than to require specific combinations of letters, numbers, or punctuation, as arbitrary rules tend to cause people to choose bad passwords to fit the standard (Firstname.123) instead of choosing good passwords. ● Password expiration Password expiration has pros and cons. If your service transmits passwords in cleartext form, it is absolutely essential. If your password transmission is considered secure, however, password expiration can actually weaken security by causing people to choose weaker passwords that they can remember or to write their passwords down on sticky notes on their monitors. See Password Expiration Considered Harmful for more information. ● Non-password authentication Hardware-token-based authentication providesfar more security than any password scheme because the correct response changes every time you use it. These tokens should always be combined with a PIN, and you should educate your users so that they do not write their username or PIN on the token itself. ● Disabled accounts When an employee leaves or a user closes an account, the accountshould be disabled so that it cannot be compromised by an attacker. The more active accounts you have, the greater the probability that one will have a weak password. ● Expired accounts Expiring unused accounts reduces the number of active accounts, and in so doing, reduces the risk of an old account getting compromised by someone stealing a password that the user has used for some other service. Note, however, that expiring a user account without warning the user first is generally a bad idea. If you do not have a means of contacting the user, expiring accounts are generally considered poor form. ● Changing passwords You can require that the client application support the ability to change passwords, or you can require that the user change the password using a web interface on the server itself. In either case, the user (or the client, on behalf of the user) must provide the previous password along with the new password (twice unless the client is updating it programmatically over a sufficiently robust channel). ● Lost password retrieval (such as a system that triggers the user’s memory or a series of questions designed to authenticate the user without a password) Security Development Checklists Client-Server Authentication 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 94Make sure your authentication method is not so insecure that an attacker doesn’t even bother to try a password, and be careful not to leak information, such as the correct length of the password, the email address to which the recovered password is sent, or whether the user ID is valid. You should always allow (and perhaps even require) customer to choose their own security questions. Pre-written questions are inherently dangerous because any question that is general enough for you to ask it of a large number of people is: ● likely to be a request for information that a large number of that person’s friends already know. In all likelihood, everyone who attended your high school can guess (in a handful of guesses) who your kindergarten teacher was, who your high school mascot was, and so on. ● probably on your public profile on a social networking site. For example, if you ask where you were born, chances are that’s public information. Even if it isn’t on your profile, someone can dig it up through government records. ● potentially guessable given other information about the person. For example, given the last four digits of a social security number, someone’s birthdate, and the city in which that person was born, you can fairly easily guess then entire social security number. Finally, you should always allow your users the option of not filing out security questions. The mere existence of security questions makes their accounts less secure, so security-conscious individuals should be allowed to refuse those questions entirely. ● Limitations on password length (adjustable by the system administrator) In general, you should require passwords to be at least eight characters in length. (As a side note, if yourserver limits passwordsto a maximum of eight characters, you need to rethink your design. There should be no maximum password length at all, if possible.) The more of these policies you enforce, the more secure your server will be. Rather than creating your own password database—which is difficult to do securely—you should use the Apple Password Server. See Open Directory Programming Guide for more information about the Password Server, Directory Service Framework Reference for a list of Directory Services functions, and the manual pages for pwpolicy(8), passwd(1), passwd(5), and getpwent(3) at http://developer.apple.com/documentation/Darwin/Reference/ManPages/index.html for tools to access the password database and set password policies. 5. Do not store unencrypted passwords and do not reissue passwords. In order to reissue a password, you first have to cache the unencrypted password, which is bad security practice. Furthermore, when you reissue a password, you might also be reusing that password in an inappropriate security context. For example, suppose your program is running on a web server, and you use SSL to communicate with clients. If you take a client’s password and use it to log into a database server to do something on the client’s behalf, there’s no way to guarantee that the database server keeps the password secure and does Security Development Checklists Client-Server Authentication 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 95not pass it on to another server in cleartext form. Therefore, even though the password was in a secure context when it was being sent to the web server over SSL, when the web server reissues it, it’s in an insecure context. If you want to spare your client the trouble of logging in separately to each server, you should use some kind of forwardable authentication, such as Kerberos. For more information on Apple’s implementation of Kerberos, see http://developer.apple.com/darwin/projects/kerberos/. Under no circumstances should you design a system in which system administrators or other employees can see users’ passwords. Your users are trusting you with passwords that they may use for other sites; therefore, it is extremely reckless to allow anyone else to see those passwords. Administrators should be allowed to reset passwords to new values, but should never be allowed to see the passwords that are already there. 6. Support Kerberos. Kerberos is the only authorization service available over a network for OS X servers, and it offers single-sign-on capabilities. If you are writing a server to run on OS X, you should support Kerberos. When you do: a. Be sure you’re using the latest version (v5). b. Use a service-specific principal, not a host principal. Each service that uses Kerberos should have its own principal so that compromise of one key does not compromise more than one service. If you use a host principal, anyone who has your host key can spoof login by anybody on the system. The only alternative to Kerberos is combining SSL/TLS authentication with some other means of authorization such as an access control list. 7. Restrict guest access appropriately. If you allow guest access, be sure that guests are restricted in what they can do, and that your user interface makes clear to the system administrator what guests can do. Guest access should be off by default. It’s best if the administrator can disable guest access. Also, as noted previously, be sure to limit what guests can do in the code that actually performs the operation, not just in the code that generates the user interface. Otherwise, someone with sufficient knowledge ofthe systemcan potentially performthose unauthorized operationsin other ways(bymodifying URLs, for example). 8. Do not implement your own directory service. Open Directory is the directory server provided by OS X for secure storage of passwords and user authentication. It is important that you use this service and not try to implement your own, as secure directory servers are difficult to implement and an entire directory’s passwords can be compromised if it’s done wrong. See Open Directory Programming Guide for more information. 9. Scrub (zero) user passwords from memory after validation. Security Development Checklists Client-Server Authentication 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 96Passwords must be kept in memory for the minimum amount of time possible and should be written over, not just released, when no longer needed. It is possible to read data out of memory even if the application no longer has pointers to it. Integer and Buffer Overflows As discussed in “Avoiding Buffer Overflows And Underflows” (page 17), buffer overflows are a major source of security vulnerabilities. This checklist is intended to help you identify and correct buffer overflows in your program. 1. Use unsigned values when calculating memory object offsets and sizes. Signed values make it easier for an attacker to cause a buffer overflow, creating a security vulnerability, especially if your application accepts signed values from user input or other outside sources. Be aware that data structures referenced in parameters might contain signed values. See “Avoiding Integer Overflows And Underflows” (page 27) and “Calculating Buffer Sizes” (page 25) for details. 2. Check for integer overflows (or signed integer underflows) when calculating memory object offsets and sizes. You must always check for integer overflows or underflows when calculating memory offsets or sizes. Integer overflows and underflows can corrupt memory in ways that can lead to execution of arbitrary code. See “Avoiding Integer Overflows And Underflows” (page 27) and “Calculating Buffer Sizes” (page 25) for details. 3. Avoid unsafe string-handling functions. The functions strcat, strcpy, strncat, strncpy, sprintf, vsprintf, gets have no built-in checks for string length, and can lead to buffer overflows. For alternatives, read “String Handling” (page 22). Cryptographic Function Use This checklist is intended to help you determine whether your program has any vulnerabilities related to use of encryption, cryptographic algorithms, or random number generation. 1. Use trusted random number generators. Do not attempt to generate your own random numbers. Security Development Checklists Integer and Buffer Overflows 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 97There are several ways to obtain high-quality random numbers: ● In iOS, use the Randomization Services programming interface. ● In OS X: ● Read from /dev/random in OS X (see the manual page for random). ● Use the read_random function in the header file random.h in the Apple CSP module, which is part of Apple’simplementation ofthe CDSA framework (available at http://developer.apple.com/darwin/projects/security/). Note that rand does not return good random numbers and should not be used. 2. Use TLS/SSL instead of custom schemes. You should always use accepted standard protocols for secure networking. These standards have gone through peer review and so are more likely to be secure. In addition, you should always use the most recent version of these protocols. To learn more about the secure networking protocols available in OS X and iOS, read “Secure Network Communication APIs” in Cryptographic Services Guide . 3. Don’t roll your own crypto algorithms. Always use existing optimized functions. It is very difficult to implement a secure cryptographic algorithm, and good, secure cryptographic functions are readily available. To learn about the cryptographic services available in OS X and iOS, read Cryptographic Services Guide . Installation and Loading Many security vulnerabilities are caused by problems with how programs are installed or code modules are loaded. This checklist is intended to help you find any such problems in your project. 1. Don’t install components in /Library/StartupItemsor/System/Library/Extensions. Code installed into these directories runs with root permissions. Therefore, it is very important that such programs be carefully audited forsecurity vulnerabilities(as discussed in this checklist) and that they have their permissions set correctly. For information on proper permissions for startup items, see “Startup Items”. (Note that in OS X v10.4 and later,startup items are deprecated; you should use launchd to launch your daemonsinstead. See Daemons and Services Programming Guide for more information.) For information on permissions for kernel extensions, see Kernel Extension Programming Topics. (Note that beginning in OS X v10.2, OS X checks for permissions problems and refuses to load extensions unless the permissions are correct.) Security Development Checklists Installation and Loading 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 982. Don’t use custom install scripts. Custom install scripts add unnecessary complexity and risk, so when possible, you should avoid them entirely. If you must use a custom install script, you should: ● If your installerscript runsin a shell, read and follow the advice in “Shell Script Security” in Shell Scripting Primer. ● Be sure that yourscript followsthe guidelinesin this checklist just asthe rest of your application does. In particular: ● Don’t write temporary files to globally writable directories. ● Don’t execute with higher privileges than necessary. In general, your script should execute with the same privileges the user has normally, and should do its work in the user’s directory on behalf of the user. ● Don’t execute with elevated privileges any longer than necessary. ● Set reasonable permissions on your installed app. For example, don’t give everyone read/write permission to files in the app bundle if only the owner needs such permission. ● Set your installer’s file code creation mask (umask) to restrict access to the files it creates (see “Securing File Operations” (page 47)). ● Check return codes, and if anything is wrong, log the problem and report the problem to the user through the user interface. For advice on writing installation code that needs to perform privileged operations, see Authorization Services Programming Guide . For more information about writing shell scripts, read Shell Scripting Primer. 3. Load plug-ins and libraries only from secure locations. An application should load plug-ins only from secure directories. If your application loads plug-ins from directories that are not restricted, then an attacker might be able to trick the user into downloading malicious code, which your application might then load and execute. Important: In code running with elevated privileges, directories writable by the user are not considered secure locations. Be aware that the dynamic link editor (dyld) might link in plugins, depending on the environment in which your code is running. If your code uses loadable bundles (CFBundle or NSBundle), then it is dynamically loading code and could potentially load bundles written by a malicious hacker. See Code Loading Programming Topics for more information about dynamically loaded code. Security Development Checklists Installation and Loading 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 99Use of External Tools and Libraries If your program includes or uses any command-line tools, you have to look for security vulnerabilities specific to the use of such tools. This checklist is intended to help you find and correct such vulnerabilities. 1. Execute tools safely. If you are using routines such as popen or system to send commands to the shell, and you are using input from the user or received over a network to construct the command, you should be aware that these routines do not validate their input. Consequently, a malicious user can pass shell metacharacters—such as an escape sequence or other special characters—in command line arguments. These metacharacters might cause the following text to be interpreted as a new command and executed. In addition, when calling functions such as execlp, execvp, popen, or system that use the PATH environment variable to search for executables, you should always specify a complete absolute path to any tool that you want to run. If you do not, a malicious attacker can potentially cause you to run a different tool using an environment variable attack. When possible, use execvP (which takes an explicit search path argument) or avoid these functions altogether. See Viega and McGraw, Building Secure Software , AddisonWesley, 2002, andWheeler, Secure Programming for Linux andUnixHOWTO, available at http://www.dwheeler.com/secure-programs/, formore information on problems with these and similar routines and for secure ways to execute shell commands. 2. Do not pass sensitive information on the command line. If your application executes command-line tools, keep in mind that your process environment is visible to other users (see man ps(1)). You must be careful not to pass sensitive information in an insecure manner. Instead, pass sensitive information to your tool through some other means such as: ● Pipe or standard input A password is safe while being passed through a pipe; however, you must be careful that the process sending the password obtains and stores it in a safe manner. ● Environment variables Environment variables can potentially be read by other processes and thus may not be secure. If you use environment variables, you must be careful to avoid passing them to any processes that your command-line tool or script might spawn. See “Shell Script Security” in Shell Scripting Primer for details. ● Shared memory Named and globally-shared memory segments can be read by other processes. See “Interprocess Communication And Networking” (page 40) for more information aboutsecure use ofshared memory. ● Temporary file Security Development Checklists Use of External Tools and Libraries 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 100Temporary files are safe only if kept in a directory to which only your program has access. See “Data, Configuration, and Temporary Files” (page 88), earlier in this chapter, for more information on temporary files. 3. Validate all arguments (including the name). Also, remember that anyone can execute a tool—it is not executable exclusively through your program. Because all command-line arguments, including the program name (argv(0)), are under the control of the user, your tool should validate every parameter (including the name, if the tool’s behavior depends on it). Kernel Security This checklist is intended to help you program safely in the kernel. Note: Coding in the kernel poses special security risks and is seldom necessary. See Coding in the Kernel for alternatives to writing kernel-level code. 1. Verify the authenticity of Mach-based services. Kernel-level code can work directly with the Mach component. A Mach port is an endpoint of a communication channel between a client who requests a service and a server that provides the service. Mach ports are unidirectional; a reply to a service request must use a second port. If you are using Mach ports for communication between processes, you should check to make sure you are contacting the correct process. Because Mach bootstrap ports can be inherited, it is important for servers and clients to authenticate each other. You can use audit trailers for this purpose. You should create an audit record for each security-related check your program performs. See “Audit Logs” (page 91), earlier in this chapter, for more information on audit records. 2. Verify the authenticity of other user-space services. If your kernel extension was designed to communicate with only a specific user-space daemon, you should check not only the name of the process, but also the owner and group to ensure that you are communicating with the correct process. 3. Handle buffers correctly. When copying data to and from user space, you must: a. Check the bounds of the data using unsigned arithmetic—just as you check all bounds (see “Integer and Buffer Overflows” (page 97), earlier in this chapter)—to avoid buffer overflows. b. Check for and handle misaligned buffers. c. Zero all pad data when copying to or from user-space memory. Security Development Checklists Kernel Security 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 101If you or the compiler adds padding to align a data structure in some way, you should zero the padding to make sure you are not adding spurious (or even malicious) data to the user-space buffer, and to make sure that you are not accidentally leaking sensitive information that may have been in that page of memory previously. 4. Limit the memory resources a user may request. If your code does not limit the memory resources a user may request, then a malicious user can mount a denial of service attack by requesting more memory than is available in the system. 5. Sanitize any kernel log messages. Kernel code often generates messages to the console for debugging purposes. If your code does this, be careful not to include any sensitive information in the messages. 6. Don’t log too much. The kernel logging service has a limited buffer size to thwart denial of service attacks against the kernel. This means that if your kernel code logs too frequently or too much, data can be dropped. If you need to log large quantities of data for debugging purposes, you should use a different mechanism, and you must disable that mechanism before deploying your kernel extension. If you do not, then your extension could become a denial-of-service attack vector. 7. Design hash functions carefully. Hash tables are often used to improve search performance. However, when there are hash collisions(where two items in the list have the same hash result), a slower (often linear) search must be used to resolve the conflict. If it is possible for a user to deliberately generate different requeststhat have the same hash result, by making many such requests an attacker can mount a denial of service attack. It is possible to design hash tables that use complex data structures such as trees in the collision case. Doing so can significantly reduce the damage caused by these attacks. Security Development Checklists Kernel Security 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 102This appendix provides secure coding guidelines for software to be bundled with Apple products. Insecure software can pose a risk to the overall security of users’ systems. Security issues can lead to negative publicity and end-user support problems for Apple and third parties. Respect Users’ Privacy Your bundled software may use the Internet to communicate with your servers or third party servers. If so, you should provide clear and concise information to the user about what information is sent or retrieved and the reason for sending or receiving it. Encryption should be used to protect the information while in transit. Servers should be authenticated before transferring information. Provide Upgrade Information Provide information on how to upgrade to the latest version. Consider implementing a “Check for updates…” feature. Customers expect (and should receive) security fixes that affect the software version they are running. You should have a way to communicate available security fixes to customers. If possible, you should use the Mac App Store for providing upgrades. The Mac App Store provides a single, standard interface for updating all of a user’s software. The Mac App Store also provides an expedited app review process for handling critical security fixes. Store Information in Appropriate Places Store user-specific information in the home directory, with appropriate file system permissions. Take special care when dealing with shared data or preferences. Follow the guidelines about file system permissions set forth in File System Programming Guide . 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 103 Third-Party Software Security GuidelinesTake care to avoid race conditions and information disclosure when using temporary files. If possible, use a user-specific temporary file directory. Avoid Requiring Elevated Privileges Do not require or encourage users to be logged in as an admin user to install or use your application. You should regularly test your application as a normal user to make sure that it works as expected. Implement Secure Development Practices Educate your developers on how to write secure code to avoid the most common classes of vulnerabilities: ● Buffer overflows ● Integer overflows ● Race conditions ● Format string vulnerabilities Pay special attention to code that: ● deals with potentially untrusted data, such as documents or URLs ● communicates over the network ● handles passwords or other sensitive information ● runs with elevated privileges such as root or in the kernel Use APIs appropriate for the task: ● Use APIs that take security into account in their design. ● Avoid low-level C code when possible (e.g. use NSString instead of C-strings). ● Use the security features of OS X to protect user data. Test for Security As appropriate for your product, use the following QA techniques to find potential security issues: Third-Party Software Security Guidelines Avoid Requiring Elevated Privileges 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 104● Test for invalid and unexpected data in addition to testing what is expected. (Use fuzzing tools, include unit tests that test for failure, and so on.) ● Static code analysis ● Code reviews and audits Helpful Resources The other chaptersin this document describe best practicesfor writing secure code, including more information on the topics referenced above. Security Overview and Cryptographic Services Guide contain detailed information on security functionality in OS X that developers can use. Third-Party Software Security Guidelines Helpful Resources 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 105This table describes the changes to Secure Coding Guide . Date Notes 2012-06-11 Made minor typographical fixes. 2012-02-16 Fixed minor errors throughout. 2012-01-09 Updated for OS X v10.7. 2010-02-12 Added security guidelines. Added article on validating input--including the dangers of loading insecurely stored archives--and added information about the iOS where relevant. 2008-05-23 New document that describes techniques to use and factors to consider to make your code more secure from attack. 2006-05-23 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 106 Document Revision HistoryAES encryption Abbreviation for Advanced Encryption Standard encryption. A Federal Information Processing Standard (FIPS), described in FIPS publication 197. AES has been adopted by the U.S. government for the protection of sensitive, non-classified information. attacker Someone deliberately trying to make a program or operating system do something that it’s not supposed to do, such as allowing the attacker to execute code or read private data. authentication The process by which a person or other entity (such as a server) proves that it is who (or what) it says it is. Compare with authorization. authorization The process by which an entity such as a user or a server gets the right to perform a privileged operation. (Authorization can also refer to the right itself, as in “Bob has the authorization to run that program.”) Authorization usually involves first authenticating the entity and then determining whether it has the appropriate privileges. See also authentication. buffer overflow The insertion of more data into a memory buffer than was reserved for the buffer, resulting in memory locations outside the buffer being overwritten. See also heap overflow and stack overflow. CDSA Abbreviation for Common Data Security Architecture. An open software standard for a security infrastructure that provides a wide array of security services, including fine-grained access permissions, authentication of users, encryption, and secure data storage. CDSA has a standard application programming interface, called CSSM. CERT Coordination Center A center of Internet security expertise, located at the Software Engineering Institute, a federally funded research and development center operated by Carnegie Mellon University. CERT is an acronym for Computer Emergency Readiness Team.) certificate See digital certificate. Common Criteria A standardized process and set of standards that can be used to evaluate the security of software products developed by the governments of the United States, Canada, the United Kingdom, France, Germany, and the Netherlands. cracker See attacker. CSSM Abbreviation for Common Security Services Manager. A public application programming interface for CDSA. CSSM also defines an interface for plug-ins that implement security services for a particular operating system and hardware environment. CVE Abbreviation for Common Vulnerabilities and Exposures. A dictionary of standard names for security vulnerabilities located at http://www.cve.mitre.org/. You can run an Internet search on the CVE number to read details about the vulnerability. 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 107 Glossarydigital certificate A collection of data used to verify the identity of the holder. OS X supports the X.509 standard for digital certificates. exploit A program or sample code that demonstrates how to take advantage of a vulnerability.) FileVault An OS X feature, configured through the Security system preference, that encrypts everything in on the root volume (or everything in the user’s home directory prior to OS X v10.7). hacker An expert programmer—generally one with the skill to create an exploit. Most hackers do not attack other programs, and some publish exploits with the intent of forcing software developers to fix vulnerabilities. See also script kiddie. heap A region of memory reserved for use by a program during execution. Data can be written to or read from any location on the heap, which grows upward (toward highermemory addresses). Compare with stack. heap overflow A buffer overflow in the heap. homographs Characters that look the same but have different Unicode values, such as the Roman character p and the Russian glyph that is pronounced like “r”. integer overflow A buffer overflow caused by entering a number that is too large for an integer data type. Kerberos An industry-standard protocol created by the Massachusetts Institute of Technology (MIT) to provide authentication over a network. keychain A database used in OS X to store encrypted passwords, private keys, and othersecrets. It is also used to store certificates and other non-secret information that is used in cryptography and authentication. Keychain Access utility An application that can be used to manipulate data in the keychain. Keychain Services A public API that can be used to manipulate data in the keychain. level of trust The confidence a user can have in the validity of a certificate. The level of trust for a certificate is used together with the trust policy to answer the question “Should I trust this certificate for this action?” nonrepudiation A process or technique making it impossible for a user to deny performing an operation (such as using a specific credit card number). Open Directory The directory server provided by OS X for secure storage of passwords and user authentication. permissions See privileges. phishing A social engineering technique in which an email or web page that spoofs one from a legitimate businessis used to trick a user into giving personal data and secrets (such as passwords) to someone who has malicious intent. policy database A database containing the set of rules the Security Server uses to determine authorization. privileged operation An operation that requires special rights or privileges. privileges The type of access to a file or directory (read, write, execute, traverse, and so forth) granted to a user or to a group. Glossary 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 108race condition The occurrence of two events out of sequence. root kit Malicious code that, by running in the kernel, can not only take over control of the system but can also cover up all evidence of its own existence. root privileges Having the unrestricted permission to perform any operation on the system. script kiddie Someone who uses published code (scripts) to attack software and computer systems. signal A message sent from one processto another in a UNIX-based operating system (such as OS X) social engineering As applied to security, tricking a user into giving up secrets or into giving access to a computer to an attacker. smart card A plastic card similar in size to a credit card that has memory and a microprocessor embedded in it. A smart card can store and process information, including passwords, certificates, and keys. stack A region of memory reserved for use by a specific program and used to control program flow. Data is put on the stack and removed in a last-in–first-out fashion. The stack grows downward (toward lower memory addresses). Compare with heap. stack overflow A buffer overflow on the stack. time of check–time of use (TOCTOU) A race condition in which an attacker creates, writes to, or alters a file between the time when a program checks the status of the file and when the program writes to it. trust policy A set of rules that specify the appropriate uses for a certificate that has a specific level of trust. For example, the trust policy for a browser might state that if a certificate has expired, the user should be prompted for permission before a secure session is opened with a web server. vulnerability A feature of the way a program was written—either a design flaw or a bug—that makes it possible for a hacker or script kiddie to attack the program. Glossary 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 109Symbols _unknown user 84 A access control 14 applications factoring 69 interfaces 73–78 arguments, command line 61, 101 argv(0) 61 attackers 8 audit logs 91 authentication 14, 90 authopen 65 Authorization Services 72 authorization granting 14 revoking 75 AuthorizationExecWithPrivilege 68 B buffer overflows 11, 17–29 calculating buffer sizes 25–26 checklist 97 detecting 28 integer arithmetic 27 strings 22 buffer overflows See also heap , stack 17 C certificates digital certificates 14 CFBundle 99 chflags 48 chmod 55 chown 55 close-on-exec flag 58 code insertion 37 command-line arguments 61, 101 command-line tools 100 configuration files 88 crackers 8 D default settings 73 denial of service 91 device ID 58 digital certificate identity 79 digital certificates 14 document organization 9 dyld 99 dynamic link editor 99 E elevated privileges 59, 86 encryption 15 environment variables 62, 88 F factoring applications 69 fchmod 55 fchown 55 file descriptor 50, 52 inheriting 58 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 110 Indexfile descriptors 61 file locations 75 file operations Carbon 55 Cocoa 51 insecure 13, 47–58 POSIX 50 file system, remotely mounted 57 files temporary 88 FileVault 75 firewall 91 fopen 55 format string attacks 34 FSFindFolder 50 fstat 55 fuzzing 39 G GID 64 group ID 64 guest access 96 GUI 88 H hackers 7 hard link 48 hash function 91, 102 heap 11 overflow 20, 22 I identity 79 input validation 12 input data structures 97 inappropriate 17 testing 28 to audit logs 92 types of 17 validating 19, 33–40, 100 insecure file operations 13, 47–58 installer 63 integer overflows 27 interface, user 76 ipfw 91 K Kerberos 96 kernel extensions 72, 89 kernel messages 102 kernel checklist 101 KEXT 72 L launchd 66, 87 least privilege, principle of 60 left bracket 57 libbsm 92 /Library/StartupItems 68 logs, audit 91 lstat 55 M Mach ports 101 mkstemp 53, 55 mktemp 55 N negative numbers 27 network ports 90 nobody user 84 NSBundle 99 NSTemporaryDirectory 51 Index 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 111O open 55 organization of document 9 P passwords 93 permissions 52 permissions See also privileges phishing 16, 78 plug-ins 99 policy database 69, 72 port numbers 90 ports, Mach 101 private key identity 79 privileges 14, 59–72 elevated 59, 86 level, changing 64 principle of least privilege 60 root 14 process limits 62 R race conditions 13, 43 interprocess communication 13 scripts 56 time of check–time of use 44–46 44–46 random numbers 97 references 10 remotely mounted file system 58 rm 48 root kit 89 root privileges 14 S script kiddies 8 scripts, avoiding race conditions 56 Security Objective-C API 79 setegid 65 seteuid 65 setgid 65 setregid 65 setreuid 65 setrlimit 62 setuid 65, 67 SFAuthorizationView 79 SFCertificatePanel 79 SFCertificateTrustPanel 79 SFCertificateView 79 SFChooseIdentityPanel 79 SFKeychainSavePanel 79 SFKeychainSettingsPanel 80 shell commands 100 signal handler 46 social engineering 16, 37, 78 stack 11 overflow 18–20 stat 55 statistics of threats and attacks 16 string-handling functions 22, 97 sudo 87 symbolic link 49 syslog 92 SystemStarter 68 T temporary files 50, 53, 88 and scripts 56 default location 50, 51 test 57 twos-complement arithmetic 27 U UID 64 Index 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 112unique 84 umask 52 URL commands 12, 36 user ID 64 user interface 76 V validating input 12, 33–40 W wildcard characters 89 X xinetd 68 Index 2012-06-11 | © 2012 Apple Inc. All Rights Reserved. 113Apple Inc. © 2012 Apple Inc. All rights reserved. No part of this publication may be reproduced, stored in a retrievalsystem, or transmitted, in any form or by any means, mechanical, electronic, photocopying, recording, or otherwise, without prior written permission of Apple Inc., with the following exceptions: Any person is hereby authorized to store documentation on a single computer for personal use only and to print copies of documentation for personal use provided that the documentation contains Apple’s copyright notice. No licenses, express or implied, are granted with respect to any of the technology described in this document. Apple retains all intellectual property rights associated with the technology described in this document. This document is intended to assist application developers to develop applications only for Apple-labeled computers. Apple Inc. 1 Infinite Loop Cupertino, CA 95014 408-996-1010 Apple, the Apple logo, Carbon, Cocoa, eMac, FileVault, iPhone, Keychain, Mac, Macintosh, Numbers, Objective-C, OS X, Pages, and Safari are trademarks of Apple Inc., registered in the U.S. and other countries. .Mac is a service mark of Apple Inc., registered in the U.S. and other countries. App Store and Mac App Store are service marks of Apple Inc. Java is a registered trademark of Oracle and/or its affiliates. Ping is a registered trademark of Karsten Manufacturing and is used in the U.S. under license. UNIX is a registered trademark of The Open Group. iOS is a trademark or registered trademark of Cisco in the U.S. and other countries and is used under license. Even though Apple has reviewed this document, APPLE MAKES NO WARRANTY OR REPRESENTATION, EITHER EXPRESS OR IMPLIED, WITH RESPECT TO THIS DOCUMENT, ITS QUALITY, ACCURACY, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.ASARESULT, THISDOCUMENT IS PROVIDED “AS IS,” AND YOU, THE READER, ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND ACCURACY. IN NO EVENT WILL APPLE BE LIABLE FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL,OR CONSEQUENTIAL DAMAGES RESULTING FROM ANY DEFECT OR INACCURACY IN THIS DOCUMENT, even if advised of the possibility of such damages. THE WARRANTY AND REMEDIES SET FORTH ABOVE ARE EXCLUSIVE AND IN LIEU OF ALL OTHERS, ORAL OR WRITTEN, EXPRESS OR IMPLIED. No Apple dealer, agent, or employee is authorized to make any modification, extension, or addition to this warranty. Some states do not allow the exclusion or limitation of implied warranties or liability for incidental or consequential damages, so the above limitation or exclusion may not apply to you. This warranty gives you specific legal rights, and you may also have other rights which vary from state to state. String Programming GuideContents Introduction to String Programming Guide for Cocoa 5 Who Should Read This Document 5 Organization of This Document 5 See Also 6 Strings 7 Creating and Converting String Objects 8 Creating Strings 8 NSString from C Strings and Data 8 Variable Strings 9 Strings to Present to the User 10 Combining and Extracting Strings 10 Getting C Strings 11 Conversion Summary 12 Formatting String Objects 13 Formatting Basics 13 Strings and Non-ASCII Characters 14 NSLog and NSLogv 14 String Format Specifiers 15 Format Specifiers 15 Platform Dependencies 17 Reading Strings From and Writing Strings To Files and URLs 19 Reading From Files and URLs 19 Reading data with a known encoding 19 Reading data with an unknown encoding 20 Writing to Files and URLs 21 Summary 21 Searching, Comparing, and Sorting Strings 22 Search and Comparison Methods 22 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 2Searching strings 22 Comparing and sorting strings 23 Search and Comparison Options 24 Examples 24 Case-Insensitive Search for Prefix and Suffix 24 Comparing Strings 25 Sorting strings like Finder 26 Paragraphs and Line Breaks 28 Line and Paragraph Separator Characters 28 Separating a String “by Paragraph” 28 Characters and Grapheme Clusters 30 Character Sets 33 Character Set Basics 33 Creating Character Sets 33 Performance considerations 34 Creating a character set file 35 Standard Character Sets and Unicode Definitions 35 Scanners 36 Creating a Scanner 36 Using a Scanner 36 Example 38 Localization 39 String Representations of File Paths 40 Representing a Path 40 User Directories 41 Path Components 42 File Name Completion 43 Drawing Strings 44 Document Revision History 45 Index 47 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 3Tables String Format Specifiers 15 Table 1 Format specifiers supported by the NSString formatting methods and CFString formatting functions 15 Table 2 Length modifiers supported by the NSString formatting methods and CFString formatting functions 16 Table 3 Format specifiers for data types 17 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 4String Programming Guide for Cocoa describes how to create, search, concatenate, and draw strings. It also describes character sets, which let you search a string for characters in a group, and scanners, which convert numbers to strings and vice versa. Who Should Read This Document You should read this document if you need to work directly with strings or character sets. Organization of This Document This document contains the following articles: ● “Strings” (page 7) describes the characteristics of string objects in Cocoa. ● “Creating and Converting String Objects” (page 8) explains the ways in which NSString and its subclass NSMutableString create string objects and convert their contents to and from the various character encodings they support. ● “Formatting String Objects” (page 13) describes how to format NSString objects. ● “String Format Specifiers” (page 15) describes printf-style format specifiers supported by NSString. ● “Reading Strings From and Writing Strings To Files and URLs” (page 19) describes how to read strings from and write strings to files and URLs. ● “Searching, Comparing, and Sorting Strings” (page 22) describes methods for finding characters and substrings within strings and for comparing one string to another. ● “Paragraphs and Line Breaks” (page 28) describes how paragraphs and line breaks are represented. ● “Characters and Grapheme Clusters” (page 30) describes how you can break strings down into user-perceived characters. ● “Character Sets” (page 33) explains how to use character set objects, and how to use NSCharacterSet methods to create standard and custom character sets. ● “Scanners” (page 36) describes NSScanner objects, which interpret and convert the characters of an NSString object into number and string values. 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 5 Introduction to String Programming Guide for Cocoa● “String Representations of File Paths” (page 40) describes the NSString methods that manipulate strings as file-system paths. ● “Drawing Strings” (page 44) discusses the methods of the NSString class that support drawing directly in an NSView object. See Also For more information, refer to the following documents: ● Attributed String Programming Guide is closely related to String Programming Guide for Cocoa . It provides information about NSAttributedString objects, which manage sets of attributes, such as font and kerning, that are associated with character strings or individual characters. ● Data Formatting Guide describes how to format data using objects that create, interpret, and validate text. ● Internationalization Programming Topics provides information about localizing strings in your project, including information on how string formatting arguments can be ordered. ● String Programming Guide for Core Foundation in Core Foundation, discussesthe Core Foundation opaque type CFString, which is toll-free bridged with the NSString class. Introduction to String Programming Guide for Cocoa See Also 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 6String objects represent character strings in Cocoa frameworks. Representing strings as objects allows you to use strings wherever you use other objects. It also providesthe benefits of encapsulation,so thatstring objects can use whatever encoding and storage is needed for efficiency while simply appearing as arrays of characters. A string object is implemented as an array of Unicode characters (in other words, a text string). An immutable string is a text string that is defined when it is created and subsequently cannot be changed. To create and manage an immutable string, use the NSString class. To construct and manage a string that can be changed after it has been created, use NSMutableString. The objects you create using NSString and NSMutableString are referred to as string objects (or, when no confusion will result, merely as strings). The term C string refers to the standard C char * type. A string object presents itself as an array of Unicode characters. You can determine how many characters it contains with the length method and can retrieve a specific character with the characterAtIndex: method. These two “primitive” methods provide basic access to a string object. Most use of strings, however, is at a higher level, with the strings being treated as single entities: You compare strings against one another, search them for substrings, combine them into new strings, and so on. If you need to access string objects character-by-character, you must understand the Unicode character encoding—specifically, issues related to composed character sequences. For details see: ● The Unicode Standard, Version 4.0 . The Unicode Consortium. Boston: Addison-Wesley, 2003. ISBN 0-321-18578-1. ● The Unicode Consortium web site: http://www.unicode.org/. 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 7 StringsNSString and its subclass NSMutableString provide several ways to create string objects, most based around the various character encodingsitsupports. Although string objects always present their own contents as Unicode characters, they can convert their contents to and from many other encodings, such as 7-bit ASCII, ISO Latin 1, EUC, and Shift-JIS. The availableStringEncodings class method returns the encodings supported. You can specify an encoding explicitly when converting a C string to or from a string object, or use the default C string encoding, which varies from platform to platform and is returned by the defaultCStringEncoding class method. Creating Strings The simplest way to create a string object in source code is to use the Objective-C @"..." construct: NSString *temp = @"Contrafibularity"; Note that, when creating a string constant in this fashion, you should use UTF-8 characters. Such an object is created at compile time and exists throughout your program’s execution. The compiler makes such object constants unique on a per-module basis, and they’re never deallocated. You can also send messages directly to a string constant as you do any other string: BOOL same = [@"comparison" isEqualToString:myString]; NSString from C Strings and Data To create an NSString object from a C string, you use methods such as initWithCString:encoding:. You must correctly specify the character encoding of the C string. Similar methods allow you to create string objects from characters in a variety of encodings. The method initWithData:encoding: allows you to convert string data stored in an NSData object into an NSString object. char *utf8String = /* Assume this exists. */ ; NSString *stringFromUTFString = [[NSString alloc] initWithUTF8String:utf8String]; 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 8 Creating and Converting String Objectschar *macOSRomanEncodedString = /* assume this exists */ ; NSString *stringFromMORString = [[NSString alloc] initWithCString:macOSRomanEncodedString encoding:NSMacOSRomanStringEncoding]; NSData *shiftJISData = /* assume this exists */ ; NSString *stringFromShiftJISData = [[NSString alloc] initWithData:shiftJISData encoding:NSShiftJISStringEncoding]; The following example converts an NSString object containing a UTF-8 character to ASCII data then back to an NSString object. unichar ellipsis = 0x2026; NSString *theString = [NSString stringWithFormat:@"To be continued%C", ellipsis]; NSData *asciiData = [theString dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]; NSString *asciiString = [[NSString alloc] initWithData:asciiData encoding:NSASCIIStringEncoding]; NSLog(@"Original: %@ (length %d)", theString, [theString length]); NSLog(@"Converted: %@ (length %d)", asciiString, [asciiString length]); // output: // Original: To be continued… (length 16) // Converted: To be continued... (length 18) Variable Strings To create a variable string, you typically use stringWithFormat:: or initWithFormat: (or for localized strings, localizedStringWithFormat:). These methods and theirsiblings use a formatstring as a template into which the values you provide (string and other objects, numerics values, and so on) are inserted. They and the supported format specifiers are described in “Formatting String Objects” (page 13). Creating and Converting String Objects Creating Strings 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 9You can build a string from existing string objects using the methods stringByAppendingString: and stringByAppendingFormat: to create a new string by adding one string after another, in the second case using a format string. NSString *hString = @"Hello"; NSString *hwString = [hString stringByAppendingString:@", world!"]; Strings to Present to the User When creating strings to present to the user, you should consider the importance of localizing your application. In general, you should avoid creating user-visible strings directly in code. Instead you should use strings in your code as a key to a localization dictionary that will supply the user-visible string in the user's preferred language. Typically thisinvolves using NSLocalizedString and similar macros, asillustrated in the following example. NSString *greeting = NSLocalizedStringFromTable (@"Hello", @"greeting to present in first launch panel", @"greetings"); For more about internationalizing your application, see Internationalization Programming Topics. “Localizing String Resources” describes how to work with and reorder variable arguments in localized strings. Combining and Extracting Strings You can combine and extract strings in various ways. The simplest way to combine two strings is to append one to the other. The stringByAppendingString: method returns a string object formed from the receiver and the given argument. NSString *beginning = @"beginning"; NSString *alphaAndOmega = [beginning stringByAppendingString:@" and end"]; // alphaAndOmega is @"beginning and end" You can also combine several strings according to a template with the initWithFormat:, stringWithFormat:, and stringByAppendingFormat: methods; these are described in more detail in “Formatting String Objects” (page 13). Creating and Converting String Objects Combining and Extracting Strings 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 10You can extract substrings from the beginning or end of a string to a particular index, or from a specific range, with the substringToIndex:, substringFromIndex:, and substringWithRange: methods. You can also split a string into substrings (based on a separator string) with the componentsSeparatedByString: method. These methods are illustrated in the following examples—notice that the index of the index-based methods starts at 0: NSString *source = @"0123456789"; NSString *firstFour = [source substringToIndex:4]; // firstFour is @"0123" NSString *allButFirstThree = [source substringFromIndex:3]; // allButFirstThree is @"3456789" NSRange twoToSixRange = NSMakeRange(2, 4); NSString *twoToSix = [source substringWithRange:twoToSixRange]; // twoToSix is @"2345" NSArray *split = [source componentsSeparatedByString:@"45"]; // split contains { @"0123", @"6789" } If you need to extract strings using pattern-matching rather than an index, you should use a scanner—see “Scanners” (page 36). Getting C Strings To get a C string from a string object, you are recommended to use UTF8String. This returns a const char * using UTF8 string encoding. const char *cString = [@"Hello, world" UTF8String]; The C string you receive is owned by a temporary object, and will become invalid when automatic deallocation takes place. If you want to get a permanent C string, you must create a buffer and copy the contents of the const char * returned by the method. Similar methods allow you to create string objects from characters in the Unicode encoding or an arbitrary encoding, and to extract data in these encodings. initWithData:encoding: and dataUsingEncoding: perform these conversions from and to NSData objects. Creating and Converting String Objects Getting C Strings 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 11Conversion Summary This table summarizes the most common means of creating and converting string objects: Source Creation method Extraction method In code @"..." compiler construct N/A UTF8 encoding stringWithUTF8String: UTF8String getCharacters: getCharacters:range: Unicode encoding stringWithCharacters: length: Arbitrary encoding initWithData: encoding: dataUsingEncoding: stringByAppendingString: N/A stringByAppendingFormat: Existing strings localizedStringWithFormat: Use NSScanner initWithFormat: locale: Format string Localized strings NSLocalizedString and similar N/A Creating and Converting String Objects Conversion Summary 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 12This article describes how to create a string using a format string, how to use non-ASCII characters in a format string, and a common error that developers make when using NSLog or NSLogv. Formatting Basics NSString uses a format string whose syntax is similar to that used by other formatter objects. It supports the format characters defined for the ANSI C function printf(), plus %@ for any object (see “String Format Specifiers” (page 15) and the IEEE printf specification). If the object responds to descriptionWithLocale: messages, NSString sends such a message to retrieve the text representation. Otherwise, it sends a description message. “Localizing String Resources” describes how to work with and reorder variable arguments in localized strings. In formatstrings, a ‘%’ character announces a placeholder for a value, with the charactersthat follow determining the kind of value expected and how to format it. For example, a format string of "%d houses" expects an integer value to be substituted for the format expression '%d'. NSString supportsthe format characters defined for the ANSI C functionprintf(), plus ‘@’ for any object. If the object responds to the descriptionWithLocale: message, NSString sends that message to retrieve the text representation, otherwise, it sends a description message. Value formatting is affected by the user’s current locale, which is an NSDictionary object that specifies number, date, and other kinds of formats. NSString uses only the locale’s definition for the decimal separator (given by the key named NSDecimalSeparator). If you use a method that doesn’t specify a locale, the string assumes the default locale. You can use NSString’s stringWithFormat: method and other related methods to create strings with printf-style formatspecifiers and argument lists, as described in “Creating and Converting StringObjects” (page 8). The examples below illustrate how you can create a string using a variety of formatspecifiers and arguments. NSString *string1 = [NSString stringWithFormat:@"A string: %@, a float: %1.2f", @"string", 31415.9265]; // string1 is "A string: string, a float: 31415.93" NSNumber *number = @1234; 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 13 Formatting String ObjectsNSDictionary *dictionary = @{ [NSDate date]:@"date" }; NSString *baseString = @"Base string."; NSString *string2 = [baseString stringByAppendingFormat: @" A number: %@, a dictionary: %@", number, dictionary]; // string2 is "Base string. A number: 1234, a dictionary: {date = 2005-10-17 09:02:01 -0700; }" Strings and Non-ASCII Characters You can include non-ASCII characters(including Unicode) in strings usingmethodssuch as stringWithFormat: and stringWithUTF8String:. NSString *s = [NSString stringWithFormat:@"Long %C dash", 0x2014]; Since \xe2\x80\x94 is the 3-byte UTF-8 string for 0x2014, you could also write: NSString *s = [NSString stringWithUTF8String:"Long \xe2\x80\x94 dash"]; NSLog and NSLogv The utility functions NSLog() and NSLogv() use the NSString string formatting servicesto log error messages. Note that as a consequence of this, you should take care when specifying the argument for these functions. A common mistake isto specify a string that includesformatting characters, asshown in the following example. NSString *string = @"A contrived string %@"; NSLog(string); // The application will probably crash here due to signal 10 (SIGBUS) It is better (safer) to use a format string to output another string, as shown in the following example. NSString *string = @"A contrived string %@"; NSLog(@"%@", string); // Output: A contrived string %@ Formatting String Objects Strings and Non-ASCII Characters 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 14This article summarizes the format specifiers supported by string formatting methods and functions. Format Specifiers The format specifiers supported by the NSString formatting methods and CFString formatting functions follow the IEEE printf specification; the specifiers are summarized in Table 1 (page 15). Note that you can also use the “n$” positional specifiers such as %1$@ %2$s. For more details, see the IEEE printf specification. You can also use these format specifiers with the NSLog function. Table 1 Format specifiers supported by the NSString formatting methods and CFString formatting functions Specifier Description Objective-C object, printed as the string returned by descriptionWithLocale: if available, or description otherwise. Also works with CFTypeRef objects, returning the result of the CFCopyDescription function. %@ %% '%' character. %d, %D Signed 32-bit integer (int). %u, %U Unsigned 32-bit integer (unsigned int). Unsigned 32-bit integer (unsigned int), printed in hexadecimal using the digits 0–9 and lowercase a–f. %x Unsigned 32-bit integer (unsigned int), printed in hexadecimal using the digits 0–9 and uppercase A–F. %X %o, %O Unsigned 32-bit integer (unsigned int), printed in octal. %f 64-bit floating-point number (double). 64-bit floating-point number (double), printed in scientific notation using a lowercase e to introduce the exponent. %e 64-bit floating-point number (double), printed in scientific notation using an uppercase E to introduce the exponent. %E 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 15 String Format SpecifiersSpecifier Description 64-bit floating-point number (double), printed in the style of %e if the exponent is less than –4 or greater than or equal to the precision, in the style of %f otherwise. %g 64-bit floating-point number (double), printed in the style of %E if the exponent is less than –4 or greater than or equal to the precision, in the style of %f otherwise. %G 8-bit unsigned character (unsigned char), printed by NSLog() as an ASCII character, or, if not an ASCII character, in the octal format \\ddd or the Unicode hexadecimal format \\udddd, where d is a digit. %c 16-bit Unicode character (unichar), printed by NSLog() as an ASCII character, or, if not an ASCII character, in the octal format \\ddd or the Unicode hexadecimal format \\udddd, where d is a digit. %C Null-terminated array of 8-bit unsigned characters. Because the %s specifier causes the characters to be interpreted in the system default encoding, the results can be variable, especially with right-to-left languages. For example, with RTL, %s inserts direction markers when the characters are not strongly directional. For this reason, it’s best to avoid %s and specify encodings explicitly. %s %S Null-terminated array of 16-bit Unicode characters. Void pointer (void *), printed in hexadecimal with the digits 0–9 and lowercase a–f, with a leading 0x. %p 64-bit floating-point number (double), printed in scientific notation with a leading 0x and one hexadecimal digit before the decimal point using a lowercase p to introduce the exponent. %a 64-bit floating-point number (double), printed in scientific notation with a leading 0X and one hexadecimal digit before the decimal point using a uppercase P to introduce the exponent. %A %F 64-bit floating-point number (double), printed in decimal notation. Table 2 Length modifiers supported by the NSString formatting methods and CFString formatting functions Length Description modifier Length modifier specifying that a following d, o, u, x, or X conversion specifier applies to a short or unsigned short argument. h Length modifier specifying that a following d, o, u, x, or X conversion specifier applies to a signed char or unsigned char argument. hh String Format Specifiers Format Specifiers 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 16Length Description modifier Length modifier specifying that a following d, o, u, x, or X conversion specifier applies to a long or unsigned long argument. l Length modifiers specifying that a following d, o, u, x, or X conversion specifier applies to a long long or unsigned long long argument. ll, q Length modifier specifying that a following a, A, e, E, f, F, g, or G conversion specifier applies to a long double argument. L Length modifier specifying that a following d, o, u, x, or X conversion specifier applies to a size_t or the corresponding signed integer type argument. z Length modifier specifying that a following d, o, u, x, or X conversion specifier applies to a ptrdiff_t or the corresponding unsigned integer type argument. t Length modifier specifying that a following d, o, u, x, or X conversion specifier applies to a intmax_t or uintmax_t argument. j Platform Dependencies OS X uses several data types—NSInteger, NSUInteger,CGFloat, and CFIndex—to provide a consistent means of representing values in 32- and 64-bit environments. In a 32-bit environment, NSInteger and NSUInteger are defined as int and unsigned int, respectively. In 64-bit environments, NSInteger and NSUInteger are defined as long and unsigned long, respectively. To avoid the need to use different printf-style type specifiers depending on the platform, you can use the specifiers shown in Table 3. Note that in some cases you may have to cast the value. Table 3 Format specifiers for data types Type Format specifier Considerations NSInteger %ld or %lx Cast the value to long. NSUInteger %lu or %lx Cast the value to unsigned long. %f works for floats and doubles when formatting; but note the technique described below for scanning. CGFloat %f or %g CFIndex %ld or %lx The same as NSInteger. %p adds 0x to the beginning of the output. If you don't want that, use %zx and no typecast. pointer %p or %zx String Format Specifiers Platform Dependencies 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 17The following example illustrates the use of %ld to format an NSInteger and the use of a cast. NSInteger i = 42; printf("%ld\n", (long)i); In addition to the considerations mentioned in Table 3, there is one extra case with scanning: you must distinguish the types for float and double. You should use %f for float, %lf for double. If you need to use scanf (or a variant thereof) with CGFloat, switch to double instead, and copy the double to CGFloat. CGFloat imageWidth; double tmp; sscanf (str, "%lf", &tmp); imageWidth = tmp; It is important to remember that %lf does not represent CGFloat correctly on either 32- or 64-bit platforms. This is unlike %ld, which works for long in all cases. String Format Specifiers Platform Dependencies 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 18Reading files or URLs using NSString is straightforward provided that you know what encoding the resource uses—if you don't know the encoding, reading a resource is more challenging. When you write to a file or URL, you must specify the encoding to use. (Where possible, you should use URLs because these are more efficient.) Reading From Files and URLs NSString provides a variety of methods to read data from files and URLs. In general, it is much easier to read data if you know its encoding. If you have plain text and no knowledge of the encoding, you are already in a difficult position. You should avoid placing yourself in this position if at all possible—anything that calls for the use of plain text files should specify the encoding (preferably UTF-8 or UTF-16+BOM). Reading data with a known encoding To read from a file or URL for which you know the encoding, you use stringWithContentsOfFile:encoding:error: or stringWithContentsOfURL:encoding:error:, or the corresponding init... method, as illustrated in the following example. NSURL *URL = ...; NSError *error; NSString *stringFromFileAtURL = [[NSString alloc] initWithContentsOfURL:URL encoding:NSUTF8StringEncoding error:&error]; if (stringFromFileAtURL == nil) { // an error occurred NSLog(@"Error reading file at %@\n%@", URL, [error localizedFailureReason]); // implementation continues ... You can also initialize a string using a data object, as illustrated in the following examples. Again, you must specify the correct encoding. 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 19 Reading Strings From and Writing Strings To Files and URLsNSURL *URL = ...; NSData *data = [NSData dataWithContentsOfURL:URL]; // Assuming data is in UTF8. NSString *string = [NSString stringWithUTF8String:[data bytes]]; // if data is in another encoding, for example ISO-8859-1 NSString *string = [[NSString alloc] initWithData:data encoding: NSISOLatin1StringEncoding]; Reading data with an unknown encoding If you find yourself with text of unknown encoding, it is best to make sure that there is a mechanism for correcting the inevitable errors. For example, Apple's Mail and Safari applications have encoding menus, and TextEdit allows the user to reopen the file with an explicitly specified encoding. If you are forced to guess the encoding (and note that in the absence of explicit information, it is a guess): 1. Try stringWithContentsOfFile:usedEncoding:error: or initWithContentsOfFile:usedEncoding:error: (or the URL-based equivalents). These methods try to determine the encoding of the resource, and if successful return by reference the encoding used. 2. If (1) fails, try to read the resource by specifying UTF-8 as the encoding. 3. If (2) fails, try an appropriate legacy encoding. "Appropriate" here depends a bit on circumstances; it might be the default C string encoding, it might be ISO or Windows Latin 1, or something else, depending on where your data are coming from. 4. Finally, you can try NSAttributedString's loading methods from the Application Kit (such as initWithURL:options:documentAttributes:error:). These methods attempt to load plain text files, and return the encoding used. They can be used on more-or-less arbitrary text documents, and are worth considering if your application has no special expertise in text. They might not be as appropriate for Foundation-level tools or documents that are not natural-language text. Reading Strings From and Writing Strings To Files and URLs Reading From Files and URLs 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 20Writing to Files and URLs Compared with reading data from a file or URL, writing isstraightforward—NSString providestwo convenient methods, writeToFile:atomically:encoding:error: and writeToURL:atomically:encoding:error:. You must specify the encoding that should be used, and choose whether to write the resource atomically or not. If you do not choose to write atomically, the string is written directly to the path you specify. If you choose to write it atomically, it is written first to an auxiliary file, and then the auxiliary file is renamed to the path. This option guarantees that the file, if it exists at all, won’t be corrupted even if the system should crash during writing. If you write to an URL, the atomicity option is ignored if the destination is not of a type that can be accessed atomically. NSURL *URL = ...; NSString *string = ...; NSError *error; BOOL ok = [string writeToURL:URL atomically:YES encoding:NSUnicodeStringEncoding error:&error]; if (!ok) { // an error occurred NSLog(@"Error writing file at %@\n%@", path, [error localizedFailureReason]); // implementation continues ... Summary This table summarizes the most common means of reading and writing string objects to and from files and URLs: Source Creation method Extraction method writeToURL: atomically:encoding: error: stringWithContentsOfURL: encoding:error: stringWithContentsOfURL: usedEncoding:error: URL contents writeToFile: atomically:encoding: error: stringWithContentsOfFile: encoding:error: stringWithContentsOfFile: usedEncoding:error: File contents Reading Strings From and Writing Strings To Files and URLs Writing to Files and URLs 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 21The string classes provide methods for finding characters and substrings within strings and for comparing one string to another. These methods conform to the Unicode standard for determining whether two character sequences are equivalent. The string classes provide comparison methods that handle composed character sequences properly, though you do have the option of specifying a literal search when efficiency is important and you can guarantee some canonical form for composed character sequences. Search and Comparison Methods The search and comparison methods each come in several variants. The simplest version of each searches or compares entire strings. Other variants allow you to alter the way comparison of composed charactersequences is performed and to specify a specific range of characters within a string to be searched or compared; you can also search and compare strings in the context of a given locale. These are the basic search and comparison methods: Search methods Comparison methods rangeOfString: compare: rangeOfString: options: compare:options: rangeOfString: options:range: compare:options: range: rangeOfString: options:range: locale: compare:options: range:locale: rangeOfCharacterFromSet: rangeOfCharacterFromSet: options: rangeOfCharacterFromSet: options:range: Searching strings You use the rangeOfString:... methods to search for a substring within the receiver. The rangeOfCharacterFromSet:... methodssearch for individual charactersfrom a supplied set of characters. 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 22 Searching, Comparing, and Sorting StringsSubstrings are found only if completely contained within the specified range. If you specify a range for a search or comparison method and don’t request NSLiteralSearch (see below), the range must not break composed character sequences on either end; if it does, you could get an incorrect result. (See the method description for rangeOfComposedCharacterSequenceAtIndex: for a code sample that adjusts a range to lie on character sequence boundaries.) You can also scan a string object for numeric and string values using an instance of NSScanner. For more about scanners, see “Scanners” (page 36). Both the NSString and the NSScanner class clusters use the NSCharacterSet class cluster forsearch operations. For more about charactersets,see “Character Sets” (page 33). If you simply want to determine whether a string contains a given pattern, you can use a predicate: BOOL match = [myPredicate evaluateWithObject:myString]; For more about predicates, see Predicate Programming Guide . Comparing and sorting strings The compare:... methods return the lexical ordering of the receiver and the supplied string. Several other methods allow you to determine whether two strings are equal or whether one isthe prefix orsuffix of another, but they don’t have variants that allow you to specify search options or ranges. The simplest method you can use to compare strings is compare:—this is the same as invoking compare:options:range: with no options and the receiver’s full extent as the range. If you want to specify comparison options(NSCaseInsensitiveSearch, NSLiteralSearch, or NSNumericSearch) you can use compare:options:; if you want to specify a locale you can use compare:options:range:locale:. NSString also provides various convenience methodsto allow you to perform common comparisons without the need to specify ranges and options directly, for example caseInsensitiveCompare: and localizedCompare:. Important: For user-visible sorted lists, you should always use localized comparisons. Thustypically instead of compare: or caseInsensitiveCompare: you should use localizedCompare: or localizedCaseInsensitiveCompare:. If you want to compare strings to order them in the same way as they’re presented in Finder, you should use compare:options:range:locale: with the user’s locale and the following options: NSCaseInsensitiveSearch, NSNumericSearch, NSWidthInsensitiveSearch, and NSForcedOrderingSearch. For an example, see “Sorting strings like Finder” (page 26). Searching, Comparing, and Sorting Strings Search and Comparison Methods 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 23Search and Comparison Options Several of the search and comparison methods take an “options” argument. This is a bit mask that adds further constraints to the operation. You create the mask by combining the following options (not all options are available for every method): Search option Effect NSCaseInsensitive- Ignores case distinctions among characters. Search Performs a byte-for-byte comparison. Differing literal sequences (such as composed character sequences) that would otherwise be considered equivalent are considered not to match. Using this option can speed some operations dramatically. NSLiteralSearch NSBackwardsSearch Performs searching from the end of the range toward the beginning. Performs searching only on characters at the beginning or end of the range. No match at the beginning or end means nothing is found, even if a matching sequence of characters occurs elsewhere in the string. NSAnchoredSearch When used with the compare:options: methods, groups of numbers are treated as a numeric value for the purpose of comparison. For example, Filename9.txt < Filename20.txt < Filename100.txt. NSNumericSearch Search and comparison are currently performed as if the NSLiteralSearch option were specified. Examples Case-Insensitive Search for Prefix and Suffix NSString provides the methods hasPrefix: and hasSuffix: that you can use to find an exact match for a prefix or suffix. The following example illustrates how you can use rangeOfString:options: with a combination of options to perform case insensitive searches. NSString *searchString = @"age"; NSString *beginsTest = @"Agencies"; NSRange prefixRange = [beginsTest rangeOfString:searchString Searching, Comparing, and Sorting Strings Search and Comparison Options 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 24options:(NSAnchoredSearch | NSCaseInsensitiveSearch)]; // prefixRange = {0, 3} NSString *endsTest = @"BRICOLAGE"; NSRange suffixRange = [endsTest rangeOfString:searchString options:(NSAnchoredSearch | NSCaseInsensitiveSearch | NSBackwardsSearch)]; // suffixRange = {6, 3} Comparing Strings The following examples illustrate the use of various string comparison methods and associated options. The first shows the simplest comparison method. NSString *string1 = @"string1"; NSString *string2 = @"string2"; NSComparisonResult result; result = [string1 compare:string2]; // result = -1 (NSOrderedAscending) You can compare strings numerically using the NSNumericSearch option: NSString *string10 = @"string10"; NSString *string2 = @"string2"; NSComparisonResult result; result = [string10 compare:string2]; // result = -1 (NSOrderedAscending) result = [string10 compare:string2 options:NSNumericSearch]; // result = 1 (NSOrderedDescending) You can use convenience methods (caseInsensitiveCompare: and localizedCaseInsensitiveCompare:) to perform case-insensitive comparisons: Searching, Comparing, and Sorting Strings Examples 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 25NSString *string_a = @"Aardvark"; NSString *string_A = @"AARDVARK"; result = [string_a compare:string_A]; // result = 1 (NSOrderedDescending) result = [string_a caseInsensitiveCompare:string_A]; // result = 0 (NSOrderedSame) // equivalent to [string_a compare:string_A options:NSCaseInsensitiveSearch] Sorting strings like Finder To sort strings the way Finder does in OS X v10.6 and later, use the localizedStandardCompare: method. It should be used whenever file names or other strings are presented in lists and tables where Finder-like sorting is appropriate. The exact behavior of this method is different under different localizations, so clients should not depend on the exact sorting order of the strings. The following example shows another implementation of similar functionality, comparing strings to order them in the same way as they’re presented in Finder, and it also shows how to sort the array of strings. First, define a sorting function that includes the relevant comparison options (for efficiency, pass the user's locale as the context—this way it's only looked up once). int finderSortWithLocale(id string1, id string2, void *locale) { static NSStringCompareOptions comparisonOptions = NSCaseInsensitiveSearch | NSNumericSearch | NSWidthInsensitiveSearch | NSForcedOrderingSearch; NSRange string1Range = NSMakeRange(0, [string1 length]); return [string1 compare:string2 options:comparisonOptions range:string1Range locale:(NSLocale *)locale]; } Searching, Comparing, and Sorting Strings Examples 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 26You pass the function as a parameter to sortedArrayUsingFunction:context: with the user’s current locale as the context: NSArray *stringsArray = @[@"string 1", @"String 21", @"string 12", @"String 11", @"String 02"]; NSArray *sortedArray = [stringsArray sortedArrayUsingFunction:finderSortWithLocale context:[NSLocale currentLocale]]; // sortedArray contains { "string 1", "String 02", "String 11", "string 12", "String 21" } Searching, Comparing, and Sorting Strings Examples 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 27This article describes how line and paragraph separators are defined and how you can separate a string by paragraph. Line and Paragraph Separator Characters There are a number of ways in which a line or paragraph break may be represented. Historically \n, \r, and \r\n have been used. Unicode defines an unambiguous paragraph separator, U+2029 (for which Cocoa provides the constant NSParagraphSeparatorCharacter), and an unambiguous line separator, U+2028 (for which Cocoa provides the constant NSLineSeparatorCharacter). In the Cocoa text system, the NSParagraphSeparatorCharacter is treated consistently as a paragraph break, and NSLineSeparatorCharacter is treated consistently as a line break that is not a paragraph break—that is, a line break within a paragraph. However, in other contexts, there are few guarantees as to how these characters will be treated. POSIX-level software, for example, often recognizes only \n as a break. Some older Macintosh software recognizes only \r, and some Windows software recognizes only \r\n. Often there is no distinction between line and paragraph breaks. Which line or paragraph break character you should use depends on how your data may be used and on what platforms. The Cocoa text system recognizes \n, \r, or \r\n all as paragraph breaks—equivalent to NSParagraphSeparatorCharacter.When it inserts paragraph breaks, for example with insertNewline:, it uses \n. Ordinarily NSLineSeparatorCharacter is used only for breaks that are specifically line breaks and not paragraph breaks, for example in insertLineBreak:, or for representing HTML
elements. If your breaks are specifically intended as line breaks and not paragraph breaks, then you should typically use NSLineSeparatorCharacter. Otherwise, you may use \n, \r, or \r\n depending on what other software is likely to process your text. The default choice for Cocoa is usually \n. Separating a String “by Paragraph” A common approach to separating a string “by paragraph” is simply to use: NSArray *arr = [myString componentsSeparatedByString:@"\n"]; 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 28 Paragraphs and Line BreaksThis, however, ignores the fact that there are a number of other ways in which a paragraph or line break may be represented in a string—\r, \r\n, or Unicode separators. Instead you can use methods—such as lineRangeForRange: or getParagraphStart:end:contentsEnd:forRange:—that take into account the variety of possible line terminations, as illustrated in the following example. NSString *string = /* assume this exists */; unsigned length = [string length]; unsigned paraStart = 0, paraEnd = 0, contentsEnd = 0; NSMutableArray *array = [NSMutableArray array]; NSRange currentRange; while (paraEnd < length) { [string getParagraphStart:¶Start end:¶End contentsEnd:&contentsEnd forRange:NSMakeRange(paraEnd, 0)]; currentRange = NSMakeRange(paraStart, contentsEnd - paraStart); [array addObject:[string substringWithRange:currentRange]]; } Paragraphs and Line Breaks Separating a String “by Paragraph” 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 29It's common to think of a string as a sequence of characters, but when working with NSString objects, or with Unicode strings in general, in most cases it is better to deal with substrings rather than with individual characters. The reason for this is that what the user perceives as a character in text may in many cases be represented by multiple characters in the string. NSString has a large inventory of methods for properly handling Unicode strings, which in general make Unicode compliance easy, but there are a few precautions you should observe. NSString objects are conceptually UTF-16 with platform endianness. That doesn't necessarily imply anything about their internalstorage mechanism; what it meansisthat NSString lengths, character indexes, and ranges are expressed in terms of UTF-16 units, and that the term “character” in NSString method names refers to 16-bit platform-endian UTF-16 units. This is a common convention for string objects. In most cases, clients don't need to be overly concerned with this; aslong as you are dealing with substrings, the precise interpretation of the range indexes is not necessarily significant. The vast majority of Unicode code points used for writing living languages are represented by single UTF-16 units. However, some less common Unicode code points are represented in UTF-16 by surrogate pairs. A surrogate pair is a sequence of two UTF-16 units, taken from specific reserved ranges, that together represent a single Unicode code point. CFString has functions for converting between surrogate pairs and the UTF-32 representation of the corresponding Unicode code point. When dealing with NSString objects, one constraint is that substring boundaries usually should not separate the two halves of a surrogate pair. This is generally automatic for rangesreturned from most Cocoa methods, but if you are constructing substring ranges yourself you should keep this in mind. However, this is not the only constraint you should consider. In many writing systems, a single character may be composed of a base letter plus an accent or other decoration. The number of possible letters and accents precludes Unicode from representing each combination as a single code point, so in general such combinations are represented by a base character followed by one or more combining marks. For compatibility reasons, Unicode does have single code points for a number of the most common combinations; these are referred to as precomposed forms, and Unicode normalization transformations can be used to convert between precomposed and decomposed representations. However, even if a string is fully precomposed, there are still many combinations that must be represented using a base character and combining marks. For most text processing, substring ranges should be arranged so that their boundaries do not separate a base character from its associated combining marks. 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 30 Characters and Grapheme ClustersIn addition, there are writing systems in which characters represent a combination of parts that are more complicated than accent marks. In Korean, for example, a single Hangul syllable can be composed of two or three subparts known as jamo. In the Indic and Indic-influenced writing systems common throughout South and Southeast Asia, single written characters often represent combinations of consonants, vowels, and marks such as viramas, and the Unicode representations of these writing systems often use code points for these individual parts,so that a single character may be composed of multiple code points. For most text processing, substring ranges should also be arranged so that their boundaries do not separate the jamo in a single Hangul syllable, or the components of an Indic consonant cluster. In general, these combinations—surrogate pairs, base characters plus combining marks, Hangul jamo, and Indic consonant clusters—are referred to as grapheme clusters. In order to take them into account, you can use NSString’s rangeOfComposedCharacterSequencesForRange: or rangeOfComposedCharacterSequenceAtIndex: methods, or CFStringGetRangeOfComposedCharactersAtIndex. These can be used to adjuststring indexes orsubstring ranges so that they fall on grapheme cluster boundaries, taking into account all of the constraints mentioned above. These methods should be the default choice for programmatically determining the boundaries of user-perceived characters.: In some cases, Unicode algorithms deal with multiple charactersin waysthat go beyond even grapheme cluster boundaries. Unicode casing algorithms may convert a single character into multiple characters when going from lowercase to uppercase; for example, the standard uppercase equivalent of the German character “ß” is the two-letter sequence “SS”. Localized collation algorithms in many languages consider multiple-character sequences as single units; for example, the sequence “ch” is treated as a single letter for sorting purposes in some European languages. In order to deal properly with cases like these, it is important to use standard NSString methods for such operations as casing, sorting, and searching, and to use them on the entire string to which they are to apply. Use NSString methods such as lowercaseString, uppercaseString, capitalizedString, compare: and its variants, rangeOfString: and its variants, and rangeOfCharacterFromSet: and its variants, or their CFString equivalents. These all take into account the complexities of Unicode string processing, and the searching and sorting methods in particular have many options to control the types of equivalences they are to recognize. In some less common cases, it may be necessary to tailor the definition of grapheme clusters to a particular need. The issues involved in determining and tailoring grapheme cluster boundaries are covered in detail in Unicode Standard Annex #29, which gives a number of examples and some algorithms. The Unicode standard in general is the best source for information about Unicode algorithms and the considerations involved in processing Unicode strings. If you are interested in grapheme cluster boundaries from the point of view of cursor movement and insertion point positioning, and you are using the Cocoa text system, you should know that on OS X v10.5 and later, NSLayoutManager has API support for determining insertion point positions within a line of text as it is laid Characters and Grapheme Clusters 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 31out. Note that insertion point boundaries are not identical to glyph boundaries; a ligature glyph in some cases, such as an “fi” ligature in Latin script, may require an internal insertion point on a user-perceived character boundary. See Cocoa Text Architecture Guide for more information. Characters and Grapheme Clusters 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 32An NSCharacterSet object represents a set of Unicode characters. NSString and NSScanner objects use NSCharacterSet objects to group characters together for searching operations, so that they can find any of a particular set of characters during a search. Character Set Basics A character set object represents a set of Unicode characters. Character sets are represented by instances of a class cluster. The cluster’s two public classes, NSCharacterSet and NSMutableCharacterSet, declare the programmatic interface for immutable and mutable character sets, respectively. An immutable character set is defined when it is created and subsequently cannot be changed. A mutable character set can be changed after it’s created. A character set object doesn’t perform any tasks; it simply holds a set of character values to limit operations on strings. The NSString and NSScanner classes define methods that take NSCharacterSet objects as argumentsto find any ofseveral characters. For example, this code excerpt findsthe range of the first uppercase letter in myString:. NSString *myString = @"some text in an NSString..."; NSCharacterSet *characterSet = [NSCharacterSet uppercaseLetterCharacterSet]; NSRange letterRange = [myString rangeOfCharacterFromSet:characterSet]; After this fragment executes, letterRange.location is equal to the index of the first “N” in “NSString” after rangeOfCharacterFromSet: isinvoked. If the first letter of the string were “S”, then letterRange.location would be 0. Creating Character Sets NSCharacterSet defines class methodsthat return commonly used charactersets,such asletters(uppercase or lowercase), decimal digits, whitespace, and so on. These “standard” character sets are always immutable, even if created by sending a message to NSMutableCharacterSet. See “Standard Character Sets and Unicode Definitions” (page 35) for more information on standard character sets. 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 33 Character SetsYou can use a standard character set as a starting point for building a custom set by making a mutable copy of it and changing that. (You can also start from scratch by creating a mutable character set with alloc and init and adding characters to it.) For example, this fragment creates a character set containing letters, digits, and basic punctuation: NSMutableCharacterSet *workingSet = [[NSCharacterSet alphanumericCharacterSet] mutableCopy]; [workingSet addCharactersInString:@";:,."]; NSCharacterSet *finalCharacterSet = [workingSet copy]; To define a custom character set using Unicode code points, use code similar to the following fragment (which creates a character set including the form feed and line separator characters): UniChar chars[] = {0x000C, 0x2028}; NSString *string = [[NSString alloc] initWithCharacters:chars length:sizeof(chars) / sizeof(UniChar)]; NSCharacterSet *characterSet = [NSCharacterSet characterSetWithCharactersInString:string]; Performance considerations Because character sets often participate in performance-critical code, you should be aware of the aspects of their use that can affect the performance of your application. Mutable character sets are generally much more expensive than immutable character sets. They consume more memory and are costly to invert (an operation often performed in scanning a string). Because of this, you should follow these guidelines: ● Create as few mutable character sets as possible. ● Cache character sets (in a global dictionary, perhaps) instead of continually recreating them. ● When creating a custom set that doesn’t need to change after creation, make an immutable copy of the final character set for actual use, and dispose of the working mutable character set. Alternatively, create a character set file as described in “Creating a character set file” (page 35) and store it in your application’s main bundle. ● Similarly, avoid archiving characterset objects;store them in characterset filesinstead. Archiving can result in a character set being duplicated in different archive files, resulting in wasted disk space and duplicates in memory for each separate archive read. Character Sets Performance considerations 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 34Creating a character set file If your application frequently uses a custom character set, you should save its definition in a resource file and load that instead of explicitly adding individual characters each time you need to create the set. You can save a character set by getting its bitmap representation (an NSData object) and saving that object to a file: NSData *charSetRep = [finalCharacterSet bitmapRepresentation]; NSURL *dataURL = <#URL for character set#>; NSError *error; BOOL result = [charSetRep writeToURL:dataURL options:NSDataWritingAtomic error:&error]; By convention, characterset filenames use the extension .bitmap. If you intend for othersto use your character set files, you should follow this convention. To read a character set file with a .bitmap extension, simply use the characterSetWithContentsOfFile: method. Standard Character Sets and Unicode Definitions The standard character sets, such as that returned by letterCharacterSet, are formally defined in terms of the normative and informative categories established by the Unicode standard, such as Uppercase Letter, Combining Mark, and so on. The formal definition of a standard character set is in most cases given as one or more of the categories defined in the standard. For example, the set returned by lowercaseLetterCharacterSet include all characters in normative category Lowercase Letters, while the set returned by letterCharacterSet includes the characters in all of the Letter categories. Note that the definitions of the categoriesthemselves may change with new versions of the Unicode standard. You can download the files that define category membership from http://www.unicode.org/. Character Sets Creating a character set file 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 35An NSScanner object scans the characters of an NSString object, typically interpreting the characters and converting them into number and string values. You assign the scanner’s string on creation, and the scanner progresses through the characters of that string from beginning to end as you request items. Creating a Scanner NSScanner is a class cluster with a single public class, NSScanner. Generally, you instantiate a scanner object by invoking the class method scannerWithString: or localizedScannerWithString:. Either method returns a scanner object initialized with the string you pass to it. The newly created scanner starts at the beginning of its string. You scan components using the scan... methods such as scanInt:, scanDouble:, and scanString:intoString:. If you are scanning multiple lines, you typically create a while loop that continues until the scanner is at the end of the string, as illustrated in the following code fragment: float aFloat; NSScanner *theScanner = [NSScanner scannerWithString:aString]; while ([theScanner isAtEnd] == NO) { [theScanner scanFloat:&aFloat]; // implementation continues... } You can configure a scanner to consider or ignore case using the setCaseSensitive: method. By default a scanner ignores case. Using a Scanner Scan operationsstart at the scan location and advance the scanner to just past the last character in the scanned value representation (if any). For example, after scanning an integer from the string “137 small cases of bananas”, a scanner’s location will be 3, indicating the space immediately after the number. Often you need to advance the scan location to skip characters in which you are not interested. You can change the implicit 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 36 Scannersscan location with the setScanLocation: method to skip ahead a certain number of characters (you can also use the method to rescan a portion of the string after an error). Typically, however, you either want to skip characters from a particular character set, scan past a specific string, or scan up to a specific string. You can configure a scanner to skip a set of characters with the setCharactersToBeSkipped: method. A scanner ignores characters to be skipped at the beginning of any scan operation. Once it finds a scannable character, however, it includes all characters matching the request. Scanners skip whitespace and newline characters by default. Note that case is always considered with regard to characters to be skipped. To skip all English vowels, for example, you must set the characters to be skipped to those in the string “AEIOUaeiou”. If you want to read content from the current location up to a particular string, you can use scanUpToString:intoString: (you can pass NULL as the second argument if you simply want to skip the intervening characters). For example, given the following string: 137 small cases of bananas you can find the type of container and number of containers using scanUpToString:intoString: asshown in the following example. NSString *bananas = @"137 small cases of bananas"; NSString *separatorString = @" of"; NSScanner *aScanner = [NSScanner scannerWithString:bananas]; NSInteger anInteger; [aScanner scanInteger:&anInteger]; NSString *container; [aScanner scanUpToString:separatorString intoString:&container]; It is important to note that the search string (separatorString) is " of". By default a scanner ignores whitespace, so the space character after the integer is ignored. Once the scanner begins to accumulate characters, however, all characters are added to the output string until the search string is reached. Thus if the search string is "of" (no space before), the first value of container is “small cases ” (includes the space following); if the search string is " of" (with a space before), the first value of container is “small cases” (no space following). Scanners Using a Scanner 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 37After scanning up to a given string, the scan location is the beginning of that string. If you want to scan past thatstring, you must therefore firstscan in the string you scanned up to. The following code fragment illustrates how to skip past the search string in the previous example and determine the type of product in the container. Note the use of substringFromIndex: to in effect scan up to the end of a string. [aScanner scanString:separatorString intoString:NULL]; NSString *product; product = [[aScanner string] substringFromIndex:[aScanner scanLocation]]; // could also use: // product = [bananas substringFromIndex:[aScanner scanLocation]]; Example Suppose you have a string containing lines such as: Product: Acme Potato Peeler; Cost: 0.98 73 Product: Chef Pierre Pasta Fork; Cost: 0.75 19 Product: Chef Pierre Colander; Cost: 1.27 2 The following example uses alternating scan operationsto extract the product names and costs(costs are read as a float forsimplicity’ssake),skipping the expected substrings“Product:” and “Cost:”, as well asthe semicolon. Note that because a scanner skips whitespace and newlines by default, the loop does no special processing for them (in particular there is no need to do additional whitespace processing to retrieve the final integer). NSString *string = @"Product: Acme Potato Peeler; Cost: 0.98 73\n\ Product: Chef Pierre Pasta Fork; Cost: 0.75 19\n\ Product: Chef Pierre Colander; Cost: 1.27 2\n"; NSCharacterSet *semicolonSet; NSScanner *theScanner; NSString *PRODUCT = @"Product:"; NSString *COST = @"Cost:"; NSString *productName; float productCost; Scanners Example 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 38NSInteger productSold; semicolonSet = [NSCharacterSet characterSetWithCharactersInString:@";"]; theScanner = [NSScanner scannerWithString:string]; while ([theScanner isAtEnd] == NO) { if ([theScanner scanString:PRODUCT intoString:NULL] && [theScanner scanUpToCharactersFromSet:semicolonSet intoString:&productName] && [theScanner scanString:@";" intoString:NULL] && [theScanner scanString:COST intoString:NULL] && [theScanner scanFloat:&productCost] && [theScanner scanInteger:&productSold]) { NSLog(@"Sales of %@: $%1.2f", productName, productCost * productSold); } } Localization A scanner bases some of its scanning behavior on a locale, which specifies a language and conventions for value representations. NSScanner uses only the locale’s definition for the decimal separator (given by the key named NSDecimalSeparator). You can create a scanner with the user’s locale by using localizedScannerWithString:, or set the locale explicitly using setLocale:. If you use a method that doesn’t specify a locale, the scanner assumes the default locale values. Scanners Localization 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 39NSString provides a rich set of methodsfor manipulating strings asfile-system paths. You can extract a path’s directory, filename, and extension, expand a tilde expression (such as “~me”) or create one for the user’s home directory, and clean up paths containing symbolic links, redundant slashes, and references to “.” (current directory) and “..” (parent directory). Note: Where possible, you should use instances of NSURL to represent paths—the operating system deals with URLs more efficiently than with string representations of paths. Representing a Path NSString represents paths generically with ‘/’ asthe path separator and ‘.’ asthe extension separator. Methods that accept strings as path arguments convert these generic representations to the proper system-specific form as needed. On systems with an implicit root directory, absolute paths begin with a path separator or with a tilde expression (“~/...” or “~user/...”). Where a device must be specified, you can do that yourself—introducing a system dependency—or allow the string object to add a default device. You can create a standardized representation of a path using stringByStandardizingPath. This performs a number of tasks including: ● Expansion of an initial tilde expression; ● Reduction of empty components and references to the current directory (“//” and “/./”) to single path separators; ● In absolute paths, resolution of references to the parent directory (“..”) to the real parent directory; for example: NSString *path = @"/usr/bin/./grep"; NSString *standardizedPath = [path stringByStandardizingPath]; // standardizedPath: /usr/bin/grep path = @"~me"; 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 40 String Representations of File PathsstandardizedPath = [path stringByStandardizingPath]; // standardizedPath (assuming conventional naming scheme): /Users/Me path = @"/usr/include/objc/.."; standardizedPath = [path stringByStandardizingPath]; // standardizedPath: /usr/include path = @"/private/usr/include"; standardizedPath = [path stringByStandardizingPath]; // standardizedPath: /usr/include User Directories The following examples illustrate how you can use NSString’s path utilities and other Cocoa functions to get the user directories. // Assuming that users’ home directories are stored in /Users NSString *meHome = [@"~me" stringByExpandingTildeInPath]; // meHome = @"/Users/me" NSString *mePublic = [@"~me/Public" stringByExpandingTildeInPath]; // mePublic = @"/Users/me/Public" You can find the home directory for the current user and for a given user with NSHomeDirectory and NSHomeDirectoryForUser respectively: NSString *currentUserHomeDirectory = NSHomeDirectory(); NSString *meHomeDirectory = NSHomeDirectoryForUser(@"me"); Note that you should typically use the function NSSearchPathForDirectoriesInDomains to locate standard directories for the current user. For example, instead of: NSString *documentsDirectory = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]; String Representations of File Paths User Directories 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 41you should use: NSString *documentsDirectory; NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); if ([paths count] > 0) { documentsDirectory = [paths objectAtIndex:0]; } Path Components NSString provides a rich set of methods for manipulating strings as file-system paths, for example: Interprets the receiver as a path and returns the receiver’s extension, if any. pathExtension Returns a new string made by deleting the extension (if any, and only the last) from the receiver. stringByDeletingPathExtension Returns a new string made by deleting the last path component from the receiver, along with any final path separator. stringByDeletingLastPathComponent Using these and related methods described in NSString Class Reference , you can extract a path’s directory, filename, and extension, as illustrated by the following examples. NSString *documentPath = @"~me/Public/Demo/readme.txt"; NSString *documentDirectory = [documentPath stringByDeletingLastPathComponent]; // documentDirectory = @"~me/Public/Demo" NSString *documentFilename = [documentPath lastPathComponent]; // documentFilename = @"readme.txt" NSString *documentExtension = [documentPath pathExtension]; // documentExtension = @"txt" String Representations of File Paths Path Components 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 42File Name Completion You can find possible expansions of file names using completePathIntoString:caseSensitive:matchesIntoArray:filterTypes:. For example, given a directory ~/Demo that contains the following files: ReadMe.txt readme.html readme.rtf recondite.txt test.txt you can find all possible completions for the path ~/Demo/r as follows: NSString *partialPath = @"~/Demo/r"; NSString *longestCompletion; NSArray *outputArray; unsigned allMatches = [partialPath completePathIntoString:&longestCompletion caseSensitive:NO matchesIntoArray:&outputArray filterTypes:NULL]; // allMatches = 3 // longestCompletion = @"~/Demo/re" // outputArray = (@"~/Demo/readme.html", "~/Demo/readme.rtf", "~/Demo/recondite.txt") You can find possible completions for the path ~/Demo/r that have an extension “.txt” or “.rtf” as follows: NSArray *filterTypes = @[@"txt", @"rtf"]; unsigned textMatches = [partialPath completePathIntoString:&outputName caseSensitive:NO matchesIntoArray:&outputArray filterTypes:filterTypes]; // allMatches = 2 // longestCompletion = @"~/Demo/re" // outputArray = (@"~/Demo/readme.rtf", @"~/Demo/recondite.txt") String Representations of File Paths File Name Completion 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 43You can draw string objects directly in a focused NSView using methods such as drawAtPoint:withAttributes: (to draw a string with multiple attributes, such as multiple text fonts, you must use an NSAttributedString object). These methods are described briefly in “Text” in Cocoa Drawing Guide . The simple methods, however, are designed for drawing small amounts of text or text that is only drawn rarely—they create and dispose of various supporting objects every time you call them. To draw strings repeatedly, it is more efficient to use NSLayoutManager, as described in “Drawing Strings”. For an overview of the Cocoa text system, of which NSLayoutManager is a part, see Cocoa Text Architecture Guide . 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 44 Drawing StringsThis table describes the changes to String Programming Guide . Date Notes 2012-07-17 Updated code snippets to adopt new Objective-C features. Corrected string constant character set to UTF-8. Added guidance about using localizedStandardCompare: for Finder-like sorting. Added caveat to avoid using %s with RTL languages. Revised "String Format Specifiers" article. 2012-06-11 2009-10-15 Added links to Cocoa Core Competencies. Added new aricle on character clusters; updated list of string format specifiers. 2008-10-15 2007-10-18 Corrected minor typographical errors. Added notes regarding NSInteger and NSUInteger to "String Format Specifiers". 2007-07-10 2007-03-06 Corrected minor typographical errors. 2007-02-08 Corrected sentence fragments and improved the example in "Scanners." 2006-12-05 Added code samples to illustrate searching and path manipulation. 2006-11-07 Made minor revisions to "Scanners" article. 2006-10-03 Added links to path manipulation methods. 2006-06-28 Corrected typographical errors. Added a new article, "Reading Strings From and Writing Strings To Files and URLs"; significantly updated "Creating and Converting Strings." 2006-05-23 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 45 Document Revision HistoryDate Notes Included “Creating a Character Set” into “Character Sets” (page 33). Changed title from "Strings" to conform to reference consistency guidelines. 2006-01-10 Added “Formatting String Objects” (page 13) article. Added Data Formatting and the Core Foundation Strings programming topics to the introduction. 2004-06-28 Added information about custom Unicode character sets and retrieved missing code fragments in “Creating a Character Set”. Added information and cross-reference to “Drawing Strings” (page 44). Rewrote introduction and added an index. 2004-02-06 Added NSNumericSearch description to “Searching, Comparing, and Sorting Strings” (page 22). 2003-09-09 2003-03-17 Reinstated the sample code that was missing from “Scanners” (page 36). Updated “Creating and Converting String Objects” (page 8) to recommend the use of UTF8 encoding, and noted the pending deprecation of the cString... methods. 2003-01-17 2002-11-12 Revision history was added to existing topic. Document Revision History 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 46A alloc method 34 archiving character set objects 34 ASCII character encoding converting string object contents 8 availableStringEncodings method 8 C C strings Cocoa string objects and 7 creating and converting 11 character encodings string manipulation and 8 character sets custom 34 example code 34 guidelines for use 34 mutable and immutable 33 saving to a file 35 standard 33, 35 characterAtIndex: method 7 characterSetWithContentsOfFile: method 35 compare: method 22 compare:options: method 22, 24 compare:options:range: method 22 comparing strings 22–23 comparison methods for strings 22 componentsSeparatedByString: method 11 current directories resolving references to 40 D dataUsingEncoding: method 11, 12 defaultCStringEncoding method 8 description method 13 descriptionWithLocale: method 13 directories manipulating strings as paths 40, 42 E encodings, character string manipulation and 8 EUC character encoding 8 F file-system paths and strings 42 format strings 13 G getCharacters:length: method 12 I init method for mutable character sets 34 initWithData:encoding: method 8, 11, 12 initWithFormat: method 10 initWithFormat:locale: method 12 ISO Latin 1 character encoding 8 L length method 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 47 Indexfor string objects 7 letterCharacterSet method 35 localization scanning strings and 39 value formatting and 13 localizedScannerWithString: method 36, 39 localizedStringWithFormat: method 9, 12 lowercaseLetterCharacterSet method 35 M myString: method 33 N NSCharacterSet class 33 NSLayoutManager class 44 NSMutableCharacterSet class 33 NSMutableString class 7, 8 NSScanner class 23, 36–38 NSString class creating string objects from 8 described 7 methods for representing file-system paths 40 scanners and 36 NSView class 44 P parent directories resolving references to 40 paths and strings 42 primitive methods of NSString 7 printf function NSString and 13 R rangeOfCharacterFromSet: method 22, 33 rangeOfCharacterFromSet:options: method 22 rangeOfCharacterFromSet:options:range: method 22 rangeOfComposedCharacterSequenceAtIndex: method 23 rangeOfString: method 22 rangeOfString:options: method 22 rangeOfString:options:range: method 22 S scan... methods 36 scanners 36, 38 instantiating 36 operation of 36 sample code 38 scannerWithString: method 36 scanUpToString:intoString: method 37 search methods for strings 22 setCaseSensitive: method 36 setCharactersToBeSkipped: method 37 setLocale: method 39 setScanLocation: method 37 Shift-JIS character encoding 8 standard character sets 33, 35 string objects combining and extracting 10 comparison methods 22 creating and converting 8–12 described 7 drawing 44 searching and comparing 22–23 stringByAppendingFormat: method 10, 12 stringByAppendingString: method 10, 12 stringWithCharacters:length: method 12 stringWithContentsOfFile: method 21 stringWithFormat: method 10 stringWithUTF8String: method 12 substringFromIndex: method 11 substringToIndex: method 11 Index 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 48substringWithRange: method 11 U Unicode characters in string objects 8 code points used to define character sets 34 in string objects 7 NSCharacterSet and 33 standard character sets 35 string comparison standard 22 UTF8 character encoding 11 UTF8String method 11, 12 V value formatting string conversion and 13 W writeToFile:atomically: method 21 Index 2012-07-17 | © 1997, 2012 Apple Inc. All Rights Reserved. 49Apple Inc. © 1997, 2012 Apple Inc. All rights reserved. No part of this publication may be reproduced, stored in a retrievalsystem, or transmitted, in any form or by any means, mechanical, electronic, photocopying, recording, or otherwise, without prior written permission of Apple Inc., with the following exceptions: Any person is hereby authorized to store documentation on a single computer for personal use only and to print copies of documentation for personal use provided that the documentation contains Apple’s copyright notice. No licenses, express or implied, are granted with respect to any of the technology described in this document. Apple retains all intellectual property rights associated with the technology described in this document. This document is intended to assist application developers to develop applications only for Apple-labeled computers. Apple Inc. 1 Infinite Loop Cupertino, CA 95014 408-996-1010 Apple, the Apple logo, Cocoa, Finder, Mac, Macintosh, Objective-C, OS X, and Safari are trademarks of Apple Inc., registered in the U.S. and other countries. Even though Apple has reviewed this document, APPLE MAKES NO WARRANTY OR REPRESENTATION, EITHER EXPRESS OR IMPLIED, WITH RESPECT TO THIS DOCUMENT, ITS QUALITY, ACCURACY, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.ASARESULT, THISDOCUMENT IS PROVIDED “AS IS,” AND YOU, THE READER, ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND ACCURACY. IN NO EVENT WILL APPLE BE LIABLE FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL,OR CONSEQUENTIAL DAMAGES RESULTING FROM ANY DEFECT OR INACCURACY IN THIS DOCUMENT, even if advised of the possibility of such damages. THE WARRANTY AND REMEDIES SET FORTH ABOVE ARE EXCLUSIVE AND IN LIEU OF ALL OTHERS, ORAL OR WRITTEN, EXPRESS OR IMPLIED. No Apple dealer, agent, or employee is authorized to make any modification, extension, or addition to this warranty. Some states do not allow the exclusion or limitation of implied warranties or liability for incidental or consequential damages, so the above limitation or exclusion may not apply to you. This warranty gives you specific legal rights, and you may also have other rights which vary from state to state. Apple AirPort Networks2 1 Contents Chapter 1 3 Getting Started 5 Configuring an Apple Wireless Device for Internet Access Using AirPort Utility 6 Extending the Range of Your AirPort Network 6 Sharing a USB Hard Disk Connected to an AirPort Extreme Base Station or Time Capsule 6 Printing with an Apple Wireless Device 6 Sharing Your Computer’s Internet Connection Chapter 2 9 AirPort Security 9 Security for AirPort Networks at Home 10 Security for AirPort Networks in Businesses and Classrooms 11 Wi-Fi Protected Access (WPA) and WPA2 Chapter 3 14 AirPort Network Designs 15 Using AirPort Utility 17 Setting Up the AirPort Extreme Network 24 Configuring and Sharing Internet Access 41 Setting Advanced Options 43 Extending the Range of an 802.11n Network 45 Keeping Your Network Secure 49 Directing Network Traffic to a Specific Computer on Your Network (Port Mapping) 51 Logging 52 Using Back to My Mac on your Wireless Network 53 Setting up IPv6 54 Sharing and Securing USB Hard Disks on Your Network 55 Using a Time Capsule in Your Network 55 Connecting a USB Printer to an Apple Wireless Device 56 Adding a Wireless Client to Your 802.11n Network 57 Solving Problems Chapter 4 59 Behind the Scenes 59 Basic Networking 63 Items That Can Cause Interference with AirPort Glossary 641 3 1 Getting Started AirPort offers the easiest way to provide wireless Internet access and networking anywhere in the home, classroom, or office. AirPort is based on the latest Institute of Electrical and Electronics Engineers (IEEE) 802.11n draft specification and provides fast and reliable wireless networking in the home, classroom, or small office. You can enjoy data transfer rates of up to five times faster than data rates provided by the 802.11g standard and more than twice the network range. The new AirPort Extreme Base Station and the new Time Capsule are based on simultaneous dual-band technology, so they work in both the 2.4 gigahertz (GHz) or 5 GHz spectrum at the same time. And they are 100 percent backward-compatible, so Mac computers and PCs that use 802.11a, 802.11b, 802.11g, or IEEE draft specification 802.11n wireless cards can connect to an AirPort wireless network. They also work flawlessly with the AirPort Express for wireless music streaming and more. The AirPort Extreme Base Station and Time Capsule have three additional 10/100/1000BaseT Gigabit Ethernet ports, so you don’t need to include another router in your network. To set up an AirPort Extreme Base Station, an AirPort Express, or a Time Capsule, you use AirPort Utility, the easy-to-use setup and management application. AirPort Utility has a simple user experience, with all software controls accessible from the same application. It provides better management of several Apple wireless devices, with client-monitoring features and logging. If you’re using AirPort Utility version 5.4 or later, you can set up a guest network, in both the 2.4 GHz and 5 GHz bands, so that guests can connect to the Internet using your AirPort network, while you keep your private network secure. You can also choose to set up guest accounts that expire, to grant temporary access to your network; you no longer need to give your network password to visitors in your home or office. You can even set up accounts with time constraints for the best in parental controls. AirPort Utility supports IPv6 and Bonjour, so you can “advertise” network services such as printing and sharing a hard disk over the Wide Area Network (WAN) port.4 Chapter 1 Getting Started Note: When the features discussed in this document apply to the AirPort Extreme Base Station, AirPort Express, and Time Capsule, the devices are referred to collectively as Apple wireless devices. With an AirPort Extreme Base Station or a Time Capsule, you can connect a USB hard disk so that everyone on the network can back up, store, and share files. Every Time Capsule includes an internal AirPort disk, so you don’t need to connect an external one. If you want, you can connect additional USB disks to the USB port on your Time Capsule. You can also connect a USB printer to the USB port on any Apple wireless device, so that everyone on the network can access the printer or hub. All Apple wireless devices provide strong, wireless security. They offer a built-in firewall and support industry-standard encryption technologies. Yet the simple setup utility and powerful access controls make it easy for authorized users to connect to the AirPort network they create. You can use an Apple wireless device to provide wireless Internet access and share a single Internet connection among several computers in the following ways:  Set up the device to act as a router and provide Internet Protocol (IP) addresses to computers on the network using Dynamic Host Configuration Protocol (DHCP) and Network Address Translation (NAT). When the wireless device is connected to a DSL or cable modem that is connected to the Internet, it receives webpages and email content from the Internet through its Internet connection, and then sends the content to wireless-enabled computers, using the wireless network or using Ethernet if there are computers connected to the Ethernet ports.  Set up the Apple wireless device to act as a bridge on an existing network that already has Internet access and a router providing IP addresses. The device passes IP addresses and the Internet connection to AirPort or wireless-enabled computers, or computers connected to the wireless device by Ethernet. This document provides information about the latest AirPort Extreme Base Station, AirPort Express, and Time Capsule, and detailed information about designing 802.11n networks with AirPort Utility for computers using Mac OS X v10.5 or later, and Windows Vista or Windows XP with Service Pack 2. If you’re using previous versions of Mac OS X, or are setting up earlier versions of AirPort devices, you’ll find more information at www.apple.com/support/airport.Chapter 1 Getting Started 5 You can set up an Apple wireless device and connect to the Internet wirelessly in minutes. But because Apple wireless devices are flexible and powerful networking products, you can also create an AirPort network that does much more. If you want to design an AirPort network that provides Internet access to non-AirPort computers via Ethernet, or take advantage of some of your wireless device’s more advanced features, use this document to design and implement your network. You can find more general wireless networking information and an overview of AirPort technology in the earlier AirPort documents, located at www.apple.com/support/manuals/airport. Note: The images of AirPort Utility in this document are from Mac OS X v10.5. If you’re using a Windows computer, the images you see in this document may be slightly different from what you see on your screen. Configuring an Apple Wireless Device for Internet Access Using AirPort Utility Like your computer, Apple wireless devices must be set up with the appropriate hardware and IP networking information to connect to the Internet. Install AirPort Utility, which came on the CD with your wireless device, and use it to provide Internet configuration information and other network settings. AirPort Utility combines the ease of use of AirPort Setup Assistant and the power of AirPort Admin Utility. It is installed in the Utilities folder in the Applications folder on a Macintosh computer using Mac OS X, and in Start > All Programs > AirPort on computers using Windows. AirPort Utility walks you through the setup process by asking a series of questions to determine how the device’s Internet connection and other interfaces should be set up. Enter the settings you received from your ISP or network administrator for Ethernet, PPP over Ethernet (PPPoE), or your local area network (LAN); give your AirPort network a name and password; set up a device as a wireless bridge to extend the range of your existing AirPort network; and set other options. When you’ve finished entering the settings, AirPort Utility transfers the settings to your wireless device. Then it connects to the Internet and shares its Internet connection with computers that join its AirPort network. You can also create an AirPort network that takes advantage of the more advanced networking features of Apple wireless devices. To set more advanced AirPort options, use AirPort Utility to manually set up your wireless device’s configuration, or make quick adjustments to one you’ve already set up. Some of the AirPort advanced networking features can be configured only using the manual setup features in AirPort Utility. 6 Chapter 1 Getting Started Set up your Apple wireless device manually using AirPort Utility when:  You want to provide Internet access to computers that connect to the wireless device using Ethernet  you’ve already set up your device, but you need to change one setting, such as your account information  You need to configure advanced settings such as channel frequency, advanced security options, closed networks, DHCP lease time, access control, WAN privacy, power controls, or port mapping or other options For instructions on using AirPort Utility to manually set up your wireless device and network, see “Using AirPort Utility” on page 15. Extending the Range of Your AirPort Network You can extend the range of your network by using AirPort Utility to set up wireless connections among several devices in your network, or to connect a device using Ethernet to create a roaming network. For more information on extending the range of your network, see “Connecting Additional Wireless Devices to Your AirPort Network” on page 41. Sharing a USB Hard Disk Connected to an AirPort Extreme Base Station or Time Capsule If you’re using an AirPort Extreme Base Station or a Time Capsule, you can connect a USB hard disk to it, and computers connected to the network—wired or wireless, Mac or Windows—can share files using the hard disk. Every Time Capsule includes an internal AirPort disk, so you don’t need to connect an external one. If you want, you can connect additional USB disks to the USB port on your Time Capsule. See “Sharing and Securing USB Hard Disks on Your Network” on page 54. Printing with an Apple Wireless Device If you have a compatible USB printer connected to your Apple wireless device, computers on the AirPort network can use Bonjour (Apple’s zero-configuration networking technology) to print to the printer. For instructions about printing to a USB printer from a computer, see “Connecting a USB Printer to an Apple Wireless Device” on page 55. Sharing Your Computer’s Internet Connection If your computer is connected to the Internet, you can share your Internet connection with other computers using Mac OS X version 10.2 or later, or Windows XP with Service Pack 2. This is sometimes called using your computer as a software base station.Chapter 1 Getting Started 7 You can share your Internet connection as long as your computer is connected to the Internet. If your computer goes to sleep or is restarted, or if you lose your Internet connection, you need to restart Internet sharing. To start Internet sharing on a computer using Mac OS X v10.5 or later: 1 Open System Preferences and click Sharing. 2 Choose the port you want to use to share your Internet connection from the “Share your connection using” pop-up menu. 3 Select the port you want to use to share your Internet connection in the “To computers using” list. You can choose to share your Internet connection with AirPort-enabled computers or computers with built-in Ethernet, for example. 4 Select Internet Sharing in the Services list. 5 If you want to share your Internet connection with computers using AirPort, click AirPort Options to give your network a name and password. 8 Chapter 1 Getting Started To start Internet sharing on a computer using Windows: 1 Open Control Panel from the Start menu, and then click “Network and Internet.” 2 Click “Network and Sharing Center.” 3 Click “Manage network connections” in the Tasks list. 4 Right-click the network connection you want to share, and then select Properties. 5 Click Sharing and then select “Allow other network users to connect through this computer’s Internet connection.” Note: If your Internet connection and your local network use the same port (built-in Ethernet, for example), contact your ISP before you turn on Internet sharing. In some cases (if you use a cable modem, for example) you might unintentionally affect the network settings of other ISP customers, and your ISP might terminate your service to prevent you from disrupting its network. The following chapters explain AirPort security options, AirPort network design and setup, and other advanced options.2 9 2 AirPort Security This chapter provides an overview of the security features available in AirPort. Apple has designed its wireless devices to provide several levels of security, so you can enjoy peace of mind when you access the Internet, manage online financial transactions, or send and receive email. The AirPort Extreme Base Station and Time Capsule also include a slot for inserting a lock to deter theft. For information and instructions for setting up these security features, see “Setting Up the AirPort Extreme Network” on page 17. Security for AirPort Networks at Home Apple gives you ways to protect your wireless AirPort network as well as the data that travels over it. NAT Firewall You can isolate your wireless network with firewall protection. Apple wireless devices have a built-in Network Address Translation (NAT) firewall that creates a barrier between your network and the Internet, protecting data from Internet-based IP attacks. The firewall is automatically turned on when you set up the device to share a single Internet connection. For computers with a cable or DSL modem, AirPort can actually be safer than a wired connection. Closed Network Creating a closed network keeps the network name and the very existence of your network private. Prospective users of your network must know the network name and password to access it. Use AirPort Utility, located in the Utilities folder in the Applications folder on a Macintosh computer using Mac OS X, or in Start > All Programs > AirPort on a computer using Windows, to create a closed network.10 Chapter 2 AirPort Security Password Protection and Encryption AirPort uses password protection and encryption to deliver a level of security comparable to that of traditional wired networks. Users can be required to enter a password to log in to the AirPort network. When transmitting data and passwords, the wireless device uses up to 128-bit encryption, through either Wi-Fi Protected Access (WPA), WPA2, or Wired Equivalent Privacy (WEP), to scramble data and help keep it safe. If you’re setting up an 802.11n-based AirPort device, you can also use WEP (Transitional Security Network) if both WEP-compatible and WPA/WPA2-compatible computers will join your network. Note: WPA security is available only to AirPort Extreme wireless devices; AirPort and AirPort Extreme clients using Mac OS X 10.3 or later and AirPort 3.3 or later; and to non-Apple clients using other 802.11 wireless adapters that support WPA. WPA2 security requires firmware version 5.6 or later for an AirPort Extreme Base Station, firmware version 6.2 or later for an AirPort Express, firmware version 7.3 or later for a Time Capsule, and a Macintosh computer with an AirPort Extreme wireless card using AirPort 4.2 or later. If your computer uses Windows XP or Windows Vista, check the documentation that came with your computer to see if your computer supports WPA2. Security for AirPort Networks in Businesses and Classrooms Businesses and schools need to restrict network communications to authorized users and keep data safe from prying eyes. To meet this need, Apple wireless devices and software provide a robust suite of security mechanisms. Use AirPort Utility to set up these advanced security features. Transmitter Power Control Because radio waves travel in all directions, they can extend outside the confines of a specific building. The Transmit Power setting in AirPort Utility lets you adjust the transmission range of your device’s network. Only users within the network vicinity have access to the network. MAC Address Access Control Every AirPort and wireless card have a unique Media Access Control (MAC) address. For AirPort Cards and AirPort Extreme Cards, the MAC address is sometimes referred to as the AirPort ID. Support for MAC address access control lets administrators set up a list of MAC addresses and restrict access to the network to only those users whose MAC addresses are in the access control list.Chapter 2 AirPort Security 11 RADIUS Support The Remote Authentication Dial-In User Service (RADIUS) makes securing a large network easy. RADIUS is an access control protocol that allows a system administrator to create a central list of the user names and passwords of computers that can access the network. Placing this list on a centralized server allows many wireless devices to access the list and makes it easy to update. If the MAC address of a user’s computer (which is unique to each 802.11 wireless card) is not on your approved MAC address list, the user cannot join your network. Wi-Fi Protected Access (WPA) and WPA2 There has been increasing concern about the vulnerabilities of WEP. In response, the Wi-Fi Alliance, in conjunction with the IEEE, has developed enhanced, interoperable security standards called Wi-Fi Protected Access (WPA) and WPA2. WPA and WPA2 use specifications that bring together standards-based, interoperable security mechanisms that significantly increase the level of data protection and access control for wireless LANs. WPA and WPA2 provide wireless LAN users with a high-level assurance that their data remains protected and that only authorized network users can access the network. A wireless network that uses WPA or WPA2 requires all computers that access the wireless network to have WPA or WPA2 support. WPA provides a high level of data protection and (when used in Enterprise mode) requires user authentication. The main standards-based technologies that constitute WPA include Temporal Key Integrity Protocol (TKIP), 802.1X, Message Integrity Check (MIC), and Extensible Authentication Protocol (EAP). TKIP provides enhanced data encryption by addressing the WEP encryption vulnerabilities, including the frequency with which keys are used to encrypt the wireless connection. 802.1X and EAP provide the ability to authenticate a user on the wireless network. 802.1X is a port-based network access control method for wired as well as wireless networks. The IEEE adopted 802.1X as a standard in August 2001. The Message Integrity Check (MIC) is designed to prevent an attacker from capturing data packets, altering them, and resending them. The MIC provides a strong mathematical function in which the receiver and the transmitter each compute and then compare the MIC. If they do not match, the data is assumed to have been tampered with and the packet is dropped. If multiple MIC failures occur, the network may initiate countermeasures.12 Chapter 2 AirPort Security The EAP protocol known as TLS (Transport Layer Security) presents a user’s information in the form of digital certificates. A user’s digital certificates can comprise user names and passwords, smart cards, secure IDs, or any other identity credentials that the IT administrator is comfortable using. WPA uses a wide variety of standards-based EAP implementations, including EAP-Transport Layer Security (EAP-TLS), EAP-Tunnel Transport Layer Security (EAP-TTLS), and Protected Extensible Authentication Protocol (PEAP). AirPort Extreme also supports the Lightweight Extensible Authentication Protocol (LEAP), a security protocol used by Cisco access points to dynamically assign a different WEP key to each user. AirPort Extreme is compatible with Cisco’s LEAP security protocol, enabling AirPort users to join Cisco-hosted wireless networks using LEAP. In addition to TKIP, WPA2 supports the AES-CCMP encryption protocol. Based on the very secure AES national standard cipher, combined with sophisticated cryptographic techniques, AES-CCMP was specifically designed for wireless networks. Migrating from WEP to WPA2 requires new firmware for the AirPort Extreme Base Station (version 5.6 or later), and for AirPort Express (version 6.2 or later). Devices using WPA2 mode are not backward compatible with WEP. WPA and WPA2 have two modes:  Personal mode, which relies on the capabilities of TKIP or AES-CCMP without requiring an authentication server  Enterprise mode, which uses a separate server, such as a RADIUS server, for user authentication WPA and WPA2 Personal  For home or Small Office/Home Office (SOHO) networks, WPA and WPA2 operates in Personal mode, taking into account that the typical household or small office does not have an authentication server. Instead of authenticating with a RADIUS server, users manually enter a password to log in to the wireless network. When a user enters the password correctly, the wireless device starts the encryption process using TKIP or AES-CCMP. TKIP or AES-CCMP takes the original password and derives encryption keys mathematically from the network password. The encryption key is regularly changed and rotated so that the same encryption key is never used twice. Other than entering the network password, the user isn’t required to do anything to make WPA or WPA2 Personal work in the home.Chapter 2 AirPort Security 13 WPA and WPA2 Enterprise WPA is a subset of the draft IEEE 802.11i standard and effectively addresses the wireless local area network (WLAN) security requirements for the enterprise. WPA2 is a full implementation of the ratified IEEE 802.11i standard. In an enterprise with IT resources, WPA should be used in conjunction with an authentication server such as RADIUS to provide centralized access control and management. With this implementation in place, the need for add-on solutions such as virtual private networks (VPNs) may be eliminated, at least for securing wireless connections in a network. For more information about setting up a WPA or WPA2 protected network, see “Using Wi-Fi Protected Access” on page 45.3 14 3 AirPort Network Designs This chapter provides overview information and instructions for the types of AirPort Extreme networks you can set up, and some of the advanced options of AirPort Extreme. Use this chapter to design and set up your AirPort Extreme network. Configuring your Apple wireless device to implement a network design requires three steps: Step 1: Setting Up the AirPort Extreme Network Computers communicate with the wireless device over the AirPort wireless network. When you set up the AirPort network created by the wireless device, you can name the wireless network, assign a password that will be needed to join the wireless network, and set other options. Step 2: Configuring and Sharing Internet Access When computers access the Internet through the AirPort Extreme network, the wireless device connects to the Internet and transmits information to the computers over the AirPort Extreme network. You provide the wireless device with settings appropriate for your ISP and configure how the device shares this connection with other computers. Step 3: Setting Advanced Options These settings are optional for most users. They include using the Apple wireless device as a bridge between your AirPort Extreme network and an Ethernet network, setting advanced security options, extending the AirPort network to other wireless devices, and fine-tuning other settings. For specific instructions on all these steps, refer to the sections later in this chapter. You can do most of your setup and configuration tasks using AirPort Utility, and following the onscreen instructions to enter your ISP and network information. To set advanced options, you need to use AirPort Utility to manually set up your Apple wireless device and AirPort network.Chapter 3 AirPort Network Designs 15 Using AirPort Utility To set up and configure your computer or Apple wireless device to use AirPort Extreme for basic wireless networking and Internet access, use AirPort Utility and answer a series of questions about your Internet settings and how you would like to set up your network. 1 Open AirPort Utility, located in the Utilities folder in the Applications folder on a Mac, or in Start > All Programs > AirPort on a Windows computer. 2 Select your device in the list on the left if there is more than one device in your network. Click Continue, and then follow the onscreen instructions to enter the settings from your ISP or network administrator for the type of network you want to set up. See the network diagrams later in this chapter for the types of networks you can set up using AirPort Utility. To set up a more complicated network, or to make adjustments to a network you’ve already set up, use the manual setup features in AirPort Utility. Setting AirPort preferences Use AirPort preferences to set up your wireless device to alert you when there are updates available for your device. You can also set it up to notify you if there are problems detected, and to provide instructions to help solve the problems. To set AirPort preferences: 1 Open AirPort Utility, located in the Utilities folder inside the Applications folder on a Mac, and in Start > All Programs > AirPort on a Windows computer. 2 Do one of the following:  On a Mac, choose AirPort Utility > Preferences  On a Windows computer, choose File > Preferences16 Chapter 3 AirPort Network Designs Select from the following checkboxes:  Select “Check for Updates when opening AirPort Utility” to automatically check the Apple website for software and firmware updates each time you open AirPort Utility.  Select the “Check for updates” checkbox, and then choose a time interval from the pop-up menu, such as weekly, to check for software and firmware updates in the background. AirPort Utility opens if updates are available.  Select “Monitor Apple wireless devices for problems” to investigate problems that may cause the device’s status light to blink amber. With the checkbox selected, AirPort Utility opens if a problem is detected, and then provides instructions to help resolve the problem. This option monitors all of the wireless devices on the network.  Select “Only Apple wireless devices that I have configured” to monitor only the devices you’ve set up using this computer. Monitoring devices for problems requires an AirPort wireless device that supports firmware version 7.0 or later. To set up your wireless device manually: 1 Open AirPort Utility, located in the Utilities folder in the Applications folder on a Mac, or in Start > All Programs > AirPort on a Windows computer. 2 Select your device in the list. 3 Choose Base Station > Manual Setup and enter the password if necessary. The default device password is public. If you don’t see your wireless device in the list: 1 Open the AirPort status menu in the menu bar on a Mac and make sure that you’ve joined the AirPort network created by your wireless device. On a Windows computer, hover the cursor over the wireless network icon in the status tray to make sure the computer is connected to the correct network. The default network name for an Apple wireless device is AirPort Network XXXXXX, where XXXXXX is replaced with the last six digits of the AirPort ID, (or MAC address). The AirPort ID is printed on the bottom of Apple wireless devices. 2 Make sure your computer’s network and TCP/IP settings are configured properly. On a computer using Mac OS X, choose AirPort from the Show pop-up menu in the Network pane of System Preferences. Then choose Using DHCP from the Configure IPv4 pop-up menu in the TCP/IP pane. On a computer using Windows, right-click the wireless connection icon that displays the AirPort network, and choose Status. Click Properties, select Internet Protocol (TCP/IP), and then click Properties. Make sure “Obtain an IP address automatically” is selected.Chapter 3 AirPort Network Designs 17 If you can’t open the wireless device settings: 1 Make sure your network and TCP/IP settings are configured properly. On a computer using Mac OS X, select AirPort from the network connection services list in the Network pane of System Preferences. Click Advanced, and then choose Using DHCP from the Configure IPv4 pop-up menu in the TCP/IP pane. On a computer using Windows, right-click the wireless connection icon that displays the AirPort network, and choose Status. Click Properties, select Internet Protocol (TCP/IP), and then click Properties. Make sure “Obtain an IP address automatically” is selected. 2 Make sure you entered the wireless device password correctly. The default password is public. If you’ve forgotten the device password, you can reset it to public by resetting the device. To temporarily reset the device password to public, hold down the reset button for one second. To reset the device back to its default settings, hold the reset button for five full seconds. If you’re on an Ethernet network that has other devices, or you’re using Ethernet to connect to the device: AirPort Utility scans the Ethernet network to create the list of devices. As a result, when you open AirPort Utility, you may see devices that you cannot configure. Setting Up the AirPort Extreme Network The first step in configuring your Apple wireless device is setting up the device and the network it will create. You can set up most features using AirPort Utility and following the onscreen instructions to enter the information from your ISP or network administrator. To configure a network manually or set advanced options, open your wireless device’s configuration in AirPort Utility and manually set up your device and network. 1 Choose the network of the wireless device you want to configure from the AirPort status menu on a computer using Mac OS X, or from the wireless connection icon in the status tray on a computer using Windows. 2 Open AirPort Utility and select the wireless device from the list. If you don’t see the device you want to configure, click Rescan to scan for available wireless devices, and then select the one you want from the list. 18 Chapter 3 AirPort Network Designs 3 Choose Base Station > Manual Setup and enter the password if necessary. The default device password is public. You can also double-click the name of the wireless device to open its configuration in a separate window. When you open the manual setup window, the Summary pane is displayed. The summary pane provides information and status about your wireless device and network.Chapter 3 AirPort Network Designs 19 If the wireless device reports a problem, the status icon turns yellow. Click Base Station Status to display the problem and suggestions to resolve it. Wireless Device Settings Click the AirPort button, and then click Base Station or Time Capsule, depending on the device you’re setting up, to enter information about the wireless device. Give the Device a Name Give the device an easily identifiable name. This makes it easy for administrators to locate a specific device on an Ethernet network with several devices. Change the Device Password The device password protects its configuration so that only the administrator can modify it. The default password is public. It is a good idea to change the device password to prevent unauthorized changes to it. If the password is not changed from public, you’ll not be prompted for a password when you select it from the list and click Configure. Other Information  Allow configuration over the WAN port. This allows you to administer the wireless device remotely.  Advertise the wireless device over the Internet using Bonjour. If you have an account with a dynamic DNS service, you can connect to it over the Internet.  Set the device time automatically. If you have access to a Network Time Protocol server, whether on your network or on the Internet, choose it from the pop-up menu. This ensures your wireless device is set to the correct time.20 Chapter 3 AirPort Network Designs Set Device Options Click Base Station Options and set the following:  Enter a contact name and location for the wireless device. The name and location are included in some logs the device generates. The contact and location fields may be helpful if you’ve more than one wireless device on your network.  Set status light behavior to either Always On or Flash On Activity. If you choose Flash On Activity, the device status light blinks when there is network traffic.  If your wireless device supports it, select “Check for firmware updates” and choose an increment, such as Daily from the pop-up menu. Wireless Network Settings Click Wireless, and enter the network name, radio mode, and other wireless information. Setting the Wireless Mode AirPort Extreme supports two wireless modes:  Create a wireless network. Choose this option if you’re creating a new AirPort Extreme network.  Extend a wireless network. Choose this option if you plan to connect another Apple wireless device to the network you’re setting up. Naming the AirPort Extreme Network Give your AirPort network a name. This name appears in the AirPort status menu on the AirPort-enabled computers that are in range of your AirPort network.Chapter 3 AirPort Network Designs 21 Choosing the Radio Mode Choose 802.11a/n - 802.11b/g from the Radio Mode pop-up menu if computers with 802.11a, 802.11n, 802.11g, or 802.11b wireless cards will join the network. Each client computer will connect to the network and transmit network traffic at the highest possible speed. Choose 802.11n - 802.11b/g if only computers with 802.11n, 802.11b, or 802.11g compatible wireless cards will join the network. Note: If you don’t want to use an 802.11n radio mode, hold down the Option key and chose a radio mode that doesn’t include 802.11n. Changing the Channel The “channel” is the radio frequency over which your wireless device communicates. If you use only one device (for example, at home), you probably won’t need to change the channel frequency. If you set up several wireless devices in a school or office, use different channel frequencies for devices that are within approximately 150 feet of each other. Adjacent wireless devices should have at least 4 channels between their channel frequencies. So if device A is set to channel 1, device B should be set to channel 6 or 11. For best results, use channels 1, 6, or 11 when operating your device in the 2.4 GHz range. Choose Manually from the Radio Channel Selection pop-up menu, and then click Edit to set the channels manually. AirPort-enabled computers automatically tune to the channel frequency your wireless device is using when they join the AirPort network. If you change the channel frequency, AirPort client computers do not need to make any changes. Password-protect Your Network To password-protect your network, you can choose from a number of wireless security options. In the AirPort pane of AirPort Utility, click Wireless and choose one of the following options from the Wireless Security pop-up menu:  None: Choosing this option turns off all password protection for the network. Any computer with a wireless adapter or card can join the network, unless the network is set up to use access control. See “Setting Up Access Control” on page 47.  WEP: If your device supports it, choose this option and enter a password to protect your network with a Wired Equivalent Privacy (WEP) password. Your Apple wireless device supports 40-bit and 128-bit encryption. To use 40-bit WEP, don’t use an 802.11n radio mode.22 Chapter 3 AirPort Network Designs  WPA/WPA2 Personal: Choose this option to protect your network with Wi-Fi Protected Access. You can use a password between 8 and 63 ASCII characters or a Pre-Shared Key of exactly 64 hexadecimal characters. Computers that support WPA and computers that support WPA2 can join the network. Choose WPA2 Personal if you want only computers that support WPA2 to join your network.  WPA/WPA2 Enterprise: Choose this option if you’re setting up a network that includes an authentication server, such as a RADIUS server, with individual user accounts. Enter the IP address and port number for the primary and optional secondary server, and enter a “shared secret,” which is the password for the server. Choose WPA2 Enterprise if you want only computers that support WPA2 to join the network.  WEP (Transitional Security Network): If your device supports it, you can use this option to allow computers using WPA or WPA2 to join the network. Computers or devices that use WEP can also join the network. WEP (Transitional Security Network) supports 128-bit encryption. To use this option, the wireless device use an 802.11n radio mode. Hold the Option key on your keyboard while clicking the Wireless Security pop-up menu to use WEP (Transitional Security Netowrk). For more information and instructions for setting up WPA or WPA2 on your network, see “Using Wi-Fi Protected Access” on page 45. Setting Wireless Options Click Wireless Options to set additional options for your network.Chapter 3 AirPort Network Designs 23 Setting Additional Wireless Options Use the Wireless Options pane to set the following:  5 GHz network name: Provide a name for the 5 GHz segment of the dual-band network if you want it to have a different name than the 2.4 GHz network.  Country: Choose the country for the location of your network from the Country pop-up menu.  Multicast rate: Choose a multicast rate from the pop-up menu. If you set the multicast rate high, only clients on the network that are within range and can achieve the speed you set will receive transmissions.  Transmit power: Choose a setting from the Transmit Power pop-up menu to set the network range (the lower the percentage, the shorter the network range).  WPA Group Key Timeout: Enter a number in the text field, and choose an increment from the pop-up menu to change the frequency of key rotation.  Use Wide Channels: If you set up your network to use the 5 GHz frequency range, you can use wide channels to provide higher network throughput. Note: Using wide channels is not permitted in some countries.  Create a closed network: Selecting a closed network hides the name of the network so that users must enter the exact network name and password to join the AirPort Extreme network.  Use interference robustness: Interference robustness can solve interference problems caused by other devices or networks. To set more advanced security options, see “Keeping Your Network Secure” on page 45.24 Chapter 3 AirPort Network Designs Setting up a Guest Network Click Guest Network and then enter the network name and other options for the guest network. When you set up a guest network, a portion of your connection to the Internet is reserved for “guests”, wireless clients that can join the guest network and connect to the Internet without accessing your private network. Select “Allow guest network clients to communicate with each other” to allow client computers to share files and services with each other while they’re connected to the guest network. Make sure sharing services are set up on the client computers. Configuring and Sharing Internet Access The next step is setting up your wireless device’s Internet connection and sharing its Internet access with client computers. The following sections tell you what to do, depending on how your device connects to the Internet. You’re Using a DSL or Cable Modem In most cases, you can implement this network design using AirPort Utility and following the onscreen instructions to set up your wireless device and network. You need to use AirPort Utility to manually set up your device only if you want to set up or adjust optional advanced settings.Chapter 3 AirPort Network Designs 25 What It Looks Like How It Works  The Apple wireless device (in this example, a Time Capsule) connects to the Internet through its Internet WAN (<) connection to your DSL or cable modem.  Computers using AirPort or computers connected to the wireless device’s Ethernet LAN port (G) connect to the Internet through the device.  The device is set up to use a single, public IP address to connect to the Internet, and uses DHCP and NAT to share the Internet connection with computers on the network using private IP addresses.  AirPort computers and Ethernet computers communicate with one another through the wireless device. Important: Connect Ethernet computers that are not connected to the Internet to the device’s LAN port (G) only. Since the device can provide network services, you must set it up carefully to avoid interfering with other services on your Ethernet network. What You Need for a DSL or Cable Modem Connection DSL or cable modem to Internet to Ethernet port Time Capsule < Ethernet WAN port 2.4 or 5 GHz Components Check Comments Internet account with DSL or cable modem service provider Does your service provider use a static IP or DHCP configuration? You can get this information from your service provider or the Network preferences pane on the computer you use to access the Internet through this service provider. Apple wireless device (an AirPort Extreme Base Station, an AirPort Express, or a Time Capsule) Place the device near your DSL or cable modem.26 Chapter 3 AirPort Network Designs What to Do If you’re using AirPort Utility to assist you with configuring the Apple wireless device for Internet access: 1 Open AirPort Utility, located in the Utilities folder in the Applications folder on a Mac, or in Start > All Programs > AirPort on a Windows computer. 2 Follow the onscreen instructions and enter the settings you received from your service provider to connect to the Internet, and then set up the device to share the Internet connection with computers on the network. If you’re using AirPort Utility to manually set up your wireless device: 1 Make sure that your DSL or cable modem is connected to the Ethernet WAN port (<) on your Apple wireless device. 2 Open AirPort Utility, located in the Utilities folder in the Applications folder on a Mac, or in Start > All Programs > AirPort on a Windows computer. Select your wireless device and choose Base Station > Manual Setup, or double-click your device’s icon in the list to open the configuration in a separate window. 3 Click the Internet button. Click Internet Connection and choose Ethernet or PPPoE from the Connect Using pop-up menu, depending on which one your service provider requires. If your service provider gave you PPPoE connection software, such as EnterNet or MacPoET, choose PPPoE. Note: If you’re connecting to the Internet through a router using PPPoE and your Apple wireless device is connected to the router via Ethernet, you do not need to use PPPoE on your wireless device. Choose Ethernet from the Connect Using pop-up menu in the Internet pane, and deselect the “Distribute IP addresses” checkbox in the Network pane. Contact your service provider if you aren’t sure which one to select. 4 Choose Manually or Using DHCP from the Configure IPv4 pop-up menu if you chose Ethernet from the Connect Using pop-up menu, depending on how your service provider provides IP addresses.  If your provider gave you an IP address and other numbers with your subscription, use that information to configure the wireless device IP address manually. If you aren’t sure, ask your service provider. Enter the IP address information in the fields below the Configure IPv4 pop-up menu.Chapter 3 AirPort Network Designs 27  If you chose PPPoE, your ISP provides your IP address automatically using DHCP. If your service provider asks you for the MAC address of your wireless device, use the address of the Ethernet WAN port (<), printed on the label on the bottom of the device. If you’ve already used AirPort Utility to set up your wireless device, the fields below the Configure IPv4 pop-up menu may already contain the information appropriate for your service provider. You can change the WAN Ethernet speed if you have specific requirements for the network you’re connected to. In most cases, the settings that are configured automatically are correct. Your service provider should be able to tell you if you need to adjust these settings. Changing the WAN Ethernet speed can affect the way the wireless device interacts with the Internet. Unless your service provider has given you specific settings, use the automatic settings. Entering the wrong settings can affect network performance. Contact your service provider for the information you should enter in these fields. Use this pop-up menu if you need to adjust the speed of the Ethernet WAN port.28 Chapter 3 AirPort Network Designs If you configure TCP/IP using DHCP, choose Using DHCP from the Configure IPv4 pop-up menu. Your IP information is provided automatically by your ISP using DHCP. 5 If you chose PPPoE from the Connect Using pop-up menu, enter the PPPoE settings your service provider gave you. Leave the Service Name field blank unless your service provider requires a service name. Note: With AirPort, you don’t need to use a third-party PPPoE connection application. You can connect to the Internet using AirPort. Your service provider may require you to enter information in these fields. Contact your service provider for the information you should enter in these fields.Chapter 3 AirPort Network Designs 29 If you’re connecting to the Internet through a router that uses PPPoE to connect to the Internet, and your wireless device is connected to the router via Ethernet, you do not need to use PPPoE on your device. Choose Ethernet from the Connect Using pop-up menu in the Internet pane, and deselect the “Distribute IP addresses” checkbox in the Network pane. Because your router is distributing IP addresses, your wireless device doesn’t need to. More than one device on a network providing IP addresses can cause problems. 6 Click PPPoE to set PPPoE options for your connection.  Choose Always On, Automatic, or Manual, depending on how you want to control when your wireless device is connected to the Internet. If you choose Always On, your device stays connected to your modem and the Internet as long as the modem is turned on. If you choose Automatic, the wireless device connects to the modem, which connects to the Internet when you use an application that requires an Internet connection, such as email or an instant message or web application. If you choose Manual, you need to connect the modem to the Internet when you use an application that requires an Internet connection. If you chose Automatic or Manual from the Connection pop-up menu, you need to choose an increment, such as “10 minutes,” from the “Disconnect if idle” pop-up menu. If you don’t use an Internet application after the increment of time has passed, you’ll be disconnected from the Internet. Note: If your wireless device is connected to your modem using an Ethernet LAN port, and your modem is connected to the Internet using PPPoE, you may not be able to use the manual setting.30 Chapter 3 AirPort Network Designs  Enter Domain Name System (DNS) server addresses and a specific domain name your wireless device accesses when you connect to the Internet. 7 Click the Network button and configure how the device will share its Internet access with AirPort and Ethernet computers. If you chose Ethernet from the Connect Using pop-up menu, choose how your device will share the Internet connection from the Connection Sharing pop-up menu.  To share a single Internet connection with AirPort computers and computers connected to the device with Ethernet using DHCP and NAT, choose “Share a public IP address” from the Connection Sharing pop-up menu. Using DHCP and NAT lets the wireless device dynamically and automatically assign IP addresses to client computers, which simplifies each computer’s TCP/IP configuration. See “Setting DHCP and NAT Options” on page 31. By default, the wireless device allows other devices, computers using Ethernet, and computers using AirPort to communicate with each other using non-IP protocols like AppleTalk. If you want to connect an AppleTalk Ethernet printer to the Apple wireless device or use AppleTalk between wired and wireless computers, make sure the devices are connected to the Ethernet LAN port (G) on the device.  To distribute a range of IP addresses using only DHCP, choose “Distribute a range of IP addresses.” See “Setting DHCP Only Options” on page 33.Chapter 3 AirPort Network Designs 31  If you don’t want your wireless device to share its IP address, choose “Off (Bridge Mode).” If you set up your device in bridge mode, AirPort computers have access to all services on the Ethernet network, and the device does not provide Internet sharing services. See “You’re Using an Existing Ethernet Network” on page 37 for more information about setting up your wireless device as a bridge. Using the wireless device as a bridge can be a way to address incompatibilities between the device’s Internet sharing features and your ISP’s connection method. Setting DHCP and NAT Options If you chose “Share a public IP address” from the Connection Sharing pop-up menu, you can set DHCP and NAT options. Click DHCP.  Choose a range of IP addresses from the DHCP Range pop-up menu. Choose 10.0, 192.168, or 172.16 and then enter a beginning and ending address in the DHCP Beginning Address and the DHCP Ending Address fields, depending on which addresses you want the wireless device to provide.  Enter a number in the DHCP Lease field, and then choose minutes, hours, or days from the pop-up menu.  Type a welcome message in the DHCP Message field. This message is displayed when a computer joins your network.  If your network is set up to use a Lightweight Directory Access Protocol (LDAP) server on your network, you can enter the address of the server in the LDAP Server field, and computers on your network will have access to it.32 Chapter 3 AirPort Network Designs  To provide specific IP addresses to specific computers on your wireless network, click the Add (+) button below the DHCP Reservations list, and follow the onscreen instructions to name the reservation and reserve the address by MAC address or DHCP client ID. If you choose MAC address, click Continue and enter the MAC address and specific IP address. Next you can set NAT options for the network. Click NAT.  You can set up a default host on your network. A default host (sometimes known as a DMZ) is a computer on your network that is exposed to the Internet and receives all inbound traffic. A default host may be useful if you use a computer on your AirPort network to play network games, or want to route all Internet traffic through a single computer.  You can set up NAT Port Mapping Protocol (NAT-PMP). NAT-PMP is an Internet Engineering Task Force Internet Draft, an alternative to the more common Universal Plug and Play (UPnP) protocol implemented in many network address translation (NAT) routers. NAT-PMP allows a computer in a private network (behind a NAT router) to automatically configure the router to allow parties outside the private network to contact this computer. Included in the protocol is a method for retrieving the public IP address of a NAT gateway, allowing a client to make this public IP address and port number known to peers that may wish to communicate with it. This protocol is implemented in current Apple products, including Mac OS X 10.4 Tiger and later, AirPort Extreme, AirPort Express, and Time Capsule networking products, and Bonjour for Windows.Chapter 3 AirPort Network Designs 33 You can also set up port mapping. To ensure that requests are properly routed to your web, AppleShare, or FTP server, or a specific computer on your network, you need to establish a permanent IP address for the server or computer, and provide “inbound port mapping” information to the Apple wireless device. See “Directing Network Traffic to a Specific Computer on Your Network (Port Mapping)” on page 49. Setting DHCP Only Options If you chose “Distribute a range of IP addresses” from the Connection Sharing pop-up menu, your wireless device is set up to use DHCP to distribute a range of IP addresses using only DHCP. You cannot use NAT if you chose this option. Click DHCP and enter the beginning and ending addresses you want to distribute to computers joining your wireless network. You can set the additional DHCP options, such as DHCP Lease, DHCP Message, and other options following the instructions above. Setting Up Client Computers To configure TCP/IP on client computers using Mac OS X v10.5: 1 Open System Preferences on the client computer and then click Network. 2 Do one of the following: a If the client computer is using AirPort, select AirPort in the network connection services list, and then click Advanced.34 Chapter 3 AirPort Network Designs Next, choose DHCP from the Configure IPv4 pop-up menu. b If you enabled a DHCP server when you set up the wireless device’s network, and the client computer is using Ethernet, select Ethernet in the network connection services list, and then choose Using DHCP from the Configure pop-up menu.Chapter 3 AirPort Network Designs 35 c If you selected “Distribute a range of IP addresses” when you set up the wireless device’s network, you can provide Internet access to client computers using Ethernet by setting the client IP addresses manually. Select Ethernet in the network connection services list, and then choose Manually from the Configure pop-up menu. When you configure Ethernet clients manually for a wireless device that provides NAT over Ethernet, you can use IP addresses in the range 10.0.1.2 to 10.0.1.200. In the Subnet Mask field, enter 255.255.255.0. In the Router field, enter 10.0.1.1. Enter the same name server address and search domain information that you entered in the wireless device configuration. To configure TCP/IP on client computers using Windows Make sure you’ve installed the wireless adapter in your computer and the software necessary to set up the adapter. To configure TCP/IP on client computers: 1 Open Control Panel from the Start menu, and then click “Network and Internet.” 2 Click “Network and Sharing Center.” 3 Click “Manage network connections” in the Tasks list. 4 Right-click the wireless connection you want to share, and then select Properties. Enter the IP and router addresses from the range your device is providing. Enter the DNS and Search Domain addresses if necessary.36 Chapter 3 AirPort Network Designs 5 Click Internet Protocol Version 4 (TCP/IPv4), and then click Properties.  If you chose “Share a public IP address” in the Network pane of AirPort Utility, select “Obtain an IP address automatically.”  If you chose “Distribute a range of IP addresses” when you set up the wireless device’s network, you can provide Internet access to client computers by setting the client IP addresses manually. Select “Use the following IP address.” When you configure clients manually for a wireless device that provides NAT service, use IP addresses in the range 10.0.1.2 to 10.0.1.200, 172.16.1.2 to 172.16.1.200, or 192.168.1.2 to 192.168.1.200. In the “Subnet mask” field, enter 255.255.255.0. In the “Default gateway” field, enter 10.0.1.1, 172.16.1.1, or 192.168.1.1, depending on which addressing scheme you used. Enter the same name server address and search domain information that you entered in the wireless device configuration.Chapter 3 AirPort Network Designs 37 You’re Using an Existing Ethernet Network You can use AirPort Utility to easily set up the Apple wireless device for Internet access through an existing Ethernet network that already has a router, switch, or other network device providing IP addresses. Use the manual setup features of AirPort Utility if you need to adjust optional advanced settings. What It Looks Like How It Works  The Apple wireless device (in this example, a Time Capsule) uses your Ethernet network to communicate with the Internet through the Ethernet WAN port (<).  AirPort and Ethernet clients access the Internet and the Ethernet network through the Apple wireless device. What You Need for an Ethernet Connection Router to Internet to Ethernet port Time Capsule All Programs > AirPort on a Windows computer. 2 Click Continue and follow the onscreen instructions to connect to your local area network (LAN). If you’re using AirPort Utility to manually set up your wireless device: 1 Open AirPort Utility, located in the Utilities folder in the Applications folder on a Mac, or in Start > All Programs > AirPort on a Windows computer. 2 Select your device and choose Base Station > Manual Setup, or double-click your device icon to open the configuration in a separate window. 3 Click Internet and choose Ethernet from the Connect Using pop-up menu. 4 Choose Manually or Using DHCP from the Configure IPv4 pop-up menu, depending on how IP addresses are provided on your Ethernet network. If you aren’t sure, ask your service provider or network administrator. If your addresses are provided manually, choose Manually from the Configure IPv4 pop-up menu. Enter your IP address information in the fields below the Configure IPv4 pop-up menu. If you’ve already used AirPort Utility to set up your Apple wireless device, the fields below the Configure IPv4 pop-up menu may already contain the appropriate information. Contact your network administrator for the information you should enter in these fields.Chapter 3 AirPort Network Designs 39 If your IP address is provided by DHCP, choose Using DHCP from the Configure IPv4 pop-up menu. 5 Choose Off (Bridge Mode) from the Connection Sharing pop-up menu. Your wireless device “bridges” the Ethernet networks Internet connection to computers connected to the device wirelessly or by Ethernet. See “Setting Up Client Computers” on page 33 for information about how to set up client computers to connect to the Ethernet network.40 Chapter 3 AirPort Network Designs Connecting Additional Devices to Your AirPort Extreme Network Connect a USB printer to the USB port of your Apple wireless device (in this example, a Time Capsule) and everyone on the network can print to it. Connect a USB hub to the USB port of an AirPort Extreme Base Station or a Time Capsule, and then connect a hard disk and a printer so everyone on the network can access them. If you connect a Time Capsule, you can use Time Machine in Mac OS X Leopard (v10.5.2 or later) to back up all of the Mac OS X Leopard computers on the network. What It Looks Like What to Do Follow the instructions in the previous sections to set up your AirPort Extreme network depending on how you connect to the Internet or set up your wireless network. Connect a USB hard disk, printer, or hub to the USB port on your AirPort Extreme Base Station or Time Capsule. Note: If you’re using an AirPort Express in your network, you can connect a USB printer to the USB port, and everyone on the network can print to it. AirPort Express doesn’t support connecting a USB hard disk. DSL or cable modem USB Printer Time Capsule to Internet Ethernet WAN port AirPort Extreme < 2.4 or 5 GHz 2.4 or 5 GHz 2.4 or 5 GHzChapter 3 AirPort Network Designs 41 Using Apple TV on Your AirPort Extreme Network to Play Content from iTunes When you connect Apple TV to your AirPort Extreme network wirelessly, or using Ethernet, and then connect Apple TV to your widescreen TV, you can enjoy your favorite iTunes content including movies, TV shows, music, and more. (See the documentation that came with your Apple TV for instructions setting it up.) Setting Advanced Options Connecting Additional Wireless Devices to Your AirPort Network You can connect additional Apple wireless devices to extend the range of your wireless network. For example, you can connect an AirPort Extreme Base Station or a Time Capsule using Ethernet. A network with devices connected using Ethernet is known as a roaming network. You can also connect Apple wireless devices wirelessly to extend the network. DSL or cable modem to Internet to Ethernet port < Ethernet WAN port Time Capsule Apple TV 2.4 GHz 2.4 or 5 GHz42 Chapter 3 AirPort Network Designs Setting Up Roaming Several AirPort Extreme Base Stations or Time Capsules can be set up to create a single wireless network. Client computers using AirPort can move from device to device with no interruption in service (a process known as roaming). To set up roaming: 1 Connect all of the AirPort Extreme Base Stations and Time Capsules to the same subnet on your Ethernet network. 2 Give each device a unique name. 3 Give each device the same network name and password. 4 Set up the devices as bridges, following the instructions in the previous section. If you want one device to assign IP addresses using DHCP, also do the following: 1 Set up one device to act as the DHCP server. 2 Set up the other devices as bridges, following the instructions in the previous section. The device acting as a DHCP server can also receive its IP address via DHCP from a server on an Ethernet network or from a cable or DSL modem connected to an Internet service provider (ISP). to Ethernet port Ethernet LAN ports to Internet AirPort Extreme DSL or cable modem G Time Capsule < Ethernet WAN port 2.4 or 5 GHz 2.4 GHzChapter 3 AirPort Network Designs 43 Extending the Range of an 802.11n Network Extending the range of an 802.11n network is simpler if you’re connecting another 802.11n device. Connecting two Apple 802.11n wireless devices makes the WDS setup process more straightforward. To extend the range of an 802.11n network: 1 Open AirPort Utility and select the device that will connect to the Internet. See the previous sections of this document for instructions about setting up your wireless device, depending on your Internet connection. 2 Choose Base Station > Manual Setup, or double-click the device’s icon to open the configuration in a separate window. Enter the password if necessary. 3 Click the AirPort button, and then click Wireless. 4 Choose “Create a wireless network” from the Wireless Mode pop-up menu, and then select the “Allow this network to be extended” checkbox. 5 Next, select the device that will extend this network and choose Base Station > Manual Setup, or double-click the device’s icon to open its configuration in a separate window. Enter the password if necessary. 6 Choose “Extend a wireless network” from the Wireless Mode pop-up menu, and then choose the network you want to extend from the Network Name pop-up menu. 7 Enter the network name and password if necessary.44 Chapter 3 AirPort Network Designs 8 Click Update to update the device with new network settings. Controlling the Range of Your AirPort Network You can also shorten the range of your AirPort network. This might be useful if you want to control who has access to the network by restricting the range to a single room, for example. To shorten the range of your AirPort network: 1 Open AirPort Utility (in the Utilities folder in the Applications folder on a Macintosh computer, or in Start > All Programs > AirPort on a computer using Windows). 2 Select your wireless device and choose Base Station > Manual Setup, or double-click the device icon to open its configuration in a separate window. Enter the password if necessary. 3 Click the AirPort button, and then click Wireless. 4 Click Wireless Options, and then choose a percentage setting from the Transmit Power pop-up menu. The lower the percentage is, the shorter the range is.Chapter 3 AirPort Network Designs 45 Keeping Your Network Secure Your network is protected by the password you assign to it. However, you can take additional steps to help keep your network secure. Networks managed by Simple Network Management Protocol (SNMP) may be vulnerable to denial-of-service attacks. Similarly, if you configure your wireless device over the WAN port, it may be possible for unauthorized users to change network settings. When remote configuration is enabled, the device’s Bonjour information (the device name and IP address) is published over the WAN port. Turning off remote configuration may provide additional security. To help protect your network and wireless device: 1 Open AirPort Utility, select your device, and choose Base Station > Manual Setup, or double-click the device icon to open its configuration in a separate window. Enter the password if necessary. 2 Click the Advanced button, and then click Logging & SNMP. 3 Make sure the Allow SNMP Access and “Allow SNMP over WAN” checkboxes are not selected. Using Wi-Fi Protected Access AirPort Extreme supports WPA and WPA2 security standard for wireless networks. Using Mac OS X v10.3 or later or Windows XP with Service Pack 2, and 802.1X authentication capabilities, WPA security delivers more sophisticated data encryption than WEP, and also provides user authentication, which was virtually unavailable with WEP. If your computer has an AirPort Extreme wireless card installed, you can take advantage of the security updates in WPA2, including AES-CCMP encryption. AirPort Extreme supports two modes of WPA and WPA2: Enterprise mode, which uses an authentication server for user authentication, and Personal mode, which relies on the capabilities of TKIP for WPA and AES-CCMP for WPA2, without requiring an authentication server. Enterprise mode is designed for a larger network in which an IT professional is most likely setting up and managing the network. In order to set up a WPA or WPA2 Enterprise network, an 802.1X connection must be set up first in Network preferences on a Mac. To set up an 802.1x connection on a Windows computer, see the documentation that came with your computer. The 802.1X connection requires an authentication protocol, like TTLS, LEAP, or PEAP. Setting up a WPA or WPA2 Enterprise network requires setting up an authentication server, such as a RADIUS server, to manage and validate network users’ credentials, such as user names, passwords, and user certificates. See the documentation that came with the server to set it up. 46 Chapter 3 AirPort Network Designs Personal mode is for the home or small office network and can be set up and managed by most users. Personal mode does not require a separate authentication server. Network users usually only need to enter a user name and password to join the network. Note: If you change an existing WDS network from WEP to WPA, you’ll need to reset the wireless devices and set up your network again. For information about resetting your Apple wireless device, see the documentation that came with it. To set up a WPA or WPA2 Enterprise network: On a computer using Mac OS X, you first need to set up an 802.1x connection. 1 Open System Preferences, click Network, and then click AirPort. 2 Click Advanced, and then click 802.1X 3 Enter the settings for the connection. Note: Some of the authentication protocols require digital certificate authorization on the server. See the documentation that came with your server to create and distribute digital certificates. 4 Click OK to save the connection settings. To use AirPort Utility to set up a WPA or WPA2 Enterprise network on computers using Mac OS X and Windows XP: 1 Open AirPort Utility, select your wireless device, and then choose Base Station > Manual Setup, or double-click the device icon to open its configuration in a separate window. Enter the password if necessary. 2 Choose WPA/WPA2 Enterprise, or WPA2 Enterprise from the Wireless Security pop-up menu, depending on the capabilities of the client computers that will join your network. 3 Click Configure RADIUS, and enter the IP address, port, and shared secret (or password) of the primary and secondary RADIUS authentication servers. Check with the administrator of the RADIUS server for information to type in these fields. To set up a WPA or WPA2 Personal network: 1 Open AirPort Utility, select your wireless device, and then choose Base Station > Manual Setup, or double-click the device icon to open its configuration in a separate window. Enter the password if necessary. 2 Choose WPA/WPA2 Personal or WPA2 Personal from the Wireless Security pop-up menu depending on the capabilities of the client computers that will join your network. 3 Type a password of 8 to 63 ASCII characters.Chapter 3 AirPort Network Designs 47 Setting Up Access Control Access control lets you specify which computers can send or receive information through the wireless device to the wired network. Each wireless-enabled computer has a unique MAC address. You can restrict access by creating an access control list that includes only the MAC addresses for computers you want to access your wired network. To find the MAC address (AirPort ID) of your computer’s AirPort Card, click the AirPort button in the Network pane of System Preferences. To set up the access control list: 1 Open AirPort Utility, select your wireless device, and then choose Base Station > Manual Setup. Enter the password if necessary. 2 Click the AirPort button, and then click Access. 3 Choose Timed Access or RADIUS from the MAC Address Access Control pop-up menu, depending on the device you’re setting up.  If you choose Timed Access, click the Add (+) button and enter the MAC address and description or name of the computers you’re allowing to access the network. You can also click This Computer to add the MAC address and name of the computer you’re using to set up this wireless device. Double-click the computer in the list and choose a value from each pop-up menu. Choose a day of the week or Everyday from the day pop-up menu, and then choose either “all day” or “between” from the other pop-up menu. If you choose “between,” you can edit the times of the day by double-clicking in the time fields.48 Chapter 3 AirPort Network Designs  If you choose RADIUS, enter the type of RADIUS service, the RADIUS IP addresses, shared secret, and primary port for the primary RADIUS server. Enter the information for the secondary RADIUS server if there is one. Check with the server administrator if you don’t have that information. Important: AirPort access control prevents computers that aren’t on the access control list from accessing the AirPort network. For information on how to prevent unauthorized computers from joining the AirPort network, see “Setting Up the AirPort Extreme Network” on page 17. You can also add the MAC address of a third-party 802.11 wireless networking card to the access control list. Most third-party cards have the MAC address on a label attached to the metal case of the card. Access control is not compatible with WPA or WPA2 Enterprise mode. You can use either access control or WPA Enterprise in a network, but you can’t use both. Using a RADIUS Server Using a RADIUS server on your network lets you authenticate MAC addresses (AirPort IDs) on a separate computer, so that each device on the network doesn’t need to store the MAC addresses of computers that have access to the network. Instead, all the addresses are stored on a server that is accessed through a specific IP address. To set up authentication using a RADIUS server: 1 On the server, enter the MAC addresses of the computers that will access the network. 2 When the RADIUS server is set up, open AirPort Utility, select your wireless device, and then choose Base Station > Manual Setup, or double-click the device icon to open its configuration in a separate window. Enter the password if necessary. 3 Click AirPort, click Access, and then choose RADIUS from the MAC Address Access Control pop-up menu. 4 Choose a format from the RADIUS pop-up menu. If you choose Default, your wireless device formats the MAC addresses as 010203- 0a0b0c, and they are used as the user names on the RADIUS server. The shared secret is the password for users joining the network. This format is often used for Lucent and Agere servers. If you choose Alternate, MAC addresses are formatted as 0102030a0b0c and are used for both the user name and password by users joining the network. This format is often used for Cisco servers.Chapter 3 AirPort Network Designs 49 5 Enter the IP address, port, and shared secret (or password) for the primary and secondary servers. See the RADIUS documentation that came with your server, or check with the network administrator for more information on setting up the RADIUS server. The access control list and RADIUS work together. When a user tries to join a network that authenticates using access control or a RADIUS server, the wireless device searches first in the access control list, and if the MAC address is there, the user can join the network. If the MAC address is not in the access control list, the device checks the RADIUS server for the MAC address. If it is there, the user can join the network. Note: RADIUS access control is not compatible with WPA or WPA2 Personal mode. You can use either RADIUS access control or WPA Enterprise in a network, but you can’t use both. Directing Network Traffic to a Specific Computer on Your Network (Port Mapping) AirPort Extreme uses Network Address Translation (NAT) to share a single IP address with the computers that join the AirPort Extreme network. To provide Internet access to several computers with one IP address, NAT assigns private IP addresses to each computer on the AirPort Extreme network, and then matches these addresses with port numbers. The wireless device creates a port-to-private IP address table entry when a computer on your AirPort (private) network sends a request for information to the Internet. 50 Chapter 3 AirPort Network Designs If you’re using a web, AppleShare, or FTP server on your AirPort Extreme network, other computers initiate communication with your server. Because the Apple wireless device has no table entries for these requests, it has no way of directing the information to the appropriate computer on your AirPort network. To ensure that requests are properly routed to your web, AppleShare, or FTP server, you need to establish a permanent IP address for your server and provide inbound port mapping information to your Apple wireless device. To set up inbound port mapping: 1 Open AirPort Utility, select your wireless device, and then choose Base Station > Manual Setup, or double-click the device icon to open its configuration in a separate window. Enter the password if necessary. 2 Click the Advanced button, and then click Port Mapping. 3 Click the Add (+) button and choose a service, such as Personal File Sharing, from the Service pop-up menu.Chapter 3 AirPort Network Designs 51 Type any additional information you need in the text fields. To use port mapping, you must configure TCP/IP manually on the computer that is running the web, AppleShare, or FTP server. You can also set up a computer as a default host to establish a permanent IP address for the computer and provide inbound port mapping information to the AirPort Extreme Base Station or AirPort Express. This is sometimes known as a DMZ and is useful when playing some network games or video conferencing. To set up a default host: 1 Open AirPort Utility, select your wireless device, and then choose Base Station > Manual Setup, or double-click the device icon to open its configuration in a separate window. Enter the password if necessary. 2 Click the Internet button, and then click NAT. 3 Select the “Enable Default Host at” checkbox. The default IP address is 10.0.1.253. 4 Enter the same IP address on the host computer. Logging You can set up your wireless device to log status information to the Mac OS X system log or the Syslog application on a Windows computer. This is helpful for understanding problems and monitoring a device’s performance. To set up logging: 1 Open AirPort Utility, select your wireless device, and then choose Base Station > Manual Setup, or double-click the device icon to open its configuration in a separate window. Enter the password if necessary. 2 Click the Advanced button, and then click Statistics.52 Chapter 3 AirPort Network Designs 3 Enter the IP address of the computer that will receive the logs in the Syslog Destination Address field. 4 Choose a level from the Syslog Level pop-up menu. You need to assign a Network Time Protocol (NTP) server for each wireless device, so the log information will contain the accurate time of the status logs. To set the time automatically: 1 Open AirPort Utility, select your wireless device, and then choose Base Station > Manual Setup, or double-click the device icon to open its configuration in a separate window. Enter the password if necessary. 2 Click the AirPort button, and then click Base Station. 3 Select the “Set time automatically” checkbox, and then choose an NTP server from the pop-up menu if you have access to one on your network or on the Internet. If you click “Logs and Statistics” you can view and export logs, and view wireless client and DHCP client information. If you export the logs, use the Mac OS X Console application, located in the Utilities folder in the Applications folder on a Mac, or in Start > All Programs > AirPort on a Windows computer, to view the logs on the computer receiving them. Using Back to My Mac on your Wireless Network If you have a paid MobileMe subscription (not a free trial), you can use Back to My Mac to access your AirPort Base Station or Time Capsule. You can access the base station or Time Capsule to monitor the network or make changes to the base station or Time Capsule settings. You can also access the hard disk built into the Time Capsule or an external USB hard disk connected to the base station or Time Capsule. To set up Back to My Mac on your wireless device: 1 Click MobileMe in the Advanced pane. 2 Enter your MobileMe account and password.Chapter 3 AirPort Network Designs 53 Setting up IPv6 IPv6 is a new version of Internet Protocol (IP). IPv6 is currently used primarily by some research institutions. Most computers do not need to set up or use IPv6. The primary advantage of IPv6 is that it increases the address size from 32 bits (the current IPv4 standard) to 128 bits. An address size of 128 bits is large enough to support billions and billions of addresses. This allows for more addresses or nodes than are currently available. IPv6 also provides more ways to set up the address and simpler autoconfiguration. By default, IPv6 is configured automatically, and the default settings are sufficient. However, if your network administrator or Internet service provider (ISP) has specifically told you to configure IPv6 manually, follow the instructions below. Open AirPort Utility, select your wireless device, and then choose Base Station > Manual Setup. Enter the password if necessary. Click the Advanced button, and then click IPv6. To manually set IPv6 options: 1 Choose Node or Tunnel from the IPv6 mode pop-up menu, depending on the method you were instructed to use. 2 Choose Manually from the Configure IPv6 pop-up menu, and enter the information you were given from your ISP or network administrator. Customizing the IPv6 firewall If your wireless device supports it, you can use AirPort Utility to adjust IPv6 firewall settings. To adjust IPv6 firewall settings: 1 Open AirPort Utility, located in the Utilities folder in the Applications folder on a Mac, or in Start > All Programs > AirPort on a Windows computer. 2 Select your device from the list, and then enter the password. 3 Click the Advanced button, and then click IPv6 Firewall By default, “Allow Teredo tunnels” and “Allow incoming IPSec authentication” are selected. To provide access to specific devices on your network from outside the IPv6 firewall, click the Add (+) button and enter the IPv6 address and/or the port for the device. To use an IPv6 firewall, you need an Apple 802.11n wireless device.54 Chapter 3 AirPort Network Designs Sharing and Securing USB Hard Disks on Your Network If you connect a USB hard disk to your AirPort Extreme Base Station or Time Capsule, computers connected to the network—both wireless and wired, Mac and Windows— can use it to back up, store, and share files. If you’re using a Time Capsule, you don’t need to connect a hard disk to it. Every Time Capsule includes an internal AirPort disk. To share a hard disk on your network: 1 Plug the hard disk into the USB port on the back of the AirPort Extreme Base Station or Time Capsule. 2 Open AirPort Utility, located in the Utilities folder in the Applications folder on a Mac, or in Start > All Programs > AirPort on a Windows computer. 3 Select your AirPort Extreme Base Station or your Time Capsule, and then choose Base Station > Manual Setup, or double-click the device icon to open its configuration in a separate window. Enter the password if necessary. 4 Click the Disks button, and then click File Sharing. 5 Choose “With a disk password,” or “With base station password” if you want to secure the shared disk with a password, or choose “With accounts” if you want to secure the disk using accounts.  If you choose to use accounts, click Configure Accounts, click the Add (+) button, and then enter a name and password for each user that will access the disk. 6 Choose “Not allowed,” “Read only,” or “Read and write” to assign guest access to the disk. 7 Select the “Share disks over Ethernet WAN port” checkbox if you want to provide remote access to the disk over the WAN port. Data transfer speed may vary, depending on the network. to Internet DSL or cable modem AirPort Extreme USB hard disk < Ethernet WAN port 2.4 or 5 GHz 2.4 or 5 GHzChapter 3 AirPort Network Designs 55 Using a Time Capsule in Your Network If you’re using a Time Capsule and a computer with Mac OS X Leopard (v10.5.2 or later), you can use Time Machine to automatically back up all of the computers on the network that are using Leopard. Other Mac computers and Windows computers can access the Time Capsule’s internal AirPort disk to back up, store, and share files. And because every Time Capsule is also a full-featured 802.11n base station, you can set up your Time Capsule to share an Internet connection with computers on the AirPort network it creates. For information about using your Time Capsule with Time Machine in Mac OS X Leopard, search for “Time Capsule” in Mac Help. Connecting a USB Printer to an Apple Wireless Device You can connect a compatible USB printer to your Apple wireless device (an AirPort Extreme Base Station, AirPort Express, or Time Capsule), so that anyone on the network using Mac OS X v10.2.3 or later, Windows XP with Service Pack 2, or Windows Vista can print to that printer. To use a printer on your network: 1 Connect the printer to the USB port on the Apple wireless device. 2 Set up the client computers:  On a computer using Mac OS X v10.5 or later, open System Preferences and click Print & Fax. Select the printer from the Printers list. If the printer isn’t in the list, click Add (+) at the bottom of the list, locate the printer, and then click Add.  On a computer using Mac OS X v10.2.3 or later, open Printer Setup Utility located in the Utilities folder in the Applications folder, and then select the printer from the list. If the printer is not in the list, click Add, choose Bonjour from the pop-up menu, and then select the printer from the list. to Internet DSL or cable modem Time Capsule < Ethernet WAN port 2.4 or 5 GHz 2.4 or 5 GHz 2.4 GHz56 Chapter 3 AirPort Network Designs  On a computer using Windows, install Bonjour for Windows from AirPort Utility CD, and follow the onscreen instructions to connect to the printer. You can change the name of the printer from the default name to one you choose. To change the name of your USB printer: 1 Open AirPort Utility, select your device, and then choose Base Station > Manual Setup, or double-click the device icon to open its configuration in a separate window. 2 Click the Printer button and type a name for the printer in the USB Printers field. Adding a Wireless Client to Your 802.11n Network If your Apple wireless device supports it, and your network is password-protected using WPA Personal or WPA/WPA2 Personal, you can provide wireless clients access to your network without requiring them to enter the network password. When you allow a client access to your network, the client’s name and wireless MAC address (or AirPort ID) are stored in the access control list of AirPort Utility until you remove them from the list. You can provide 24 hours of access, after which time the client will no longer be able to access your network. When you provide a client access to your wireless network, the client does not need to enter the network password. To allow client access to your network: 1 Open AirPort Utility, located in the Utilities folder in the Applications folder on a Mac, or in Start > All Programs > AirPort on a Windows computer. 2 Select your Apple wireless device and choose Base Station > Manual Setup. Enter the password if necessary. 3 Choose Add Wireless Clients from the Base Station menu. 4 Select how you want the client to access the network:  Select PIN to enter the eight-digit number provided by the client requesting network access.  Select “First attempt” to allow network access to the first client attempting to join the network.  Select “Limit client’s access to 24 hours” if you want to provide only one day of access to your network. If you don’t select this option, the client will have access to your network until you remove the name from the list.Chapter 3 AirPort Network Designs 57 Solving Problems If you have trouble connecting to the Internet with any AirPort Extreme network design, try the following: On a computer using Mac OS X:  Make sure the wireless device is connected to the Internet. The computers on your AirPort network cannot connect to the Internet if your device is not connected to the Internet.  Check your Internet connection using your computer. If you can’t connect with your computer, the problem may be with your Internet connection.  On a Mac using Mac OS X v10.5, check the active network services in the Network pane of System Preferences. Make sure the ports you want to use are active.  Open Network preferences and then click AirPort. Make sure that the computer has joined the AirPort network created by your wireless device.  Restart your computer. This renews the IP address you receive from the wireless device. The IP addresses should be in the range of 10.0.1.2 to 10.0.1.200, 172.16.1.2 to 172.16.1.200, or 192.168.1.2 to 192.168.1.200, depending on the address scheme the wireless device uses.  If the wireless device is set up as a DHCP server, make sure you choose “Share a public IP address” from the Connection Sharing pop-up menu on the Internet Connection pane of Internet settings in AirPort Utility.  If you’re using a cable modem and your wireless device cannot connect to the Internet, turn off the cable modem, wait a few minutes, and then turn it on again. On a computer using Windows:  Make sure the wireless device is connected to the Internet. The computers on your AirPort network cannot connect to the Internet if your device is not connected to the Internet.  Check your Internet connection using your computer. If you can’t connect with your computer, the problem may be with your Internet connection.  Right-click the wireless connection icon, and then choose Status.58 Chapter 3 AirPort Network Designs  Make sure that the computer has joined the AirPort network created by your wireless device.  Restart your computer. This renews the IP address you receive from the wireless device. The IP addresses should be in the range of 10.0.1.2 to 10.0.1.200, 172.16.1.2 to 172.16.1.200, or 192.168.1.2 to 192.168.1.200 depending on the address scheme the device uses.  If the device is set up as a DHCP server, make sure the “Obtain an IP address automatically” checkbox is selected in the General pane of Internet Protocol (TCP/IP) Properties. Right-click the wireless connection icon and click Properties. Click Internet Protocol (TCP/IP), and then click Properties. More Information About AirPort You can find more information about AirPort in the following locations:  AirPort Utility Help Look in AirPort Utility Help for information on setting up an AirPort Extreme network; using an AirPort Extreme Base Station, an AirPort Express, or a Time Capsule; editing settings; avoiding sources of interference; locating additional information on the Internet; and more. On a computer using Mac OS X, open AirPort Utility and choose Help > AirPort Utility Help. On a computer using Windows, open AirPort Utility and click Help.  World Wide Web Apple AirPort website at www.apple.com/airportextreme Apple Support website at www.apple.com/support/airport4 59 4 Behind the Scenes This chapter defines terms and concepts used to discuss computer networks. Use it as a reference to help you understand what is taking place behind the scenes of your AirPort wireless network. Basic Networking Packets and Traffic Information travels across a network in chunks called packets. Each packet has a header that tells where the packet is from and where it’s going, like the address on the envelope when you send a letter. The flow of all these packets on the network is called traffic. How Information Reaches Its Destination Hardware Addresses Your computer “listens” to all of the traffic on its local network and selects the packets that belong to it by checking for its hardware address (also called the media access control, or MAC address) in the packet header. This address is a number unique to your computer. Every hardware product used for networking is required to have a unique hardware address permanently embedded in it. Your AirPort Card’s number is called the AirPort ID. IP Addresses Since the Internet is a network of networks (connecting millions of computers), hardware addresses alone are not enough to deliver information on the Internet. It would be impossible for your computer to find its packets in all the world’s network traffic, and impossible for the Internet to move all traffic to every network.60 Chapter 4 Behind the Scenes So, your computer also has an Internet Protocol (IP) address that defines exactly where and in what network it’s located. IP addresses ensure that your local Ethernet network receives only the traffic intended for it. Like the hierarchical system used to define zip codes, street names, and street numbers, IP addresses are created according to a set of rules, and their assignment is carefully administered. The hardware address is like your name; it uniquely and permanently identifies you. But it doesn’t offer any clues about your location, so it’s only helpful in a local setting. An IP address is like your street address, which contains the information that helps letters and packages find your house. Rules for Sending Information (Protocols) A protocol is a set of rules that define how communication takes place. For instance, a networking protocol may define how information is formatted and addressed, just as there’s a standard way to address an envelope when you send a letter. Using the AirPort Extreme Base Station This section describes the different network interfaces of the AirPort Extreme Base Station and describes the functions the base station can provide. Base Station Interfaces To use the AirPort Extreme Base Station, you configure how its networking interfaces will be used. The AirPort Extreme Base Station has five hardware networking interfaces:  AirPort interface: The AirPort interface creates an AirPort network for AirPortenabled computers to join. The base station can provide IP services such as DHCP and NAT using this interface. The base station cannot use the AirPort interface to establish a connection with the Internet.  Ethernet WAN (<) interface: Use the Ethernet WAN interface to connect DSL or cable modems and connect to the Internet.  Ethernet LAN (G) interface: If your base station has one or more Ethernet LAN interface ports, you can use them to provide IP services to local Ethernet clients.  USB (d) interface: Use the USB interface to connect a USB printer or hard disk to the AirPort Extreme Base Station. Status light Ethernet WAN port Power port USB port Ethernet ports Reset button Security slot < G ¯ ∏ dChapter 4 Behind the Scenes 61 Using the Time Capsule This section describes the different network interfaces of the Time Capsule and describes the functions it can provide. Time Capsule Interfaces To use your Time Capsule, you configure how its networking interfaces will be used. The Time Capsule has five hardware networking interfaces:  AirPort interface: The AirPort interface creates an AirPort network for AirPortenabled computers to join. The Time Capsule can provide IP services such as DHCP and NAT using this interface. The Time Capsule cannot use the AirPort interface to establish a connection with the Internet.  Ethernet WAN (<) interface: Use the Ethernet WAN interface to connect DSL or cable modems and connect to the Internet.  Ethernet LAN (G) interface: The Time Capsule has three Ethernet LAN interface ports. You can use them to provide IP services to local Ethernet clients.  USB (d) interface: Use the USB interface to connect a USB printer to the Time Capsule. Using the AirPort Express This section describes the different network interfaces of the AirPort Express Base Station and describes the functions the base station can provide. AirPort Express Interfaces To set up the AirPort Express Base Station, you configure how its networking interfaces will be used. The AirPort Express Base Station has four hardware networking interfaces:  AirPort interface: The AirPort interface creates an AirPort network for AirPortenabled computers to join. The base station can provide IP services such as DHCP and NAT using this interface. The base station cannot use the AirPort interface to establish a connection with the Internet.  Ethernet WAN (<) interface: Use the Ethernet WAN interface to connect DSL or cable modems and connect to the Internet.  USB (d) interface: Use the USB interface to connect a USB printer to the AirPort Extreme Base Station. < G ≤ d ∏ Status light Ethernet WAN port Power port Reset button USB port Ethernet ports Security slot62 Chapter 4 Behind the Scenes  Audio (-) interface: Use the analog and optical digital audio stereo mini-jack to connect an AirPort Express to a home stereo or powered speakers. Apple Wireless Device Functions  Bridge: Each Apple wireless device is configured by default as a bridge between the wireless AirPort network and the wired Ethernet network. Connecting an AirPort network to an Ethernet network through the device’s Ethernet LAN port (G) bridges the wireless AirPort network to the wired Ethernet network. Important: If you’re connecting an Ethernet network to the device’s Ethernet LAN port (G), make sure the Ethernet network does not have an Internet connection.  NAT router: One of the most powerful features of Apple wireless devices is their ability to share one Internet connection with several computers. To provide this service, the device acts as a router. The device can be configured to provide both bridging services and routing services at the same time.  DHCP server: When you configure the wireless device to act as a DHCP server, it provides IP addresses to both wired and wireless client computers that are configured to obtain IP addresses using DHCP. Using DHCP makes IP configuration simple for client computers, since they don’t need to enter their own IP information. Status light AC plug adapter USB port Ethernet port Line Out port (Analog and optical digital audio mini-jack) Reset button G - d ∏Chapter 4 Behind the Scenes 63 Items That Can Cause Interference with AirPort The farther away the interference source, the less likely it is to cause a problem. The following items can cause interference with AirPort communication:  Microwave ovens  DSS (Direct Satellite Service) radio frequency leakage  The original coaxial cable that came with certain types of satellite dishes. Contact the device manufacturer and obtain newer cables.  Certain electrical devices, such as power lines, electrical railroad tracks, and power stations  Cordless telephones that operate in the 2.4 gigahertz (GHz) range. If you have problems with your phone or AirPort communication, change the channel of your base station.  Other AirPort and wireless networks  Adjacent base stations using nearby channels. If base station A is set to channel 1, base station B should be set to channel 6 or 11. For best results, use channels 1, 6, or 11 when operating your base station in the 2.4 GHz range.  Moving objects that temporarily place metal between your computer and the base stationGlossary 64 Glossary 10Base-T The most common cabling method for Ethernet. 10Base-T conforms to IEEE standard 802.3. It was developed to enable data communications over unshielded twisted pair (telephone) wiring at speeds of up to 10 megabits per second (Mbps) up to distances of approximately 330 feet on a network segment. 10/100Base-T A networking standard that supports data transfer rates up to 100 Mbps. Because it is 10 times faster than Ethernet, it is often referred to as Fast Ethernet. 10/100/1000Base-T A term describing various technologies for transmitting Ethernet packets at a rate of a gigabit per second. Sometimes referred to as Gigabit Ethernet. In 2000, Apple’s Power Mac G4 and PowerBook G4 were the first mass-produced personal computers featuring the 10/100/1000Base-T connection. It quickly became a built-in feature in many other computers. 802.11a An IEEE standard for a wireless network that operates at 5 GHz with rates up to 54 Mbps. 802.11b An IEEE standard for a wireless network that operates at 2.4 GHz with rates up to 11 Mbps. 802.11g An IEEE standard for a wireless network that operates at 2.4 GHz Wi-Fi with rates up to 54 Mbps. 802.11n A task group of the IEEE 802.11 committee whose goal is to define a standard for high throughput speeds of at least 100 Mbps on wireless networks. Some proposals being fielded by the task group include designs for up to 540 Mbps, Multiple-input multiple-output (MIMO) technology, using multiple receivers and multiple transmitters in both the client and access point to achieve improved performance, is expected to form the basis of the final specification. See Mbps, MIMO. access point Also known as a wireless access point (WAP), a device that connects wireless devices together to form a network. authentication The process that occurs after association to verify the identity of the wireless device or end user and allow access to the network. See WPA, WPA2.Glossary 65 backbone The central part of a large network that links two or more subnetworks. The backbone is the primary data transmission path on large networks such as those of enterprises and service providers. A backbone can be wireless or wired. bandwidth The maximum transmission capacity of a communications channel at any point in time. Bandwidth, usually measured in bits per second (bps), determines the speed at which information can be sent across a network. If you compare the communications channel to a pipe, bandwidth represents the pipe width and determines how much data can flow through the pipe at any one time. The greater the bandwidth, the faster data can flow. See bps. base station In the area of wireless computer networking, a base station is a radio receiver/transmitter that serves as the hub of the local wireless network, and may also be the gateway between a wired network and the wireless network. A base station can also be referred to as an access point or router. Bluetooth A technology designed for short-range, wireless communications among computing devices and mobile products, including PCs and laptop computers, personal digital assistants, printers, and mobile phones. Designed as a cable replacement, Bluetooth enables short-range transmission of voice and data in the 2.4 GHz frequency spectrum within a range of about 30 feet. bps Bits per second. A measure of data transmission speed across a network or communications channel; bps is the number of bits that can be sent or received per second. It measures the speed at which data is communicated and should not be—but often is—confused with bytes per second. Whereas “bits” is a measure of transmission speed, “bytes” is a measure of storage capacity. See bandwidth, Mbps. bridge A wireless device that connects multiple networks together. Using an access point as a bridge turns off Network Address Translation (NAT) and DHCP routing and simply extends the range of service. broadband A comparatively fast Internet connection possessing sufficient bandwidth to accommodate multiple voice, data, and video channels simultaneously. Cable, DSL, and satellite are all considered to be broadband channels; they provide much greater speed than dial-up Internet access over telephone wires. See cable modem, DSL. broadband modem A device that connects a local computer or network to a highspeed Internet service, such as DSL or Cable Internet. See cable modem, DSL. cable modem A device used with broadband Internet service provided by a traditional cable TV service. Cable modems convert analog data from the cable TV system into a digital format that can be used by a computer. See broadband modem.66 Glossary channel One portion of the available radio spectrum that all devices on a wireless network use to communicate. Changing the channel on the access point/router can help reduce interference. client Any computer or device connected to a network that requests files and services (files, print capability) from the server or other devices on the network. The term also refers to end users. DHCP Dynamic Host Configuration Protocol. A protocol for dynamically assigning IP addresses from a predefined list to nodes on a network. When they log on, network nodes automatically receive an IP address from a pool of addresses served by a DHCP. The DHCP server provides (or leases) an IP address to a client for a specific period of time. The client will automatically request a renewal of the lease when the lease is about to run out. If a lease renewal is not requested and it expires, the address is returned to the pool of available IP addresses. Using DHCP to manage IP addresses simplifies client configuration and efficiently utilizes IP addresses. See IP address. DNS Domain Name System. An Internet service that translates alphanumeric domain names to assigned IP addresses and vice versa. The term is typically used to describe the server that makes the translation. Every website has its own specific IP address on the Internet. DNS typically refers to a database of Internet names and addresses that translates the alphanumeric names to the official Internet Protocol numbers and vice versa. For instance, a DNS server converts a name like mywebsite.com to a series of numbers like 107.22.55.26. See IP, IP address. DSL Digital Subscriber Line. A dedicated digital circuit between a residence or business and a telephone company’s central office. It allows high-speed data, voice, and video transmissions over existing twisted-pair copper plain old telephone service (POTS) telephone wires. See broadband. dual-band A device that is capable of operating in either of two frequencies. On a wireless network, dual-band devices are capable of operating in the 2.4 GHz (802.11b/g) or 5 GHz (802.11a) bands. encryption A mechanism for providing data confidentiality. See WPA, WPA2. Ethernet The most popular international standard technology for wired local area networks (LANs). It provides from 10 Mbps transmission speeds on basic 10Base-T Ethernet networks to 100 Mbps transmission speeds on Fast Ethernet networks, 1000 Mbps on Gigabit Ethernet, and 10,000 Mbps on 10 Gigabit Ethernet.Glossary 67 firewall A system of software and/or hardware that resides between two networks to prevent access by unauthorized users. The most common use of a firewall is to provide security between a local network and the Internet. Firewalls can make a network appear invisible to the Internet and can block unauthorized and unwanted users from accessing files and systems on the network. Hardware and software firewalls monitor and control the flow of data in and out of computers in both wired and wireless enterprise, business and home networks. They can be set to intercept, analyze, and stop a wide range of Internet intruders and hackers. gateway In the wireless world, a gateway is an access point with additional software capabilities such as providing NAT and DHCP. Gateways may also provide VPN support, roaming, firewalls, various levels of security, and so on. hotspot A location where users can access the Internet using Wi-Fi laptops and other Wi-Fi enabled devices. Access may be provided free or for a fee. Hotspots are often found at coffee shops, hotels, airport lounges, train stations, convention centers, gas stations, truck stops, and other public meeting areas. Corporations and campuses often offer hotspot service to visitors and guests. Hotspot service is sometimes available aboard planes, trains, and boats. hub A multiport device used to connect client devices to a wired Ethernet network. Hubs can have numerous ports and can transmit data at speeds ranging from 10 to 1000 Mbps to all the connected ports. A small wired hub may only connect 4 computers; a large hub can connect 48 or more. See router. IEEE 802.11 The family of specifications developed by the Institute of Electrical and Electronics Engineers (IEEE) 802.11 committee, which establishes standards for wireless Ethernet networks. 802.11 standards define the over-the-air interface between wireless clients and a base station, or an access point that is physically connected to the wired network. IP Internet Protocol. The basic communications protocol of the Internet. See IP address, TCP/IP. IP address Internet Protocol address. IP Version 4, the most widely used Internet protocol, provides a 32-bit number that identifies the sender or receiver of information sent across the Internet. An IP address has two parts: The identifier of the particular network on the Internet and the identifier of the particular device (which can be a server or a workstation) within that network. The newer IP, Version 6, provides a 128-bit addressing scheme to support a much greater number of IP addresses. See DHCP, DNS, IP. IP subnet An IP subnet is a local network as defined by IP network numbers. Connecting to a subnet involves connecting to the appropriate hardware network and configuring IP for that network.68 Glossary LAN Local area network. A system of connecting PCs and other devices within the same physical proximity for sharing resources such as an Internet connections, printers, files, and drives. When Wi-Fi is used to connect the devices, the system is known as a wireless LAN or WLAN. See WAN. MAC address Media Access Control address. A unique hardware number that identifies each device on a network. A device can be a computer, printer, and so on. A MAC address is also known as an AirPort ID. Mbps Megabits per second. A measurement of data speed equivalent to a million bits per second. MIMO Multiple-input multiple-output. An advanced signal processing technology that uses multiple receivers and multiple transmitters in both the client and access point to achieve data throughput speeds of 100 Mbps. See 802.11n. NAT Network Address Translation. A network capability that enables multiple computers to dynamically share a single incoming IP address from a dial-up, cable, or DSL connection. NAT takes a single incoming public IP address and translates it to a new private IP address for each client on the network. See DHCP, IP address. network name A name used to identify a wireless network. See SSID. NIC Network interface card. A wireless or wired PC adapter card that allows the client computer to utilize network resources. Most office-wired NICs operate at 100 Mbps. Wireless NICs operate at data rates defined by 802.11 standards. packet A unit of information transmitted from one device to another on a network. A packet typically contains a header with addressing information, data, and a checksum mechanism to ensure data integrity. pass phrase A series of characters used to create a key that is used by Wi-Fi Protected Access (WPA). See PSK, WPA. print server A network device, often a computer, that connects to at least one printer, allowing it to be shared among computers on a network. PSK Pre-shared key. A mechanism in Wi-Fi Protected Access (WPA)-Personal that allows the use of manually entered keys or passwords to initiate WPA security. The PSK is entered on the access point or home wireless gateway and each PC that is on the Wi-Fi network. After entering the password, Wi-Fi Protected Access automatically takes over. It keeps out eavesdroppers and other unauthorized users by requiring all devices to have the matching password. The password also initiates the encryption process which, in WPA is Temporal Key Integrity Protocol (TKIP) and in WPA2 is Advanced Encryption Standard (AES). See TKIP, WPA-Personal, WPA2-Personal.Glossary 69 roaming (Wi-Fi) The ability to move from one area of Wi-Fi coverage to another with no loss in connectivity (hand-off). router A wireless router is a device that accepts connections from wireless devices to a network, includes a network firewall for security, and provides local network addresses. See hub. server A computer that provides resources or services to other computers and devices on a network. Types of servers include print servers, Internet servers, mail servers, and DHCP servers. A server can also be combined with a hub or router. See DHCP, hub, router. SSID Service set identifier. A unique 32-character network name, or identifier, that differentiates one wireless LAN from another. All access points and clients attempting to connect to a specific WLAN must use the same SSID. The SSID can be any alphanumeric entry up to a maximum of 32 characters. See network name. subnet An IP address range that is part of a larger address range. Subnets are used to subdivide a network address of a larger network into smaller networks. Subnets connect to other networks through a router. Each individual wireless LAN will typically use the same subnet for all of its clients. See IP address, router. TCP Transmission Control Protocol. The transport-level protocol used with the Internet Protocol (IP) to route data across the Internet. See IP, TCP/IP. TCP/IP The underlying technology of Internet communications. While IP handles the actual delivery of data, TCP tracks the data packets to efficiently route a message through the Internet. Every computer in a TCP/IP network has its own IP address that is either dynamically assigned at startup (see DHCP) or permanently assigned as a static address. All TCP/IP messages contain the address of the destination network, as well as the address of the destination station. This enables TCP/IP messages to be transmitted to multiple networks (subnets) within an organization or worldwide. For example, when a user downloads a webpage, TCP divides the page file on the web server into packets, numbers the packets, and forwards them individually to the user’s IP address. The packets may be routed along different paths before reaching the user’s address. At the destination, TCP reassembles the individual packets, waiting until they have all arrived to present them as a single file. See IP, IP address, packet, TCP. throughput Usually measured in bps, Kbps, Mbps or Gbps, throughput is the amount of data that can be sent from one location to another in a specific amount of time. See bps, Mbps. USB Universal Serial Bus. A high-speed bidirectional serial connection used to transfer data between a computer and peripherals such as digital cameras and memory cards. 70 Glossary WEP Wired equivalent privacy. The original security standard used in wireless networks to encrypt the wireless network traffic. See WPA, Wireless local area network. Wi-Fi A term developed by the Wi-Fi Alliance to describe wireless local area network (WLAN) products that are based on the Institute of Electrical and Electronics Engineers. Wi-Fi Certified The certification standard designating IEEE 802.11-based wireless local area network (WLAN) products that have passed interoperability testing requirements developed and governed by the Wi-Fi Alliance. wireless network Devices connected to a network using a centralized wireless access point. See WLAN. WLAN A data communications network that spans large local, regional, national, or international areas and is usually provided by a public carrier (such as a telephone company or service provider).The term is used to distinguish between phone-based data networks and Wi-Fi networks. Phone networks are considered wide area networks (WANs) and Wi-Fi networks are considered wireless local area networks (WLANs). See LAN. WPA - Enterprise Wi-Fi Protected Access-Enterprise. A wireless security method that provides strong data protection for multiple users and large managed networks. It uses the 802.1X authentication framework with TKIP encryption and prevents unauthorized network access by verifying network users through an authentication server. See 802.1X. WPA - Personal Wi-Fi Protected Access-Personal. A wireless security method that provides strong data protection and prevents unauthorized network access for small networks. It uses TKIP encryption and protects against unauthorized network access. WPA2 Wi-Fi Protected Access 2. The follow-on security method to WPA for wireless networks that provides stronger data protection and network access control. It provides enterprise and consumer Wi-Fi users with a high level of assurance that only authorized users can access their wireless networks. Based on the ratified IEEE 802.11i standard, WPA2 provides government grade security by implementing the National Institute of Standards and Technology (NIST) FIPS 140-2 compliant AES encryption algorithm and 802.1X-based authentication. There are two versions of WPA2: WPA2- Personal and WPA2-Enterprise. WPA2-Personal protects unauthorized network access by utilizing a set-up password. WPA2-Enterprise verifies network users through a server. WPA2 is backward compatible with WPA. Like WPA, WPA2 uses the 802.1X/EAP framework as part of the infrastructure that ensures centralized mutual authentication and dynamic key management and offers a pre-shared key for use in home and small office environments. Like WPA, WPA2 is designed to secure all versions of 802.11 devices, including 802.11b, 802.11a, and 802.11g, multiband and multimode. See WPA2- Enterprise, WPA2-Personal.Glossary 71 WPA2 - Enterprise Wi-Fi Protected Access 2 - Enterprise. The follow-on wireless security method to WPA that provides stronger data protection for multiple users and large managed networks. It prevents unauthorized network access by verifying network users through an authentication server. See WPA2. WPA2 - Personal Wi-Fi Protected Access 2 - Personal. The follow-on wireless security method to WPA that provides stronger data protection and prevents unauthorized network access for small networks. See WPA2, PSK.www.apple.com/airportextreme www.apple.com/airport © 2009 Apple Inc. All rights reserved. Apple, the Apple logo, AirPort, AirPort Extreme, AppleShare, AppleTalk, Back to My Mac, Bonjour, Mac, and Mac OS are trademarks of Apple Inc., registered in the U.S. and other countries. AirPort Express, AirTunes, Time Capsule, and Time Machine are trademarks of Apple Inc. Other product and company names mentioned herein may be trademarks of their respective companies. 019-1257 Time Capsule3  5 1 7 Time Capsule 8  AirPort  9  11 Time Capsule 13 2 Time Capsule 14 Time Capsule  17  AirPort  19  19  ! Internet " 21 #$%& 22 '()*+,-./0"12 23 3Time Capsule 4 Time Machine 25 3 25 5627"1 Internet 25 56289-.:Time Capsule -. 26 56Time Capsule ;<=> 27 56Time Capsule  ?@ABC4 28 56DEF;<=> 29 G AirPort  29 HITime Capsule JKLM 30 NO AirPort PQR& 31 4 33 Time Capsule 36 Regulatory Compliance Information1 5 1  Time Capsule Time Capsule Time Capsule 0S2TUL#V Wi-Fi WXYZ[\❡ Mac OS X v10.5.2 Leopard :^4_`a Time Machine >❝0^TcLd4 eZ[ 4e 23 ? ➋A Time Capsule 5 Time Machine➌❡  Ÿ-. ¡¢£"1 Internet❝Sžfg Wi-Fi Z ⑧5 iPhone❞iPod touch  Apple TV⑨kl ! Internet "❡2¤0^3"1h fg¥¦ !§¨❡  <-. ¡:;<-. ¡©ª❝«¬d­< Internet "®¯ z{°±K ⑧ˆ5fg❞iPhone❞iPod touch  Apple TV⑨❡  d Time Capsule "1h2›œ❡pZtu Macintosh❞ Windows XP : Windows Vista fg™š1❝/u"1s‚❡  d²³ USB DEF"1h2 Time Capsule❡AirPort 4e<“”fg ⑧<:⑨´u"1hµDEF#V¶D❡  d·1 USB ¸¹"1h2 Time Capsule 4❡AirPort 4e<“”fg ⑧<:⑨´uº»¸¹¼½¾❡ 1  7  d USB ¿À"1h Time Capsule 4❝ÁÂÃ"1Ă USB Z ⑧5DEF: ¸¹⑨❡4e / ➝§¨I¼❤56n Windows XP : Windows Vista fg❝FnB [ J ] > [ e< ] > AirPort ¼❡ -./01( Time Capsule ÷ðZKL❝'()*"1❡ý: ;< 22 ì➋'()*+,-./0"12 ➌❡ /2 13 2  Time Capsule Time Capsule Internet AirPort `Mdz{ê¶N\OP✐dTime Capsule "1 Internet❝^ ➜AirPort ➝¼QR2 Time Capsule žtu❡5G Ä“½Q❝^ ➜AirPort ➝#$tu“½Q❝ý:; www.apple.com/tw/support/airport S4 ➜ AirPort T AirPort  ⑧Mac OS X v10.5 + Windows⑨➝❡ 32ç±q Time Capsule ãä¥å¹4 ➜AirPort ➝¥Â❝2K0^  ➜AirPort ➝¼QRUVVoWpK\ X❡íî#$%&❝ý3 ➜AirPort ➝ ➜wLx➝%ia%D ➜þY➝❡ý:;< 21 ì ➋#$%&➌❡14  2  Time Capsule Time Capsule ~2 Time Capsule z{ Internet "l❝ê¶fgZdu"1  AirPort  !§¨❞YZ[❝^ Internet > ⑧ˆ5\ ]Àf^_`>⑨✐  pZ ➜AirPort ø➝ ➜AirPort Extreme ø➝ Macintosh fg  pZ 802.11a❞802.11b❞802.11g  IEEE 802.11n draft ñòtufg  ž Wi-Fi Z ›œ"1 Time Capsule fgm0º» !§¨^"1 Internet❡ í2ç±q Mac OS X v10.5.2 :^4_`❝2K0^Time Machine d4 e / ➝§¨ I¼❤^Windows fg [ J ] > [ e< ] > AirPort ¼⑨❝%D2 Time Capsule❝ÁÂ×jê ➜e*➝❡ 4 èéfg4 +h❡ 5 Mac OS X v10.5 6789:;<✐ 1 ý%D ➜i6➝ > ➜j♠➝❝ÁÂ×jê ➜¶DÊl➝❡ 2 ×jê ➜Ž,➝⑧+⑨❝ÁÂ3¶E¼%D2DEF❡ 3 ×jê ➜Ž,➝×Ø❡ 56¶Ea;<á DEF❝ý¶4×ØmnDEF❡ 5 Mac OS X v10.3 ,10.4 6789:;<✐ 1 c ➜DEF➝⑧B ➜> / ➝§¨Io⑨❡ 2 %D¶EaDEF❡ 56¶Ea;<á DEF❝ý×jê ➜Ž,➝£A%ia%D Bonjour❝ Á¶Ea%DDEF❡ =>Windows XP , Vista 679:;<✐ 1 ý Time Capsule ãäå¹4ç± Windows _` Bonjour❡ 2 ýèéfg4 +h"1h2DEF❡  AirPort fg:ž“”ø:p1øfg❝d0™š Time Capsule "1 Internet❡"1h Time Capsule ›œËfgm0º»" 1 Internet❡ 2  Time Capsule 17 ™š Time Capsule❝fg"1h›œËfgmu“q#VPQ❡ AirPort íî£pK2 Time Capsule❝ý ➜AirPort ➝¼QR ❡➜AirPort ➝€32ç± Time Capsule å¹4lj"ç±❡ 5 Mac OS X v10.4 ,8?@ Macintosh 678✐ 1 c ➜AirPort ➝⑧B ➜> / ➝§¨Io⑨❡ 2 %D2 Time Capsule ÁÂ×jê [ e*]❡ 56; [ e< ] > AirPort⑨❡ 2 %D2 Time Capsule ÁÂ×jê [ e*]❡18  2  Time Capsule 3 ýèéfg4 +h Time Capsule 2❡ ➜AirPort ➝¼QR€vÝ2jƓÝÞ❝wxî y‹2îz{❝£€|R2+,ö❡ 562î Time Capsule "1 Internet❝2óô} Internet z{{>~ ⑧ISP⑨ý—} ⑧DSL :ÎÏÐF⑨€ ❝:n™šÑ<›œ"1 Internet❡í2 ISP 1h‚½Q ⑧5ƒ IP B„: DHCP )* ID⑨❝0 uî3 ➜AirPort ➝a+,ÅƽQ❡32 Time Capsule l❝ý9 êÅƽQ^Zd❡ 2  Time Capsule 19 20^ ➜AirPort ➝¼QR❡Q Rd…†2UVóô‡ˆ'‰Š❞-. ¡❝ž&â ❡ í2î34 ! USB DEF: USB ¸¹✐ 1 dDEF:¸¹"1h Time Capsule  USB Ë ⑧d⑨❡ 2 c ➜AirPort ➝⑧B Macintosh fg4 ➜> / ➝§ ¨I¼❤:Windows XP fg [ J ] > [ e< ] > AirPort ¼⑨❡ 3 %D2 Time Capsule ÁÂ×jê [ e*]❡ 56; / ➝§¨ I¼❤56nWindows XP fg❝FnB [ J ] > [ e< ] > AirPort ¼⑨❡ 2 %D2 Time Capsule ÁÂ×jê [ e*]❡ í2%3G÷ Time Capsule❝20uî"1÷❝Á ÂÃG Time Capsule ❡ íî3 Macintosh fg4%D2îG❝ý%i¶a AirPort %i❡3Windows XP fg4❝dŽ ï3"‘ 4❝ $h2r’Š“ (SSID) '(❝í”iaÑĂ❝ý%D2❡ 3 ýèéfg4 +h ! Time Capsule  Internet "❡ ➜AirPort ➝z{Tc Time Capsule à7❡562î ž%&❝5¯•"❝:n#$ DHCP %&❝ý ➜AirPort ➝ ➜wLx➝%ia%D ➜þY➝❡ 2  Time Capsule 21 í2î#$ Time Capsule %& ⑧5#$çW%&❞–—❞DHCP ˜ ™l¦❞"®¯•❞fûü❞3€ ^ž⑨❝ý ➜AirPort ➝þY Time Capsule❡ 9F"G✐ 1 c ➜AirPort ➝⑧B Macintosh fg4 ➜> / ➝§ ¨I¼❤^Windows XP fg [ J ] > [ e< ] > AirPort ¼⑨❡ 2 í¶EaÑĂZ❝ý%D2îZ❡56;❝20^Z[fg4e<& â❝w¬2é­❞®¯❞°­±`❡32dTime Machine r#Â❝€ ªXYZ[2fg❡ 562n Mac OS X v10.5.2 :^4_`❝~2²H"1 Time Capsule l❝Time Machine €vÝ2n³îZ[2§¨❡ý×jê ➜\'Z[´¹➝❝ ÁÂTime Machine €XYr#µêY\❡  Mac OS X Leopard ➜j➝ Time Machine ÈCXYZ[❞ ¶j‚Z[´¹❝:nsž❡ 5 Mac OS X Leopard 678,VWTime Machine✐ 1 ý%D ➜i6➝ > ➜j♠➝❝ÁÂ×jêTime Machine❡ 2 dh ➜➝❡ 3 ×jê ➜G´¹➝❡ 4 %D2 Time Capsule £×jê ➜Z[➝❡24  2  Time Capsule ·Z[½¾I¸❝2 ➜Mac QR+h➝❝ÁÂ3mnÆBa+, Time Machine❡3 25 3 XYZ[\]^ Time Capsule Internet  ý£G$12fg"1 Internet❡5627"1❝ý&2n%& ❡56%&❝Ǥn7"1❝ýÈÉ2 Internet  z{{>~ ⑧ISP⑨❡  ý&2"1n%&❡ Time Capsule 20^ÖK Time Capsule ”Ÿ AirPort -.: Time Capsule -.❡ _` Time Capsule PQ✐ 1 ÊËÌ ⑧ˆ58^Í⑨×ÎÖK×Øj ❡ 7k lmnolpqrst❝u+,Y vwx❡26  3  2 %D2 AirPort ❡  5 Macintosh 678❝%i¶a AirPort %i%D Time Capsule  ⑧Š“€Ï⑨❡  5Windows XP ab678❝dŽ ï3"‘ 4❝$h2 r’ [AirPort Š“ ] (SSID) '(❝í”iaÑĂ❝ý%D2 AirPort ❡ 3 c ➜AirPort ➝⑧B Macintosh fg4 ➜> / ➝§ ¨I¼❤^Windows XP fg [ J ] > [ e< ] > AirPort ¼⑨❡ 4 %D2 Time Capsule❝£ ➜wLx➝%ia%D ➜þY➝❡ 5 ׶a AirPort jê❝ÁÂ×jê ➜wLx➝❡ 6 +, Time Capsule -.❡ 7 ×jê ➜➝£ ➜çWЛ➝A%ia%DŽ-àŽ- tu❝£–'2 AirPort Y-. ¡❡íqŽ-tu❝ý+, AirPort -.❡ 8 × ➜G➝jêÖY Time Capsule❝£–Ñ,❡ Time Capsule GÒd AirPort Extreme fÓÂ❝ÃÖd=❡ í Time Capsule rW(=>❝20uîdwLxÖK'ÔÕÖ❡ / Time Capsule noyz{|Y}~v€‚Vƒ„Y ❝… v/ Time Capsule noyz{|Y}❡ 3  27 c Time Capsule defghi✐ m ÊËÌ⑧ˆ58^Í⑨×ÎÖK×Ø❝$h „?@'(⑧™ 5 ⑨❡ Time Capsule d€^ê¶ÖK✐  Time Capsule € DHCP 1 IP B„❡  Š“d€ÖK# ➜Apple Network XXXXXX➝⑧a XXXXXX €^ AirPort ID a Â×.».⑨❡  Time Capsule -.€ÖK# public❡ k Time Capsule lmnopq❝rst;uv✐ 1 ÓØ Time Capsule f❡ 2 ~2, Time Capsule l❝ýÊËÌ×ÎÖK×Ø❡ Time Capsule 0un›œ;<1❝Time Capsule ¡ AirPort PQÙÚ❝:n Internet z{{>~ ⑧ISP⑨ÛÕ45qÝÞ❡562n DSL :ÎÏÐ F"1 Internet❝m0unÏÐF: Internet ¥¦"÷6aÜ❡œ ÏÐFr"?\%@❝mý£GaÜÏÐFf❝¤ÝÞ ¥ÂÃÖ" 1❡3Ö14ÏÐFf¥ß❝ý& Time Capsule n™š›œ$1 "1hÏÐF4❡28  3  5GÄ ?@89“½Q❝ýc ➜AirPort ➝❝%D2 Time Capsule❝Á ➜wLx➝%ia%D ➜þY➝❡×jê ➜wLx ➝á ?@“½Q❡ 2m0^3 AirPort j¼%D ➜·wLxn³<ÝÞ➝❡56wLx4 5ÝÞ❝➜AirPort ➝€❝£|R2ÙÚÝÞ❡ í2÷dDEF"1h Time Capsule 4 USB Ë❝Çn AirPort 4fg7 #V¶D❝ýUV궇ˆ✐ 1 &÷14£÷DEF❡ 2 &1÷ßß14DEF Time Capsule 4 USB Ë❡ 3 &÷3)*fg4 ➜DEF¶E➝·à¼%DDEF❡ 5 Mac OS X v10.5 ,8?@ Macintosh 678✐  ý%D ➜i6➝ > ➜j♠➝❝ÁÂ×jê ➜¶DÊl➝❡  ×jê ➜Ž,➝⑧+⑨£%D¶EaDEF❝ÁÂ×jê ➜Ž,➝⑧+⑨❡ 5 Mac OS X v10.2.7 ,8?@ Macintosh 678✐  c ➜DEF➝⑧B ➜> / ➝§¨Io⑨❡  íDEF3¶E¥o❝ý× ➜Ž,➝jê❡  A%ia%D Bonjour❝%DDEF❝ÁÂ×jê ➜Ž,➝⑧+⑨❡ 3  29 5Windows XP 678✐   [ J ] tuEac [ ¶DÊl ]❡  %DDEF❡í”ia2ÑDEF❝× [ áDEF ] jê❝ÁÂèéfg4 +h #V❡ 4 —DEF❝¤ÝÞ ¥ÂÃÖYDEF❡ AirPort Apple €ªz{G AirPort ❡â2G Time Capsule  ❡ 20^3 AirPort j¼%D ➜~c AirPort lãäG&â➝: ➜ãäG&â➝❡562å% ➜ãäG&â➝❝ý3A%i¼%Dj‚ æªl¦ ⑧ˆ5¼æ⑨❝«¬XYãäG&â❡ Time Capsule ê¶âR&0|R2 Time Capsule çhPQÙڐ‘è éêÙÚ❡  d2 Time Capsule KëìÌ ⑧5í:îï⑨‰ðJñe❡òIî SóôõöEÈ❡  í2d Time Capsule KíÂà❝ýS Time Capsule íÕ÷¥¦ )ú ð 2.5 øW ⑧1 ùú⑨ûü❡  ýþd2 Time Capsule JK3<ÒÈ^4õöÈñe❡30  3   í2d Time Capsule K¬®Z¯a❝>ýþ Time Capsule  Ò®❞·Q:f❡d21¿aJK Time Capsule j ❡ 0uS Time Capsule 1¥¦ÕV ¦❡  ± Time Capsule BK❝>ûü ❞2.4 : 5 gigahertz ⑧GHz⑨f ^žNOð 7.6 ø ⑧25 ù⑨❡  ýdžÌ` ⑧❞❞ ̤⑨J3Time Capsule 4È❡Ž€N OTime Capsule ❡ AirPort ûüNO❝uð#ÝÞ0u•❡ ê¶&â0u€NO AirPort PQ✐   $z{ ⑧DSS⑨f}  !Æy‹¹‹¨eãäk"fÎ❡ýZ#~ÈÉ^»b‹ fÎ❡  !Æf$%❝ˆ5f❞f&è'()^4fÔ¤   2.4 : 5 GHz }*f❡562f: AirPort PQ45ÝÞ❝ý GwLx: Time Capsule e})❝:Gfe})❡  “ôwLx“+})❡ˆ5❝56wLx A '}) 1❝wLx B K>'}) 6 :}) 11❡4 31 4 wxyz❞|}~€ Time Capsule 5 Time Capsule “½Q❝ýß, www.apple.com/tw/airport S❡ íî-. Time Capsule⑧56~²23ç± Time Capsule å¹4l£2- .⑨❝ýß, www.apple.com/tw/register S❡ 5 AirPort ²³½Q❞‚/0½Q3/’12Ó❝^ Apple  êÑ❝ýß, www.apple.com/tw/support/airport S❡ 534^·²³z{❝ýß, www.apple.com/tw/support S❝£%D2 4¢:LÓ❡32  4  íî7ÙGÄ3 Time Capsule 4 ➜AirPort ➝“½Q❝ýc ➜AirPort ➝£%D ➜QR+h➝ > ➜AirPort QR+h➝❡ í2 Time Capsule Û567:n7%@?\❝ýèé`þ.a+h ❞ fgQR+h4½ü❡ í Time Capsule 8Á7,9?\❝ýß, www.apple.com/tw/support S^7 Ù5»b ƒz{½Q❡ Time Capsule 2 Time Capsule :oD<- ❡33 Time Capsule ‚ƒ„~C… †‡ Time Capsule  ˆ‰Š‹✐2.4  5 GHz  LŒMf3‹✐ƒ 23 dBm ⑧;⑨  Ž✐802.11 DSSS 1  2 Mbps ïð❝802.11a❞802.11b❞802.11g ñò draft 802.11n ñò  1 RJ-45 10/100/1000Base-T Gigabit ›œ WAN ⑧<⑨  3 RJ-45 10/100/1000Base-T Gigabit ›œ LAN ⑧G⑨  P-¶<=> ⑧USB d⑨ 2.0  802.11 a/b/g/n AirPort Extreme   v‘✐0° C ú 35° C ⑧32° F ú 95° F⑨  ’“‘✐–25° C ú 60° C ⑧–13° F ú 140° F⑨  ”•–‘ ⑧v—⑨✐20% ú 80%  ”•–‘ ⑧’“—⑨✐10% ú 90%❝?@A 34 ˜ Time Capsule  ™‘✐197.0 øB ⑧7.75 ùú⑨  š‘✐197.0 øB ⑧7.75 ùú⑨  ›‘✐36.33 øB ⑧1.43 ùú⑨  _œ✐1.6 øC ⑧3.5 ùD⑨ MAC Time Capsule :oD<҂¸B„✐  AirPort ID✐Ł‚B„nEF4 Time Capsule❡  žNO ID✐íîd Time Capsule "1 Internet❝20uîz{µB„½Q° 2 ISP❡ Time Capsule  d Time Capsule frW—Gjà7naÜf❡  ~"1:ÓØ Time Capsule l❝ý{óHÎI❡îSþ óôI õöo[❡  2n89❝œn Time Capsule ;<14f❝´0^dJÙ❡í 2 Time Capsule îz{❝ý:;< 31 ì ➋GÄ+h❞z{²³➌❡  ý Vd1I,Ê+Ëa❡í27^öü%$d1I,Ê+Ëa❝ ÛK«ñò0u£“õ❡ý&21IÊ+ËL¬“õ❝–2nd 1I, >Ê+Ëa❡˜ Time Capsule 35  ~2 Time Capsule l❝·MN Oƒn%@ÑP❡Time Capsule ·M <t❝uʆooQ`N❝4ú·o‰R &a❡  S Time Capsule üS❝5T¾❞UV❞WX❞YW¦¤ñe❡  ý ¡ Time Capsule❝ýþŸhZå$[❝£–ýþ9\]:ž9^¸Ÿ _❡  ý îS`Ì:Sab32 Time Capsule 4❡í454PcË❝ ýӟfÔüabS❡  ýî3d· Time Capsule❡Time Capsule nTdo/0❡ 3KJ:¿elíü~❝0u€ Time Capsule #6f❡~23?Œš a❝ý îgh Time Capsule❡ !†‡ˆ0‰Š‹ŒŽ❝(A‘’“”•–ƒ  Time Capsule❡ (—˜™š  Time Capsule ›œ/žŸ❡7a/Œˆ0 ¡… ¢„£¤¥¦§x¨❡AirPort Express ©ª…^«h¬­®¯°❡36 Regulatory Compliance Information Wireless Radio Use This device is restricted to indoor use due to its operation in the 5.15 to 5.25 GHz frequency range to reduce the potential for harmful interference to cochannel Mobile Satellite systems. Cet appareil doit être utilisé à l’intérieur. Exposure to Radio Frequency Energy The radiated output power of this device is well below the FCC and EU radio frequency exposure limits. However, this device should be operated with a minimum distance of at least 20 cm between its antennas and a person’s body and the antennas used with this transmitter must not be colocated or operated in conjunction with any other antenna or transmitter subject to the conditions of the FCC Grant. FCC Declaration of Conformity This device complies with part 15 of the FCC rules. Operation is subject to the following two conditions: (1) This device may not cause harmful interference, and (2) this device must accept any interference received, including interference that may cause undesired operation. See instructions if interference to radio or television reception is suspected. Radio and Television Interference This computer equipment generates, uses, and can radiate radio-frequency energy. If it is not installed and used properly—that is, in strict accordance with Apple’s instructions—it may cause interference with radio and television reception. This equipment has been tested and found to comply with the limits for a Class B digital device in accordance with the specifications in Part 15 of FCC rules. These specifications are designed to provide reasonable protection against such interference in a residential installation. However, there is no guarantee that interference will not occur in a particular installation. You can determine whether your computer system is causing interference by turning it off. If the interference stops, it was probably caused by the computer or one of the peripheral devices. If your computer system does cause interference to radio or television reception, try to correct the interference by using one or more of the following measures:  Turn the television or radio antenna until the interference stops.  Move the computer to one side or the other of the television or radio.  Move the computer farther away from the television or radio.  Plug the computer into an outlet that is on a different circuit from the television or radio. (That is, make certain the computer and the television or radio are on circuits controlled by different circuit breakers or fuses.) If necessary, consult an Apple Authorized Service Provider or Apple. See the service and support information that came with your Apple product. Or, consult an experienced radio/television technician for additional suggestions. Important: Changes or modifications to this product not authorized by Apple Inc. could void the EMC compliance and negate your authority to operate the product.37 This product was tested for FCC compliance under conditions that included the use of Apple peripheral devices and Apple shielded cables and connectors between system components. It is important that you use Apple peripheral devices and shielded cables and connectors between system components to reduce the possibility of causing interference to radios, television sets, and other electronic devices. You can obtain Apple peripheral devices and the proper shielded cables and connectors through an Apple-authorized dealer. For non-Apple peripheral devices, contact the manufacturer or dealer for assistance. Responsible party (contact for FCC matters only) Apple Inc., Corporate Compliance, 1 Infinite Loop M/S 26-A, Cupertino, CA 95014-2084 Industry Canada Statement This Class B device meets all requirements of the Canadian interference-causing equipment regulations. Cet appareil numérique de la Class B respecte toutes les exigences du Règlement sur le matériel brouilleur du Canada. VCCI Class B Statement Europe—EU Declaration of Conformity For more information, see www.apple.com/euro/ compliance. European Union — Disposal Information This symbol means that according to local laws and regulations your product should be disposed of separately from household waste. When this product reaches its end of life, take it to a collection point designated by local authorities. Some collection points accept products for free. The separate collection and recycling of your product at the time of disposal will help conserve natural resources and ensure that it is recycled in a manner that protects human health and the environment. Disposal and Recycling Information This product has an internal battery. Please dispose of it according to your local environmental laws and guidelines. For information about Apple’s recycling program, go to www.apple.com/environment. California: The coin cell battery in your product contains perchlorates. Special handling and disposal may apply. Refer to www.dtsc.ca.gov/hazardouswaste/ perchlorate. Deutschland: Dieses Gerät enthält Batterien. Bitte nicht in den Hausmüll werfen. Entsorgen Sie dieses Gerätes am Ende seines Lebenszyklus entsprechend der maßgeblichen gesetzlichen Regelungen. Nederlands: Gebruikte batterijen kunnen worden ingeleverd bij de chemokar of in een speciale batterijcontainer voor klein chemisch afval (kca) worden gedeponeerd.38 Ÿ ✐ Singapore Wireless Certification Taiwan Warning Statements Korea Warning Statements © 2009 Apple Inc.  j®9❡ Apple❞i6❞Apple ïi❞AirPort❞AirPort Express❞ AirPort Extreme❞Apple TV❞Bonjour❞iPod❞ Leopard❞Macintosh❞Mac OS Time Capsule n Apple Inc. 334ž4¢LÓ-.~ï❡ Finder❞iPhone  Time Machine n Apple Inc. ~ï❡ ¬zžøj/0Š“0u'eöøj ~ï❡www.apple.com/airport www.apple.com/support/airport TA019-1384-A Time Capsule3  5 1 7  Time Capsule 8  AirPort  9  11 Time Capsule  13 2 Time Capsule 14  Time Capsule  17  AirPort  19  19  !"# Internet $% 21 &'()*+ 22 ,-./0123456$%7 23 8 Time Capsule  Time Machine 25 3 25 9:;<= Internet 25 >?34@ Time Capsule 34 26 Time Capsule ABCD 27 Time Capsule  EFGHIJK4 28 LMNABCD 29 O AirPort  29 P Time Capsule QRS+ 30 TU AirPort VWXY&Z 31 4 33 Time Capsule 36 Regulatory Compliance Information1 5 1  Time Capsule  Time Capsule  Wi-Fi [\]Z^_`ab❞d Mac OS X v10.5.2 Leopard @O(efg Time Machine DhijklmnopBqrs\]Z^ t Time Capsule o❞ Time Capsule uvw[x: AirPort Extreme yzj{|}~€‚❞ & ƒ Time Capsule „j…T†(‡ Wi-Fi ˆ   2.4 ‰Š‹ (GHz) j 802.11b❝ 802.11g ! 802.11n &Zj iPhone❝ iPod touch !Žqr   5 GHz j 802.11n ! 802.11a &Zjqr! Apple TV &ZT:‘’{|“”•:–—˜•j™š Time Capsule T› oqr!&Z"#œ Internet ;<❞6  1 Bž Time Capsulej76Ÿˆ  d Mac OS X v10.5.2 @O(ef¡g Time Machine DhiZ^ opBqrŸ–Ÿ¢;? Time Capsule  Time Machine@❞  £34¤¥¦j§„;? Mac OS X Leopard D Time Machine  Time Capsule  Mac OS X v10.5.2 aST❞  Macintosh  Time Capsule  wäåB AirPort @ AirPort Extreme ù Macintosh qrjŸ°& …µ¶ ;<ú@wŸ¢q´;❞7â ã? @Ab dâAirPort ãâAirPort & ãây zãÈBg¡g*4âC]üJKãjD TF I JKj+C]'=❞ &()*10*-. 6:Edí]%2❞ Time Capsule EFí]¨GHIJ❞12  1 E Time Capsule q„j âAirPort ã& …jŸ› Internet ;<❝USB LMN❝ USB ¼½@ÒB8❞d¶ Mac OS X q rojâAirPort ãËâDhiã¬Kâã¬Kgú™ d¶ Windows XP @ Windows Vista qrojDË âLã> âpBhiã> âAirPortãg❞ &'2* Time Capsule ìïZƒ,-./0$%❞9: ; 22 é â,-./0123456$%7 ã❞ /2 13 2  Time Capsule Time Capsule Internet AirPort fM{|žBE Time Capsule ;âp Bhiã > âAirPortãg¡j*]7 Time Capsulej§„^Ù â_`ã❞ 4 Ùæab ❞ 4 Mac OS X v10.5 56789:; 1 *4cb > âdefƒ& ãj§„^Ù âLM›ghã❞ 2 ^ÙiÙÚ (+) ¨÷+g*]7LMN❞ 3 ^ÙiÙÚ❞ 7LMN9d÷+gjgÙÚjk…❞ 4 Mac OS X v10.3 < 10.4 56789:; 1 LâLMN& ã ËâDhiã¬Kâã¬Kg¡❞ 2 ÷+g*]LMN❞ LMN9d÷+gj^ÙiÙÚ¨?@Abg*4âBonjourãj§„ ÷+g*]LMN❞ =>?9 Windows XP < Windows Vista 567:;@ 1  Time Capsule » CD äå Bonjour  Windows e¡❞ 2 Ùæab ; âpBhiã > âAirPortã❞ 2 *]7 Time Capsulej§„^Ù â_`ã❞18  2 Time Capsule 3 Ùæab & Time Capsule !❞ âAirPort ã& NþEs%7Bátu!á0vU% 2j¨wN728& ❞ 7á Time Capsule ;<= InternetjD1á Internet vUx (ISP) {|œ  DSL ÎÏÐο@´ÎÏÐο¡y/j@ÑÒBŸ¢ < Internet ;<❞7 ISP 3`žz'Á { IP m|@ DHCP . / ID¡j76:1ád âAirPort ãg2}ÁÂ❞à& 7 Time Capsule ü34ºÁÂ❞ 2 Time Capsule 19 76Ÿ âAirPort ã& Nþ❞º& NþT~ 57%W€❝34¤¥–&'’©*+pô1~❞ 7Ld7o"# USB LMN@ USB ¼½ˆ 1 ELMN@¼½;<= Time Capsule  USB 0Ê (d) o❞ 2 LâAirPort ã Macintosh qrˆËâDhiã¬Kâ ã¬Kgú¶ Windows XP qrˆËâLã>âpBhiã>âAirPortã g¡❞ 3 *]7 Time Capsulej§„^Ù â_`ã❞ o9tpá  Time Capsulej^ÙâFqrãŸqr6&Zj §„÷+g*]7 Time Capsule❞ 4 Ùæab ❞ Internet 7L›oB‚x:@;<=Ÿ¢0Êqr"# Internet ; âpBhiã > âAirPortãg¡❞ 2 *]7 Time Capsulej§„^Ù â_`ã❞ áUìƒ& ƒ Time Capsule µ¶O„j76:ô;âpBhiã>âAirPortã g¡❞ 2 ÷+gBÄ&Zj*]7pá &Z❞o9tpá  Time Capsulej^Ù âFqrãŸqr6&Zj§„÷+g*]7  Time Capsule❞ 7áUìƒ& ƒ Time Capsule µ¶O„j76:ô;<=… j…:U Time Capsule µ¶O„❞ á*47páO„jd Macintosh qrobg AirPort b❞däåž Windows XP qrojE †Pd;<‡îoj&t7 ot€ˆ (SSID)j§„÷+g*4  BÄ6¡❞ 3  âyzãbg*4 â]& ã❞{7234jD234❞ B âAirPort ãg]& x:OÄÁÂj9:www.apple.com.cn/ support/airport oâDesigning AirPort Networks Using AirPort Utility (Mac OS X v10.5 + Windows)ã  Airport &Q AirPort  (MacOS X v10.5 + Windows)¡❞22  2 Time Capsule 7 WPA Personal @ WPA/WPA2 Personal µ¶34¤¥jD76Ÿ‘ ./0{|U7$%x:j™91©*234❞ à7,-./0$%7üjº./0€ˆ! MAC m|  @ AirPort ID¡T/E”d âAirPort ã$%Ï÷+gj&t7÷+g •–º./0❞7û6Ÿ{| 24 —ü$%j®ü«³„j./0E9:G$% 7❞ à7,-./0$%7üjº./01234❞ NOPQRSTUVWXYZ[\!5UV 1 LâAirPort ãj*]7 Time Capsulej§„âyzãb*4â ]& ã❞ôáü234❞ 2  âyzãbg*4 âi./0ã❞ 3 *]º./0$%‰Aˆ  *] PIN Ÿ2./0ø$%ü{|˜ËT™❞  *] âšHIJãŸ,-;IJ./0$%❞ à Time Capsule d“›./0üj LED TFœI#$❞ 2 Time Capsule 23 p‘7{|žü«$%j*] âE./0$%‹Ï‘ 24 — üã❞9*]}*+j./0E6Ÿ&$%j&t7÷+g•–º./0❞ Time Capsule Time Machine d Mac OS X Leopard g Time Machine Dhij76ŸZ^qroŸ ˜j ¡7æ¢❝£¤❝¥¢!¬¦❞ & ƒ Time Machine ª„j…T'§\]Z^7qr❞ 7v Mac OS X v10.5.2 @O(efjD;H;Z^©½ãj§ „ Time Machine Tª¶«ç¬>❞  Mac OS X Leopard g âdefƒ& ã âTime MachineãÈB& \ ]Z^❝O„=9}Z^©½@α’©& ❞ A?9 Mac OS X Leopard 567I<]^ Time Machine 1 *4cb > âdefƒ& ãj§„^Ù âTime Machineã❞ 2 E­]= âã❞ 3 ^Ù âO„©½ã❞ 4 *47 Time Capsule ¨^Ù âZ^ã❞24  2 Time Capsule šH Time Capsule ! Time Machine Z^6:1á±®@O¯ü«j4° 7Z^T±IJ❞ᐳLZ^‡jŸ¢E Time Capsule ; âMac wNãj§„djkÄ âTime Machineã❞3 25 3 _`abcde Time Capsule Internet  IJ&<7qr;<= Internet❞79:;âpBhiã>âAirPortã g¡❞ 4 *]7 Time Capsulej§„ âyzãbg*4 â]& ã❞ 5 dg^Ù âAirPortãj§„^Ù âyzã❞ 6 ‘7 Time Capsule 234❞ 7 ^Ùâã¨âä[•ã?@Abg*4ý3‰ŠjŸ°‘ AirPort í3¨ÓC34¤¥❞7Lž3x:j‘7 AirPort 2 34❞ 8 ^Ù âOãŸFí] Time Capsule ¨Ô& ❞ Time Capsule IJÕç„GE…q❞  Time Capsule %[ÂÃCDjD76:1áE’ØËt@Ö& ❞ , Time Capsule ij0vwxyUVsz{|4}RUV~,Qi j0 Time Capsule €CUV❞ 3 27 h Time Capsule ifjkl m ËÌÍÎ  ÏÐÑ¡ÙÒØËÙÚj&t ‡JK  S× 5 ! "¡❞ Time Capsule EØ˨BŸç& ˆ  Time Capsule  DHCP <ؒ IP m|❞  €ˆEØˑ Apple Network XXXXXX ®Ù XXXXXX  AirPort ID “„Ú ËT™ÛÜ¡❞  Time Capsule 34Øˑ public❞ mn!5 Time Capsule opqrstuvwxy 1 E Time Capsule Þq❞ 2 E Time Capsule q}üjËÌÍÎÙÒØËÙÚ❞ Time Capsule Ÿ¢q´6:Ý'(;<❝ Time Capsule 6:9d AirPort ÞßàáŸ@Ñ 7 Internet vUx6:Ed%2❞7 DSL ÎÏÐο@´ÎÏÐο ;<= InternetjDºÎÏÐο6:ìâãž;<@ Internet ;<❞5°Î ÏÐοäå>'=jûIJÞ…qj“›è!"j§„‘ÎÏÐο Fˆ 1 ('LMNìƒq¨ìq❞ 2 ('q´ìƒëìm;<=LMN! Time Capsule  USB 0Êo❞ 3 (¤ìƒd./0qr âLMN÷+ãíÊg*]žºLMN❞ ABCD Mac OS X v10.5 âdefƒ& ãj§„^Ù âLM›ghã❞  ^ÙiÙÚ (+) ¨d÷+g*]7LMNj§„^ÙiÙÚ (+)❞ ABCD Mac OS X v10.2.7 ❞ 4 LMNj“›è!ýj§„Gí…❞ AirPort Apple '§O AirPort ❞î7O Time Capsule Ÿ“❞ 7û6Ÿd AirPort fƒ& g*] âL AirPort üÅÆOãj@*] âÅÆOã❞7*] âÅÆOãjD?@Abg*4ü«ï   â´ð㡟\]ÅÆO❞ Time Capsule ŸçîBN Time Capsule 3`“”²Áàá!Þßàá❞  E Time Capsule P dèåABÜñÍ Sò@óô¡õö÷Íg❞I JE’P døùúû+ÈË ❞  7E Time Capsule P dò„ÈjD Time Capsule !ò×ü«ýD= ²B 25.4 þ  1 ¡❞  E Time Capsule P dÓÈ@Óȟosvúû+È÷Íg❞30  3  ád ¤g gE Time Capsule !0 &ZPd$j£€q ´❝ €q´@q Time Capsule❞P Time Capsule üjq´áPd ❞ Time Capsule !q´ª«á¤¸6:Sõ«❞  IJE Time Capsule P dù❝ 2.4 @ 5 ‰Š‹ (GHz) q!’©X Y=² 7.6   25 ¡Ë ❞  E’©ÍΠf❝@—͓“¡P d Time Capsule ❞®6: T¥C Time Capsule ❞ AirPort ùXY øjVW%26:•ûR —❞ŸçS+TU AirPort ²Á!"XYˆ    &<#$vU (DSS) €’%&  'Ætu()#$žp»*§}+q´❞‚d&Z"!xŸ3`u q´❞  'Æq,&Zj(-q❝q,./0❝qz““  2.4 GHz @ 5 GHz q€’àáŸq❞7q@ AirPort ²ÁE d%2jO„7yz@ Time Capsule €0j@ÑO„7q €0❞  »1B21€0yz❞Սjyz A & ‘€0 1jDyz B Dº& ‘€0 6 @ 11❞4 31 4 DdEz{|❝~1€ Web Time Capsule B Time Capsule “ÁÂj$% www.apple.com.cn/airport❞ áQ3 Time Capsule 7däå Time Capsule CD oüAB®¯4¡j $% www.apple.com/register/cn/❞ B AirPort ·¸ÁÂ❝›z'!ÎmÁÂ!56À7Ÿ–“ Apple  çÔj$% www.apple.com.cn/support/airport❞ B89Ÿ¾·¸ÁÂj$% www.apple.com/supportj§„*47pd9 ò@m÷❞32  4 ážÐB Time Capsule » âAirPort ãOÄÁÂjL âAirPort ã¨*4 âwNã > âAirPort wNã❞  Time Capsule o$ì:;@9:'=>jÙæf3❝abwN!d <g¬>❞  Time Capsule È9:>j$% www.apple.com.cn/support ŸžÐB 3`¤=vUÁÂ❞ Time Capsule i÷ M Time Capsule >❞33 Time Capsule ‚ƒ1B„…† Time Capsule  ‡ˆ2.4 = 5 GHz  S‰TkŠ‹“(6? 23 dBm  îˆ@¡  Œ802.11 DSSS 1 ! 2 Mbps îï❝ 802.11a❝802.11b❝ 802.11g ðñjŸ–òó 802.11n ðñ  1 RJ-45 10/100/1000Base-T ‰ŠËŸ¢ÌÍ (<)  3 RJ-45 10/100/1000Base-T ‰ŠËŸ¢ÔÍ (G)  ²A¶B (USB d) 2.0  802.11 a/b/g/n AirPort Extreme   xyŽ0° C = 35° C  32° F = 95° F¡  ‘Ž–25° C = 60° C  –13° F = 140° F¡  ’“” •xy–—20% = 80% mUC  ’“” •‘–—10% = 90% mUC  DEF¡34 ˜ Time Capsule  ™197.0 þ  7.75 ¡  š197.0 þ  7.75 ¡  F36.33 þ  1.43 ¡  ›œ1.6 ‰G  3.5 H¡ (MAC) Time Capsule d¾I>JMBÓ¼m|ˆ  AirPort ID’g†m|KLo Time Capsule❞  U ID76:1áE}m|{|æ ISP Ÿ°E Time Capsule ; Time Capsule qN‰ŠvE’qoÕç❞  à;<@Þ Time Capsule üjUôOÒP†❞ áøùPúû Q❞  9¹8‘çè78js9DR Time Capsulej5à…ìÞqüû9:R ❞7 Time Capsule 1áS=j9:; 31 é âžÐOÄÁÂ❝vU! ·¸ã❞  9áEj E&ZŸt¾ÈZXõ,g❞   Time Capsule øù[ j\]❝^_¼❝`a❝b`c“❞  ¤¥ Time Capsule 9£dn&‘!ef@’©C,g❞  — 9áEhÍ@[ ijd Time Capsule o❞ìkÍÎjæ… Þqj§„GÉ^ijÍ❞  dc¾ Time Capsule❞ Time Capsule vcŸ!Î❞ E”@¬>9àj6:T:; Time Capsule❞d2 Time Capsule ³hgj— 9áE…–dmo❞ ‚*ƒ„…†‡&ˆ‰Šc‹ŒjV Time Capsule❞ \ Ž‘’ Time Capsule❞ s“”*ƒ~4•–— ˜™š›❞œž4Ÿ '€ ¡—¢L❞36 Regulatory Compliance Information Wireless Radio Use This device is restricted to indoor use due to its operation in the 5.15 to 5.25 GHz frequency range to reduce the potential for harmful interference to cochannel Mobile Satellite systems. Cet appareil doit être utilisé à l’intérieur. Exposure to Radio Frequency Energy The radiated output power of this device is well below the FCC and EU radio frequency exposure limits. However, this device should be operated with a minimum distance of at least 20 cm between its antennas and a person’s body and the antennas used with this transmitter must not be colocated or operated in conjunction with any other antenna or transmitter subject to the conditions of the FCC Grant. FCC Declaration of Conformity This device complies with part 15 of the FCC rules. Operation is subject to the following two conditions: (1) This device may not cause harmful interference, and (2) this device must accept any interference received, including interference that may cause undesired operation. See instructions if interference to radio or television reception is suspected. Radio and Television Interference This computer equipment generates, uses, and can radiate radio-frequency energy. If it is not installed and used properly—that is, in strict accordance with Apple’s instructions—it may cause interference with radio and television reception. This equipment has been tested and found to comply with the limits for a Class B digital device in accordance with the specifications in Part 15 of FCC rules. These specifications are designed to provide reasonable protection against such interference in a residential installation. However, there is no guarantee that interference will not occur in a particular installation. You can determine whether your computer system is causing interference by turning it off. If the interference stops, it was probably caused by the computer or one of the peripheral devices. If your computer system does cause interference to radio or television reception, try to correct the interference by using one or more of the following measures:  Turn the television or radio antenna until the interference stops.  Move the computer to one side or the other of the television or radio.  Move the computer farther away from the television or radio.  Plug the computer into an outlet that is on a different circuit from the television or radio. (That is, make certain the computer and the television or radio are on circuits controlled by different circuit breakers or fuses.) If necessary, consult an Apple Authorized Service Provider or Apple. See the service and support information that came with your Apple product. Or, consult an experienced radio/television technician for additional suggestions. Important: Changes or modifications to this product not authorized by Apple Inc. could void the EMC compliance and negate your authority to operate the product.37 This product was tested for FCC compliance under conditions that included the use of Apple peripheral devices and Apple shielded cables and connectors between system components. It is important that you use Apple peripheral devices and shielded cables and connectors between system components to reduce the possibility of causing interference to radios, television sets, and other electronic devices. You can obtain Apple peripheral devices and the proper shielded cables and connectors through an Apple-authorized dealer. For non-Apple peripheral devices, contact the manufacturer or dealer for assistance. Responsible party (contact for FCC matters only) Apple Inc., Corporate Compliance, 1 Infinite Loop M/S 26-A, Cupertino, CA 95014-2084 Industry Canada Statement This Class B device meets all requirements of the Canadian interference-causing equipment regulations. Cet appareil numérique de la Class B respecte toutes les exigences du Règlement sur le matériel brouilleur du Canada. VCCI Class B Statement Europe—EU Declaration of Conformity For more information, see www.apple.com/euro/ compliance. European Union — Disposal Information This symbol means that according to local laws and regulations your product should be disposed of separately from household waste. When this product reaches its end of life, take it to a collection point designated by local authorities. Some collection points accept products for free. The separate collection and recycling of your product at the time of disposal will help conserve natural resources and ensure that it is recycled in a manner that protects human health and the environment. žŸ1 ¡{| f!Π-Ÿ q¼❞l±àm¤Šðþ …❞B Apple mØQnÁÂj$% www.apple.com.cn/environment❞ California: The coin cell battery in your product contains perchlorates. Special handling and disposal may apply. Refer to www.dtsc.ca.gov/hazardouswaste/ perchlorate. Deutschland: Dieses Gerät enthält Batterien. Bitte nicht in den Hausmüll werfen. Entsorgen Sie dieses Gerätes am Ende seines Lebenszyklus entsprechend der maßgeblichen gesetzlichen Regelungen. Nederlands: Gebruikte batterijen kunnen worden ingeleverd bij de chemokar of in een speciale batterijcontainer voor klein chemisch afval (kca) worden gedeponeerd.38 Taiwan: Singapore Wireless Certification Taiwan Warning Statements Korea Warning Statements © 2009 Apple Inc. ¤opq❞ Apple❝c❝Apple îr❝AirPort❝ AirPort Express❝ AirPort Extreme❝Apple TV❝Bonjour❝iPod❝Leopard❝ Macintosh❝Mac OS ! Time Capsule v Apple Inc. d8 9–’©9ò!m÷Q3xî❞Finder❝iPhone ! Time Machine v Apple Inc. xî❞ ®Ù{–’©!Î!st€ˆ6:v’mDst xî❞www.apple.com/airport www.apple.com/support/airport CH019-1384-A Time Capsule Setup Guide3 Contents 5 Getting Started 8 About Your Time Capsule 9 About the AirPort Software 10 What You Need to Get Started 12 The Time Capsule Status Light 14 Setting Up Your Time Capsule 15 Using Your Time Capsule to Create Your Wireless Network 18 Using AirPort Utility 20 Creating a New Wireless Network 20 Configuring and Sharing Internet Access 22 Setting Advanced Options 23 Allowing Wireless Clients to Access Your Network Without Entering a Password 24 Using Time Machine with Your Time Capsule 26 Tips and Troubleshooting 26 If You Can’t Connect to the Internet 26 If You Forgot Your Network Password or Time Capsule Password 28 If Your Time Capsule Isn’t Responding 29 If Your Time Capsule Status Light Flashes Amber4 30 If Your Printer Isn’t Responding 31 Updating AirPort Software 31 Time Capsule Placement Considerations 32 Items That Can Cause Interference with AirPort 33 Learning More, Service, and Support 35 Time Capsule Specifications and Safety Guidelines 38 Regulatory Compliance Information1 5 Getting Started Congratulations on purchasing your Time Capsule. Read this guide to get started. Time Capsule offers you the simplicity of fully automated backup for your Wi-Fi network. Using the Time Machine application in Mac OS X v10.5.7 Leopard or later, it’s easy and automatic to back up all the computers on your network to a single Time Capsule. The Time Capsule is also a fully featured AirPort Extreme Base Station that provides simultaneous dual-band wireless networking.When you set up your Time Capsule, it creates two high-speed Wi-Fi networks:  A 2.4 gigahertz (GHz) network for 802.11b, 802.11g, and 802.11n devices, such as iPhone, iPod touch, and older computers  A 5 GHz network for 802.11n and 802.11a devices, such as newer computers, iPad, and Apple TV Wireless devices join the network that provides them the best performance and compatibility, and the Time Capsule shares your broadband Internet connection with computers and devices on your network.6 Chapter 1 Getting Started With your Time Capsule, you can:  Use the Time Machine application in Mac OS X v10.5.7 (or later) to back up all the computers on your wireless network, as well as computers connected to your Time Capsule using Ethernet. Note:  Your first backup with Time Capsule and Time Machine could take overnight or longer, depending on how much data you’re backing up. To speed up the initial backup, use an Ethernet cable to connect your computer to the LAN port on your Time Capsule. For more information about using Time Machine, see “Using Time Machine with Your Time Capsule” on page 24.  Create a password-protected wireless home network, and then connect to the Internet and share the connection with other computers and Wi-Fi devices, such as iPad, iPhone, iPod touch, and Apple TV. You can also share files among computers connected to the network.  Create a guest network, with or without password protection to provide Internet-only access to wireless devices, such as computers, iPad, iPhone, iPod touch, and Apple TV.  Connect your Time Capsule to your Ethernet network.Wireless-equipped Mac, Windows XP, Windows Vista, or Windows 7 computers can then have access to an entire network without being connected by a cable.  Connect a supported USB printer to your Time Capsule. Compatible computers on the AirPort network, both wireless and wired, can print to it.  Connect an additional USB hard drive to your Time Capsule. Compatible computers on the AirPort network, both wireless and wired, can access information on the hard disk.Chapter 1 Getting Started 7  Connect a USB hub to your Time Capsule, and then connect multiple USB devices, such as printers or hard disks. All computers on the network have access to those devices. Important:  Use AirPort Utility to set up your Time Capsule. Previous versions of AirPort Setup Assistant and AirPort Admin Utility are not compatible with this Time Capsule. AirPort Utility is installed in the Utilities folder in the Applications folder on a computer using Mac OS X, and in Start > All Programs > AirPort on a computer using Windows. If AirPort Utility isn’t installed on your computer, you can download it from www.apple.com/support/airport. Apple periodically updates AirPort software. It’s recommended that you update your software to keep your Time Capsule up to date. Note:  To download a copy of this setup guide in your language, open AirPort Utility and choose Help > AirPort Service and Support, and click Manuals.8 Chapter 1 Getting Started About Your Time Capsule Your Time Capsule has five ports on the back:  One 10/100/1000Base-T Gigabit Ethernet Wide Area Network (WAN) port for connecting a DSL or cable modem, or for connecting to an existing Ethernet network  Three 10/100/1000Base-T Gigabit Ethernet Local Area Network (LAN) ports for connecting Ethernet devices, such as printers or computers, or for connecting to an existing Ethernet network  One USB port for connecting a compatible USB printer, hard drive, or hub for connecting several devices Status light Internet WAN port Power port Power cord USB port Reset button Ethernet ports Security slot Ethernet activity light The reset button next to the ports is used for troubleshooting your Time Capsule. The status light on the front shows the current status.Chapter 1 Getting Started 9 About the AirPort Software Your Time Capsule works with AirPort Utility, installed in the Utilities folder in the Applications folder on a computer using Mac OS X, and in Start > All Programs > AirPort on a computer using Windows. If AirPort Utility isn’t installed on your computer, you can download it from www.apple.com/support/airport. Use AirPort Utility and follow the instructions on the following pages to set up your Time Capsule and your AirPort wireless network. Note:  You must use AirPort Utility v5.5.3 (or later) to set up your Time Capsule. This Time Capsule is not compatible with previous versions of AirPort software. AirPort Utility Use AirPort Utility to set up your Time Capsule to create a wireless network, connect to the Internet, and share compatible USB printers and hard disks. You can also connect your Time Capsule to an existing AirPort Extreme wireless network. AirPort Utility is also an advanced tool for setting up and managing the Time Capsule, AirPort Extreme, and AirPort Express Base Stations. Use it to manually adjust network, routing, and security settings and other advanced options. Z AirPort status menu Use the AirPort status menu in the menu bar to switch quickly between AirPort networks, monitor the signal quality of the current network, create a computer-to-computer network, and turn AirPort on or off. The status menu is available on computers using Mac OS X.10 Chapter 1 Getting Started What You Need to Get Started To use your Time Capsule, you need a wireless-enabled computer that’s compliant with IEEE 802.11a, 802.11b, 802.11g, or IEEE 802.11n standards. To set up your Time Capsule, your computer must meet the requirements listed below. Note:  To use your Time Capsule with Time Machine in Mac OS X, you need to use Mac OS X v10.5.7 or later. To set up your Time Capsule using a Mac, you need the following:  A Mac computer with an AirPort or AirPort Extreme Card installed to set it up wirelessly, or a Mac computer connected to your Time Capsule with an Ethernet cable to set it up using Ethernet  Mac OS X v10.5.7 or later  AirPort Utility v5.5.3 or later To set up your Time Capsule using a Windows computer, you need the following:  A Windows computer with 300 MHz or higher processor speed and a compatible 802.11a, 802.11b, or 802.11g, IEEE 802.11n wireless card, or a Windows computer connected to a Time Capsule with an Ethernet cable to set it up using Ethernet  Windows XP Home or Professional (SP3), Windows Vista (SP2), or Windows 7 (SP1)  AirPort Utility v5.5.3 or laterChapter 1 Getting Started 11 Plugging In Your Time Capsule Before you plug in your Time Capsule, first connect the appropriate cables to the ports you want to use:  Connect the Ethernet cable that’s connected to your DSL or cable modem (if you will connect to the Internet) to the Ethernet WAN (<) port.  Connect a USB cable connected from the USB (d) port on your Time Capsule to a compatible USB printer (if you will print to a USB printer), a hard disk, or a hub.  Connect an Ethernet cable from any Ethernet device to the Ethernet LAN (G) ports. After you’ve connected the cables for all the devices you plan to use, connect the power cord to the power port and plug your Time Capsule into a power outlet. There is no power switch. Important:  Use only the power cord that came with your Time Capsule. When you plug your Time Capsule into a power outlet, the status light flashes green for one second and then glows amber while your Time Capsule starts up. After your Time Capsule has started up completely, the status light flashes amber until your Time Capsule has been updated with the correct settings. The status light glows solid green after your Time Capsule is properly set up and connected to the Internet or a network. When you connect Ethernet cables to the Ethernet ports, the lights above them glow solid green.12 Chapter 1 Getting Started The Time Capsule Status Light The following table explains the Time Capsule light sequences and what they indicate. Light Status/description Off Your Time Capsule is unplugged. Solid amber Your Time Capsule is completing its startup sequence. Flashing amber Your Time Capsule can’t establish a connection to the network or the Internet, or is encountering a problem. Make sure you have installed AirPort Utility and use it to get information about what might cause the status light to flash amber. See “If Your Time Capsule Status Light Flashes Amber” on page 29. Solid green Your Time Capsule is on and working properly. If you choose Flash On Activity from the Status Light pop-up menu (in the Base Station pane of AirPort settings in AirPort Utility), the status light may flash green to indicate normal activity. Flashing amber and green There may be a problem starting up. Your Time Capsule will restart and try again. Solid blue Your Time Capsule is ready to allow a wireless client access to the network. See “Allowing Wireless Clients to Access Your Network Without Entering a Password” on page 23.Chapter 1 Getting Started 13 What’s Next After you plug in your Time Capsule, use AirPort Utility to set it up to work with your Internet connection, USB printer or hard disk, or an existing network. AirPort Utility is located in the Utilities folder in the Applications folder on a computer using Mac OS X, and in Start > All Programs > AirPort on a computer using Windows XP or Windows Vista.14 2 Setting Up Your Time Capsule This chapter provides information and instructions for connecting your Time Capsule to the Internet, and using AirPort Utility to set it up to create or join a wireless network. This chapter provides an overview of connecting your Time Capsule to the Internet, and using the setup assistant in AirPort Utility to set up your network and other features of your Time Capsule. For more information about wireless networking, and for information about the advanced features of AirPort Utility, refer to “Apple AirPort Networks” at www.apple.com/support/airport. You can do most of your network setup and configuration tasks using the setup assistant in AirPort Utility. To set advanced options, choose Manual Setup from the Base Station menu of AirPort Utility. See “Setting Advanced Options” on page 22.Chapter 2 Setting Up Your Time Capsule 15 Using Your Time Capsule to Create Your Wireless Network When you set up your Time Capsule to provide network and Internet access, the following computers and devices can access the wireless AirPort network to share files, play games, and use Internet applications such as web browsers and email applications:  Mac computers with AirPort or AirPort Extreme Cards  802.11a, 802.11b, 802.11g, and IEEE 802.11n wireless-equipped computers  Other Wi-Fi devices, such as iPad, iPhone, iPod Touch, and Apple TV Computers connected to your Time Capsule using Ethernet can also access the network to share files and connect to the Internet. With Mac OS X v10.5.7 or later you can set up Time Machine to back up all the computers on the network to your Time Capsule. See “Using Time Machine with Your Time Capsule” on page 24 for more information. When you connect a compatible USB printer to your Time Capsule, supported computers on the network (wired and wireless) can print to it.16 Chapter 2 Setting Up Your Time Capsule Using Time Capsule to create a wireless network to Internet DSL or cable modem < Internet WAN port Shared printer Time Capsule to USB port 2.4 or 5 GHz 2.4 GHz 2.4 or 5 GHz To set it up: 1 Connect your DSL or cable modem to your Time Capsule using the Ethernet WAN (<) port. 2 If you plan to share a USB printer on the network, connect it to the Time Capsule USB (d) port or to a USB hub using a USB cable.Chapter 2 Setting Up Your Time Capsule 17 3 Open AirPort Utility (located in the Utilities folder in the Applications folder on a computer using Mac OS X, and in Start > All Programs > AirPort on a computer using Windows), select your Time Capsule, and then click Continue. 4 Follow the onscreen instructions to create a new network. To print from a computer using Mac OS X v10.5 or later: 1 Choose Apple > System Preferences, and then click Print & Fax. 2 Click Add (+) and select your printer from the list. 3 Click the Add button. If your printer isn’t in the list, use the buttons in the toolbar to search for it. To print from a computer using Mac OS X v10.2.7 or later: 1 Open Printer Setup Utility (located in the Utilities folder in the Applications folder). 2 Select your printer from the list. If your printer isn’t in the list, click Add and choose Bonjour from the pop-up menu, and then select your printer from the list. To print from a computer using Windows XP, Windows Vista, or Windows 7: Use Bonjour for Windows and follow the onscreen instructions to connect to your printer. Computers using AirPort or other compatible wireless cards or adapters can connect to the Internet through your Time Capsule. Computers connected to the Time Capsule Ethernet ports can also access the network and connect to the Internet. Wireless computers and computers connected to the Ethernet ports can also communicate with each other through your Time Capsule.18 Chapter 2 Setting Up Your Time Capsule Using AirPort Utility To set up and configure your Time Capsule, use the setup assistant in AirPort Utility. On a Mac computer using Mac OS X v10.5.7 or later: 1 Open AirPort Utility, located in the Utilities folder in the Applications folder. 2 Select your Time Capsule and click Continue. If you don’t see the Time Capsule you want to configure, click Rescan to scan for available wireless devices, and then select your Time Capsule from the list. 3 Follow the onscreen instructions to set up your Time Capsule and your wireless network. On a computer using Windows XP (SP3), Windows Vista (SP2), or Windows 7 (SP1): 1 Open AirPort Utility, located in Start > All Programs > AirPort. 2 Select your Time Capsule and click Continue. If AirPort Utility isn’t installed on your computer, you can download it from www.apple.com/support/airport.Chapter 2 Setting Up Your Time Capsule 19 3 Follow the onscreen instructions to set up your Time Capsule and your wireless network. The AirPort Utility setup assistant asks you questions about the type of network you want to use and the services you want to set up, and helps you enter the appropriate settings. If you’re using your Time Capsule to connect to the Internet, you need a broadband (DSL or cable modem) account with an Internet service provider (ISP), or a connection to the Internet using an existing Ethernet network. If you received specific information from your ISP (such as a static IP address or a DHCP client ID), you may need to enter it in AirPort Utility. Have this information available when you set up your Time Capsule.20 Chapter 2 Setting Up Your Time Capsule Creating a New Wireless Network You can use the AirPort Utility setup assistant to create a new wireless network. The setup assistant guides you through the steps necessary to name your network, protect your network with a password, and set other options. If you plan to share a USB printer or USB hard disk on your network: 1 Connect the printer or hard disk to the Time Capsule USB (d) port. 2 Open AirPort Utility, located in the Utilities folder in the Applications folder on a Mac, or in Start > All Programs > AirPort on a computer using Windows. 3 Select your Time Capsule and click Continue. If you don’t see the Time Capsule you want to configure, click Rescan to scan for available wireless devices, and then select your Time Capsule from the list. 4 Follow the onscreen instructions to create a new network. Configuring and Sharing Internet Access If you plan to share your Internet connection with wireless-enabled computers on your network or with computers connected to the Ethernet ports, you need to set up your Time Capsule as an AirPort base station. After your Time Capsule is set up, computers access the Internet through the AirPort network. Your Time Capsule connects to the Internet and transmits information to the computers over the wireless network. Before you use AirPort Utility to set up your Time Capsule, connect your DSL or cable modem to the Time Capsule Ethernet WAN (<) port. If you’re connecting your Time Capsule to an Ethernet network that already has Internet access, connect it to the Ethernet network.Chapter 2 Setting Up Your Time Capsule 21 Use the AirPort Utility setup assistant to enter your ISP settings and configure how your Time Capsule shares the settings with other computers. 1 Open AirPort Utility, located in the Utilities folder in the Applications folder on a computer using Mac OS X, or in Start > All Programs > AirPort on a computer using Windows. If AirPort Utility isn’t installed on your computer, you can download it from www.apple.com/support/airport. 2 Select your Time Capsule and click Continue. If you’re making changes to a Time Capsule that has already been set up, you might have to connect to the network it’s created before making changes to the Time Capsule. To choose the wireless network you want to change on a Mac, use the AirPort status menu in the menu bar. On a computer using Windows, hold the pointer over the wireless connection icon until you see the network name (SSID), and then choose it from the list if there are multiple networks available. 3 Follow the onscreen instructions to configure and share Internet access on your Time Capsule. AirPort Utility provides a quick and easy way to set up your Time Capsule and network. If you want to set additional options for your network, such as restricting access to your network or setting advanced DHCP options, choose Manual Setup from the Base Station menu of AirPort Utility.22 Chapter 2 Setting Up Your Time Capsule Setting Advanced Options Use AirPort Utility to set up your Time Capsule manually if you want to set advanced Time Capsule options such as advanced security options, closed networks, DHCP lease time, access control, power controls, user accounts, and more. To set advanced options: 1 Open AirPort Utility, located in the Utilities folder in the Applications folder on a Mac, and in Start > All Programs > AirPort on a computer using Windows. If AirPort Utility isn’t installed on your computer, you can download it from www.apple.com/support/airport. 2 If there’s more than one wireless device in the list, select the one you want to configure. If you don’t see the Time Capsule you want to configure, click Rescan to scan for available wireless devices, and then select your Time Capsule from the list. If you’re making changes to a Time Capsule that has already been set up, you might have to connect to the network it’s created before making changes to your Time Capsule. To choose the wireless network you want to change on a Mac, use the AirPort status menu in the menu bar. On a computer using Windows, hold the pointer over the wireless connection icon until you see the network name (SSID), and then choose it from the list if there are multiple networks available. 3 Choose Manual Setup from the Base Station menu. If you’re prompted for a password, enter it. For more about the manual setup features in AirPort Utility, see “Apple AirPort Networks” at www.apple.com/support/airport.Chapter 2 Setting Up Your Time Capsule 23 Allowing Wireless Clients to Access Your Network Without Entering a Password If your network is password-protected using WPA Personal or WPA/WPA2 Personal, you can provide wireless clients access to your network without requiring them to enter the network password. When you allow a client access to your network, the client’s name and wireless MAC address (or AirPort ID) are stored in the access control list of AirPort Utility until you remove the client from the list. You can also provide 24 hours of access, after which time the client can no longer access your network. When you give a client access to your wireless network, the client doesn’t need to enter the network password. To allow a client to access your network without entering the network password: 1 Open AirPort Utility, select your Time Capsule, and then choose Manual Setup from the Base Station menu. Enter the password if necessary. 2 Choose Add Wireless Clients from the Base Station menu. 3 Select how you want the client to access the network:  Select PIN to enter the eight-digit number provided by the client requesting network access.  Select“First attempt”to allow network access to the first client attempting to join the network. While the Time Capsule waits for a client to join the network, the LED glows blue.24 Chapter 2 Setting Up Your Time Capsule Select“Limit client’s access to 24 hours”if you want to provide just one day of access to your network. If you don’t select this option, the client has access until you remove the client from the list. Using Time Machine with Your Time Capsule With the Time Machine application in Mac OS X (Leopard or later) you can back up everything on your computer, including your photos, music, movies, and documents. After you set up Time Machine, it automatically backs up your computer on a regular basis. If you’re using Mac OS X v10.5.7 or later, the first time you connect to your Time Capsule, Time Machine asks if you’d like to use it to back up your files. Click “Use as Backup Disk,” and Time Machine takes care of the rest. Use the Time Machine pane of System Preferences to set up automatic backups, change to a different backup disk, or adjust other settings. To set up or adjust Time Machine on a computer using Mac OS X Leopard or later: 1 Choose Apple > System Preferences, and then click Time Machine. 2 Slide the switch to ON. 3 Click Change Disk. 4 Choose your Time Capsule and click “Use for Backup.”Chapter 2 Setting Up Your Time Capsule 25 Your first backup with Time Capsule and Time Machine could take overnight or longer, depending on how much data you’re backing up. To speed up the initial backup, connect your Time Capsule to your computer using Ethernet. In each subsequent backup, Time Machine backs up only files that have changed since the previous backup, so the backups don’t take as long. Time Capsule is a great wireless backup solution for portable computers. Since the first backup can take some time, plug your portable into a power adapter—this conserves battery power and guarantees that backups won’t be interrupted. Also, for the best wireless performance, place your portable computer in the same room as your Time Capsule. If you shut down your Mac or put it to sleep during a backup, Time Machine stops the backup and then continues from where it left off after your Mac starts up again. For more information about Time Machine, choose Help > Mac Help from the Finder menu on a computer using Mac OS X Leopard or later, and then type Time Machine in the search field.26 3 Tips and Troubleshooting You can quickly solve most problems with your Time Capsule by following the advice in this chapter. If You Can’t Connect to the Internet  Try connecting to the Internet directly from your computer. If you can’t connect, check to make sure your network settings are correct. If they appear to be correct and you still can’t connect, contact your Internet service provider (ISP).  Make sure you’re connecting to the correct wireless network. If You Forgot Your Network Password or Time Capsule Password You can clear the AirPort network password or Time Capsule password by resetting your Time Capsule. To reset the Time Capsule password: 1 Use something pointed (such as a ballpoint pen) to press and hold down the reset button for one second. Important:  If you hold the reset button for more than one second, you may lose your network settings.Chapter 3 Tips and Troubleshooting 27 2 Select your AirPort network.  On a Mac, use the AirPort status menu in the menu bar to select the network created by your Time Capsule (the network name doesn’t change).  On a computer using Windows, hold the pointer over the wireless connection icon until you see your AirPort network name (SSID), and choose it from the list if there are multiple networks available. 3 Open AirPort Utility (in the Utilities folder in the Applications folder on a Mac, and in Start > All Programs > AirPort on a computer using Windows). If AirPort Utility isn’t installed on your computer, you can download it from www.apple.com/support/airport. 4 Select your Time Capsule, and then choose Manual Setup from the Base Station menu. 5 Click AirPort in the toolbar, and then click Base Station. 6 Enter a new password for your Time Capsule. 7 Click Wireless and choose an encryption method from the Wireless Security pop-up menu to turn on encryption and activate password protection for your AirPort network. If you turn on encryption, enter a new password for your AirPort network. 8 Click Update to restart your Time Capsule and load the new settings.28 Chapter 3 Tips and Troubleshooting If Your Time Capsule Isn’t Responding Try unplugging it and plugging it back in. If your Time Capsule stops responding completely, you may need to reset it to the factory default settings. Important:  Resetting your Time Capsule to factory default settings erases all of the current settings and resets them to the settings that came with your Time Capsule. To return your Time Capsule to the factory settings: m Use something pointed (such as a ballpoint pen) to press down and hold the reset button until the status light flashes quickly (about 5 seconds). Your Time Capsule resets with the following settings:  Your Time Capsule receives its IP address using DHCP.  The network name is reset to Apple Network XXXXXX (where XXXXXX is replaced with the last six digits of the AirPort ID).  The Time Capsule password is reset to public. If your Time Capsule still isn’t responding, try the following: 1 Unplug your Time Capsule. 2 Use something pointed to press and hold down the reset button while you plug in your Time Capsule.Chapter 3 Tips and Troubleshooting 29 If Your Time Capsule Status Light Flashes Amber The Ethernet cable may not be connected properly, your Time Capsule may be out of range of an AirPort network, or there may be a problem with your Internet service provider. If you’re connected to the Internet with a DSL or cable modem, the modem may have lost its connection to the network or the Internet. Even if the modem seems to be working properly, try disconnecting it from its power supply, waiting a few seconds, and then reconnecting it. Make sure your Time Capsule is connected directly to the modem via Ethernet before reconnecting power to the modem. For more information about why the light is flashing, open AirPort Utility, select your Time Capsule, and then choose Manual Setup from the Base Station menu. Click Base Station Status to display information about the flashing light. You can also select“Monitor base station for problems”in AirPort preferences. If the base station has a problem, AirPort Utility opens and walks you through solving the problem.30 Chapter 3 Tips and Troubleshooting If Your Printer Isn’t Responding If you connected a printer to the USB port on your Time Capsule and the computers on the AirPort network can’t print, try the following: 1 Make sure the printer is plugged in and turned on. 2 Make sure the cables are securely connected to the printer and to the Time Capsule USB port. 3 Make sure the printer is selected in the Printer List window on client computers. On a Mac using Mac OS X v10.5 or later:  Choose Apple > System Preferences, and then click Print & Fax.  Click Add (+) and select your printer in the list, and then click Add (+). On a Mac using Mac OS X v10.2.7 or later:  Open Printer Setup Utility, located in the Utilities folder in the Applications folder.  If the printer isn’t in the list, click Add.  Choose Bonjour from the pop-up menu, select the printer and click Add (+). On a computer using Windows:  Open “Printers and Faxes”from the Start menu.  Select the printer. If the printer isn’t in the list, click Add Printer and then follow the onscreen instructions.  If Bonjour for Windows is installed, click the Bonjour Printer, click the Bonjour Printer Wizard on the desktop, and then follow the onscreen instructions for setting up a printer. 4 Turn off the printer, wait a few seconds, and then turn it back on.Chapter 3 Tips and Troubleshooting 31 Updating AirPort Software Apple periodically updates AirPort software. It is recommended that you update your Time Capsule to use the latest software. You can select“Check for updates when opening AirPort Utility,” or“Check for updates” in AirPort preferences. If you select“Check for updates,” choose an increment of time, such as weekly, from the pop-up menu to automatically check for updates. Time Capsule Placement Considerations The following recommendations can help your Time Capsule achieve the best wireless range and network coverage.  Place your Time Capsule in an open area where there are few obstructions, such as large pieces of furniture or walls. Try to place it away from metallic surfaces.  If you place your Time Capsule behind furniture, keep at least an inch of space between the Time Capsule and the edge of the furniture.  Avoid placing your Time Capsule in areas surrounded by metal surfaces on three or more sides.  If you place your Time Capsule in an entertainment center with your stereo equipment, avoid surrounding your Time Capsule with audio, video, or power cables. Place your Time Capsule so that the cables are to one side. Maintain as much space as possible between your Time Capsule and the cables.  Try to place your Time Capsule at least 25 feet (7.6 meters) from any microwave oven, 2.4 or 5 gigahertz (GHz) cordless phone, and other sources of interference.  Do not place other objects (books, papers, small pets, etc.) on top of the Time Capsule. It may interfere with Time Capsule cooling.32 Chapter 3 Tips and Troubleshooting Items That Can Cause Interference with AirPort The farther away the interference source, the less likely it is to cause a problem. The following can interfere with AirPort communication:  Microwave ovens  Direct Satellite Service (DSS) radio frequency leakage  The original coaxial cable that came with certain types of satellite dishes. Contact the device manufacturer and obtain newer cables.  Certain electrical devices such as power lines, electrical railroad tracks, and power stations.  Cordless telephones that operate in the 2.4 or 5 GHz range. If you have problems with your phone or AirPort communication, change the channel your base station or Time Capsule uses, or change the channel your phone uses.  Nearby base stations using adjacent channels. For example, if base station A is set to channel 1, base station B should be set to channel 6 or 11.4 33 Learning More, Service, and Support You can find more information about using your Time Capsule on the web and in onscreen help. Online Resources For the latest information about the Time Capsule, go to www.apple.com/airport. To register your Time Capsule, go to www.apple.com/register. For AirPort support information, forums with product-specific information and feedback, and the latest Apple software downloads, go to www.apple.com/support/airport. For support outside of the United States, go to www.apple.com/support, and then choose your country.34 Chapter 4 Learning More, Service, and Support Onscreen Help To learn more about using AirPort Utility with your Time Capsule, open AirPort Utility and choose Help > AirPort Utility Help. Obtaining Warranty Service If your Time Capsule appears to be damaged or doesn’t function properly, follow the advice in this booklet, the onscreen help, and the online resources. If your Time Capsule still doesn’t function, go to www.apple.com/support for information about getting warranty service. Finding the Serial Number of Your Time Capsule The serial number is printed on the bottom of your Time Capsule.35 Appendix Time Capsule Specifications and Safety Guidelines Time Capsule Specifications  Frequency Band: 2.4 and 5 GHz  Radio Output Power: Up to 23 dBm (nominal)  Standards: 802.11 DSSS 1 and 2 Mbps standard, 802.11a, 802.11b, 802.11g, and 802.11n specifications Interfaces  1 RJ-45 10/100/1000Base-T Gigabit Ethernet WAN (<)  3 RJ-45 10/100/1000Base-T Gigabit Ethernet LAN (G)  Universal Serial Bus (USB d) 2.0  802.11 a/b/g/n AirPort Extreme wireless Environmental Specifications  Operating Temperature: 32° F to 95° F (0° C to 35° C)  Storage Temperature: –13° F to 140° F (–25° C to 60° C)  Relative Humidity (Operational): 20% to 80% relative humidity  Relative Humidity (Storage): 10% to 90% relative humidity, noncondensing36 Appendix Time Capsule Specifications and Safety Guidelines Size and Weight  Length: 7.75 inches (197.0 mm)  Width: 7.75 inches (197.0 mm)  Height: 1.43 inches (36.33 mm)  Weight: 3.5 pounds (1.6 kilograms) Hardware Media Access Control (MAC) Addresses The Time Capsule has three hardware addresses printed on the bottom of the case:  AirPort ID: The two addresses used to identify the Time Capsule on a wireless network.  Ethernet ID: You may need to provide this address to your ISP to connect your Time Capsule to the Internet. Using Your Time Capsule Safely  The only way to shut off power completely to your Time Capsule is to disconnect it from the power source.  When connecting or disconnecting your Time Capsule, always hold the plug by its sides. Keep fingers away from the metal part of the plug.  Your Time Capsule should not be opened for any reason, even when it’s unplugged. If your Time Capsule needs service,see“Learning More, Service, and Support”on page 33.  Never force a connector into a port. If the connector and port don’t join with reasonable ease, they probably don’t match. Make sure that the connector matches the port and that you’ve positioned the connector correctly in relation to the port.Appendix Time Capsule Specifications and Safety Guidelines 37 About Operating and Storage Temperatures When you’re using your Time Capsule, it is normal for the case to get warm. The Time Capsule case functions as a cooling surface that transfers heat from inside the unit to the cooler air outside. Avoid Wet Locations WARNING:  To reduce the chance of shock or injury, do not use your Time Capsule in or near water or wet locations.  Keep your Time Capsule away from sources of liquid, such as drinks, washbasins, bathtubs, shower stalls, and so on.  Protect your Time Capsule from direct sunlight and rain or other moisture.  Take care not to spill any food or liquid on your Time Capsule. If you do, unplug it before cleaning up the spill.  Do not use your Time Capsule outdoors. The Time Capsule is an indoor product. Do Not Make Repairs Yourself WARNING:  Do not attempt to open your Time Capsule or disassemble it. You run the risk of electric shock and voiding the limited warranty. No user-serviceable parts are inside. About Handling Your Time Capsule may be damaged by improper storage or handling. Be careful not to drop your Time Capsule when transporting it.38 FCC Declaration of Conformity This device complies with part 15 of the FCC rules. Operation is subject to the following two conditions: (1) This device may not cause harmful interference, and (2) this device must accept any interference received, including interference that may cause undesired operation. See instructions if interference to radio or television reception is suspected. Radio and Television Interference This computer equipment generates, uses, and can radiate radiofrequency energy. If it is not installed and used properly—that is, in strict accordance with Apple’s instructions—it may cause interference with radio and television reception. This equipment has been tested and found to comply with the limits for a Class B digital device in accordance with the specifications in Part 15 of FCC rules. These specifications are designed to provide reasonable protection against such interference in a residential installation. However, there is no guarantee that interference will not occur in a particular installation. You can determine whether your computer system is causing interference by turning it off. If the interference stops, it was probably caused by the computer or one of the peripheral devices. If your computer system does cause interference to radio or television reception, try to correct the interference by using one or more of the following measures: • Turn the television or radio antenna until the interference stops. • Move the computer to one side or the other of the television or radio. • Move the computer farther away from the television or radio. • Plug the computer into an outlet that is on a different circuit from the television or radio. (That is, make certain the computer and the television or radio are on circuits controlled by different circuit breakers or fuses.) If necessary, consult an Apple Authorized Service Provider or Apple. See the service and support information that came with your Apple product. Or, consult an experienced radio/television technician for additional suggestions. Important:  Changes or modifications to this product not authorized by Apple Inc. could void the EMC compliance and negate your authority to operate the product. This product was tested for FCC compliance under conditions that included the use of Apple peripheral devices and Apple shielded cables and connectors between system components. It is important that you use Apple peripheral devices and shielded cables and connectors between system components to reduce the possibility of causing interference to radios, television sets, and other electronic devices. You can obtain Apple peripheral devices and the proper shielded cables and connectors through an Appleauthorized dealer. For non-Apple peripheral devices, contact the manufacturer or dealer for assistance. Responsible party (contact for FCC matters only) Apple Inc. Corporate Compliance 1 Infinite Loop M/S 26-A Cupertino, CA 95014 Wireless Radio Use This device is restricted to indoor use when operating in the 5.15 to 5.25 GHz frequency band. Cet appareil doit être utilisé à l’intérieur. Exposure to Radio Frequency Energy The radiated output power of the AirPort Card in this device is below the FCC and EU radio frequency exposure limits for uncontrolled equipment. This device should be operated with a minimum distance of at least 20 cm between the AirPort Card antennas and a person’s body and must not be co-located or operated with any other antenna or transmitter subject to the conditions of the FCC Grant.39 Canadian Compliance Statement This device complies with Industry Canada license-exempt RSS standard(s). Operation is subject to the following two conditions: (1) this device may not cause interference, and (2) this device must accept any interference, including interference that may cause undesired operation of the device. Cet appareil est conforme aux normes CNR exemptes de licence d’Industrie Canada. Le fonctionnement est soumis aux deux conditions suivantes : (1) cet appareil ne doit pas provoquer d’interférences et (2) cet appareil doit accepter toute interférence, y compris celles susceptibles de provoquer un fonctionnement non souhaité de l’appareil. Industry Canada Statement Complies with the Canadian ICES-003 Class B specifications. Cet appareil numérique de la classe B est conforme à la norme NMB-003 du Canada. This device complies with RSS 210 of Industry Canada. Europe–EU Declaration of Conformity Български Apple Inc. декларира, че това WLAN Access Point е в съответствие със съществените изисквания и другите приложими правила на Директива 1999/5/ЕС. Česky Společnost Apple Inc. tímto prohlašuje, že tento WLAN Access Point je ve shodě se základními požadavky a dalšími příslušnými ustanoveními směrnice 1999/5/ES. Dansk Undertegnede Apple Inc. erklærer herved, at følgende udstyr WLAN Access Point overholder de væsentlige krav og øvrige relevante krav i direktiv 1999/5/EF. Deutsch Hiermit erklärt Apple Inc., dass sich das Gerät WLAN Access Point in Übereinstimmung mit den grundlegenden Anforderungen und den übrigen einschlägigen Bestimmungen der Richtlinie 1999/5/EG befinden. Eesti Käesolevaga kinnitab Apple Inc., et see WLAN Access Point vastab direktiivi 1999/5/EÜ põhinõuetele ja nimetatud direktiivist tulenevatele teistele asjakohastele sätetele. English Hereby, Apple Inc. declares that this WLAN Access Point is in compliance with the essential requirements and other relevant provisions of Directive 1999/5/EC. Español Por medio de la presente Apple Inc. declara que este WLAN Access Point cumple con los requisitos esenciales y cualesquiera otras disposiciones aplicables o exigibles de la Directiva 1999/5/CE. Ελληνικά Mε την παρούσα, η Apple Inc. δηλώνει ότι αυτή η συσκευή WLAN Access Point συμμορφώνεται προς τις βασικές απαιτήσεις και τις λοιπές σχετικές διατάξεις της Οδηγίας 1999/5/ΕΚ. Français Par la présente Apple Inc. déclare que l’appareil WLAN Access Point est conforme aux exigences essentielles et aux autres dispositions pertinentes de la directive 1999/5/CE. Islenska Apple Inc. lýsir því hér með yfir að þetta tæki WLAN Access Point fullnægir lágmarkskröfum og öðrum viðeigandi ákvæðum Evróputilskipunar 1999/5/EC. Italiano Con la presente Apple Inc. dichiara che questo dispositivo WLAN Access Point è conforme ai requisiti essenziali ed alle altre disposizioni pertinenti stabilite dalla direttiva 1999/5/CE. Latviski Ar šo Apple Inc. deklarē, ka WLAN Access Point ierīce atbilst Direktīvas 1999/5/EK būtiskajām prasībām un citiem ar to saistītajiem noteikumiem. Lietuvių Šiuo „Apple Inc.“ deklaruoja, kad šis WLAN Access Point atitinka esminius reikalavimus ir kitas 1999/5/EB Direktyvos nuostatas. Magyar Alulírott, Apple Inc. nyilatkozom, hogy a WLAN Access Point megfelel a vonatkozó alapvetõ követelményeknek és az 1999/5/EC irányelv egyéb elõírásainak. 40 Malti Hawnhekk, Apple Inc., jiddikjara li dan WLAN Access Point jikkonforma mal-ħtiġijiet essenzjali u ma provvedimenti oħrajn relevanti li hemm fid-Dirrettiva 1999/5/EC. Nederlands Hierbij verklaart Apple Inc. dat het toestel WLAN Access Point in overeenstemming is met de essentiële eisen en de andere bepalingen van richtlijn 1999/5/EG. Norsk Apple Inc. erklærer herved at dette WLAN Access Point -apparatet er i samsvar med de grunnleggende kravene og øvrige relevante krav i EU-direktivet 1999/5/EF. Polski Niniejszym Apple Inc. oświadcza, że ten WLAN Access Point są zgodne z zasadniczymi wymogami oraz pozostałymi stosownymi postanowieniami Dyrektywy 1999/5/EC. Português Apple Inc. declara que este dispositivo WLAN Access Point está em conformidade com os requisitos essenciais e outras disposições da Directiva 1999/5/CE. Română Prin prezenta, Apple Inc. declară că acest aparat WLAN Access Point este în conformitate cu cerinţele esenţiale şi cu celelalte prevederi relevante ale Directivei 1999/5/CE. Slovensko Apple Inc. izjavlja, da je ta WLAN Access Point skladne z bistvenimi zahtevami in ostalimi ustreznimi določili direktive 1999/5/ES. Slovensky Apple Inc. týmto vyhlasuje, že toto WLAN Access Point spĺňa základné požiadavky a všetky príslušné ustanovenia Smernice 1999/5/ES. Suomi Apple Inc. vakuuttaa täten, että tämä WLAN Access Point tyyppinen laite on direktiivin 1999/5/EY oleellisten vaatimusten ja sitä koskevien direktiivin muiden ehtojen mukainen. Svenska Härmed intygar Apple Inc. att denna WLAN Access Point står i överensstämmelse med de väsentliga egenskapskrav och övriga relevanta bestämmelser som framgår av direktiv 1999/5/EG. A copy of the EU Declaration of Conformity is available at: www.apple.com/euro/compliance This Apple WLAN Access Point can be used in the following countries: AT EE BG FI BE FR CY DE CZ GR DK HU IE IT LV LT LU MT NL PL PT RO SK SL ES SE GB IS LI NO CH Korea Warning Statements B૶ૺૺ(ਜ਼ႜဧ෮໽ቛཅૺၴႁ) ၦૺૺ௴ਜ਼ႜဧ(B૶) ႖ၴኒ႕ጁૺૺച໏჎ച ਜ਼ႜ࿝໏ຫဧዻ௴ઇၕඛ႕ၒചዻඑ, ක౷ხ ࿦࿝໏ຫဧዾ༘ၰཀఁఋ. ෮ቛ၁ધགྷ࿝ಋ൏ધხຫጃ ጄఙඳ໓໕๗௴ဪဧთ႖ኒጯཅਜ਼௻ໜၦၰၗ ၦૺૺ௴ၨ඗ྦ႖઴શഏౘ໏๗༺࿝ຫဧዾ༘࿖ཀఁఋ ఝዽූ૑ ૬ႜ ෟ ა༘ Singapore Wireless Certification41 Taiwan Wireless Statements Taiwan Class B Statement 警告 本電池如果更換不正確會有爆炸的危險 請依製造商說明書處理用過之電池 Japan VCCI Class B Statement Russia Disposal and Recycling Information This symbol indicates that your product must be disposed of properly according to local laws and regulations.When your product reaches its end of life, contact Apple or your local authorities to learn about recycling options. For information about Apple’s recycling program, go to www.apple.com/recycling. European Union — Disposal Information This symbol means that according to local laws and regulations your product should be disposed of separately from household waste.When this product reaches its end of life, take it to a collection point designated by local authorities. Some collection points accept products for free. The separate collection and recycling of your product at the time of disposal will help conserve natural resources and ensure that it is recycled in a manner that protects human health and the environment. Türkiye EEE yönetmeliğine (Elektrikli ve Elektronik Eşyalarda Bazı Zararlı Maddelerin Kullanımının Sınırlandırılmasına Dair Yönetmelik) uygundur.42 Brasil—Informações sobre descarte e reciclagem O símbolo acima indica que este produto e/ou sua bateria não devem ser descartadas no lixo doméstico. Quando decidir descartar este produto e/ou sua bateria, faça-o de acordo com as leis e diretrizes ambientais locais. Para informações sobre o programa de reciclagem da Apple, pontos de coleta e telefone de informações, visite www.apple.com/br/environment Battery Disposal Information Dispose of batteries according to your local environmental laws and guidelines. Deutschland: Dieses Gerät enthält Batterien. Bitte nicht in den Hausmüll werfen. Entsorgen Sie dieses Gerät am Ende seines Lebenszyklus entsprechend der maßgeblichen gesetzlichen Regelungen. Nederlands:  Gebruikte batterijen kunnen worden ingeleverd bij de chemokar of in een speciale batterijcontainer voor klein chemisch afval (kca) worden gedeponeerd. China Battery Statement Taiwan Battery Statementwww.apple.com/airport www.apple.com/support/airport © 2011 Apple Inc. All rights reserved. Apple, the Apple logo, AirPort, AirPort Express, AirPort Extreme, Apple TV, Bonjour, Finder, iPhone, iPod touch, Leopard, Mac, Mac OS, Time Capsule, and Time Machine are trademarks of Apple Inc., registered in the U.S. and other countries. iPad is a trademark of Apple Inc. Other product and company names mentioned herein may be trademarks of their respective companies. 034-5910-A Printed in XXXX Time Capsule Setup Guide3 Contents 5 Chapter 1: Getting Started 7 About Your Time Capsule 8 About the AirPort Software 9 What You Need to Get Started 11 The Time Capsule Status Light 13 Chapter 2: Setting Up Your Time Capsule 14 Using Your Time Capsule to Create Your Wireless Network 17 Using AirPort Utility 19 Creating a New Wireless Network 19 Configuring and Sharing Internet Access 21 Setting Advanced Options 22 Allowing Wireless Clients to Access Your Network Without Entering a Password 23 Using Time Machine with Your Time Capsule 25 Chapter 3: Tips and Troubleshooting 25 If You Can’t Connect to the Internet 25 If You Forgot Your Network Password or Time Capsule Password 26 If Your Time Capsule Isn’t Responding 27 If Your Time Capsule Status Light Flashes Amber4 Contents 28 If Your Printer Isn’t Responding 29 Updating AirPort Software 29 Time Capsule Placement Considerations 30 Items That Can Cause Interference with AirPort 31 Chapter 4: Learning More, Service, and Support 33 Appendix: Time Capsule Specifications and Safety Guidelines 36 Regulatory Compliance Information1 5 1 Getting Started Congratulations on purchasing your Time Capsule. Read this guide to get started. The new Time Capsule offers you the simplicity of fully automated backup for your Wi-Fi network. Using the Time Machine application in Mac OS X v10.5.2 Leopard or later, it’s easy and automatic to back up all the computers on your network to a single Time Capsule. The Time Capsule is also a fully featured AirPort Extreme Base Station that provides simultaneous dual-band wireless networking. When you set up your Time Capsule, it creates two high-speed Wi-Fi networks:  A 2.4 gigahertz (GHz) network for 802.11b, 802.11g, and 802.11n devices, such as iPhone, iPod touch, and older computers  A 5 GHz network for 802.11n and 802.11a devices, such as newer computers and Apple TV Wireless devices join the network that provides them the best performance and compatibility, and the Time Capsule shares your broadband Internet connection with computers and devices on your network.6 Chapter 1 Getting Started With your Time Capsule, you can:  Use the Time Machine application in Mac OS X v10.5.2 (or later) to back up all the computers on your wireless network, as well as computers connected to your Time Capsule using Ethernet. Note: Your first backup with Time Capsule and Time Machine could take overnight or longer, depending on how much data you’re backing up. To speed up the initial backup, use an Ethernet cable to connect your computer to the LAN port on your Time Capsule. For more information about using Time Machine, see “Using Time Machine with Your Time Capsule” on page 23.  Create a password-protected wireless home network, and then connect to the Internet and share the connection with other computers and Wi-Fi devices, such as iPhone, iPod touch, and Apple TV. You can also share files among computers connected to the network.  Create a guest network with or without password protection, to provide Internetonly access to wireless devices, such as computers, iPhone, iPod touch, and Apple TV.  Connect your Time Capsule to your Ethernet network. Wireless-equipped Macintosh, Windows XP, or Windows Vista computers can then have access to an entire network without being connected by a cable.  Connect a supported USB printer to your Time Capsule. Compatible computers on the AirPort network, both wireless and wired, can print to it.  Connect an additional USB hard drive to your Time Capsule. Compatible computers on the AirPort network, both wireless and wired, can access information on the hard disk.Chapter 1 Getting Started 7  Connect a USB hub to your Time Capsule, and then connect multiple USB devices, such as printers or hard disks. All computers on the network have access to those devices. Important: Install AirPort Utility 5.4 from the CD that came with your Time Capsule, or download it using Software Update. Previous versions of AirPort Setup Assistant and AirPort Admin Utility are not compatible with this Time Capsule. About Your Time Capsule Your Time Capsule has five ports on the back:  One 10/100/1000Base-T Gigabit Ethernet Wide Area Network (WAN) port for connecting a DSL or cable modem, or for connecting to an existing Ethernet network  Three 10/100/1000Base-T Gigabit Ethernet Local Area Network (LAN) ports for connecting Ethernet devices, such as printers or computers, or for connecting to an existing Ethernet network 8 Chapter 1 Getting Started  One USB port for connecting a compatible USB printer, hard drive, or hub for connecting several devices The reset button next to the ports is used for troubleshooting your Time Capsule. The status light on the front shows the current status. About the AirPort Software Your Time Capsule works with AirPort Utility, included on the Time Capsule CD. Install AirPort Utility and follow the instructions on the following pages to set up your Time Capsule and your AirPort wireless network. Status light Internet WAN port Power port Power cord USB port Reset button Ethernet ports Security slot Ethernet activity lightChapter 1 Getting Started 9 Note: You must use AirPort Utility v5.4 to set up your Time Capsule. This Time Capsule is not compatible with previous versions of AirPort software. What You Need to Get Started To use your Time Capsule, you need a wireless-enabled computer that’s compliant with IEEE 802.11a, 802.11b, or 802.11g standards, or with an IEEE 802.11n draft specification. To set up your Time Capsule, your computer must meet the requirements listed below. Note: To use your Time Capsule with Time Machine in Mac OS X Leopard, you need to use Mac OS X v10.5.2 or later. To set up your Time Capsule using a Macintosh, you need the following:  A Macintosh computer with an AirPort or AirPort Extreme Card installed to set it up wirelessly, or a Macintosh computer connected to your Time Capsule with an Ethernet cable to set it up using Ethernet AirPort Utility Use AirPort Utility to set up your Time Capsule to create a wireless network, connect to the Internet, and share compatible USB printers and hard disks. You can also connect your Time Capsule to an existing AirPort Extreme wireless network. AirPort Utility is also an advanced tool for setting up and managing the Time Capsule, AirPort Extreme, and AirPort Express Base Stations. Use it to manually adjust network, routing, and security settings and other advanced options. Z AirPort status menu Use the AirPort status menu in the menu bar to switch quickly between AirPort networks, monitor the signal quality of the current network, create a computer-tocomputer network, and turn AirPort on or off. The status menu is available on computers using Mac OS X. 10 Chapter 1 Getting Started  Mac OS X v10.4 or later  AirPort Utility v5.4 or later To set up your Time Capsule using a Windows PC, you need the following:  A Windows PC with 300 MHz or higher processor speed and a compatible 802.11a, 802.11b, or 802.11g wireless card, or a wireless card that complies with an IEEE 802.11n draft specification  Windows XP Home or Professional (with Service Pack 2 installed) or Windows Vista  AirPort Utility v5.4 or later Plugging In Your Time Capsule Before you plug in your Time Capsule, first connect the appropriate cables to the ports you want to use:  Connect the Ethernet cable that’s connected to your DSL or cable modem (if you will connect to the Internet) to the Ethernet WAN (<) port.  Connect a USB cable connected from the USB (d) port on your Time Capsule to a compatible USB printer (if you will print to a USB printer), a hard disk, or a hub.  Connect an Ethernet cable from any Ethernet device to the Ethernet LAN (G) ports. After you’ve connected the cables for all the devices you plan to use, connect the power cord to the power port and plug your Time Capsule into a power outlet. There is no power switch. Important: Use only the power cord that came with your Time Capsule.Chapter 1 Getting Started 11 When you plug your Time Capsule into a power outlet, the status light flashes green for one second and then glows amber while your Time Capsule starts up. After your Time Capsule has started up completely, the status light flashes amber until your Time Capsule has been updated with the correct settings. The status light glows solid green after your Time Capsule is properly set up and connected to the Internet or a network. When you connect Ethernet cables to the Ethernet ports, the lights above them glow solid green. The Time Capsule Status Light The following table explains the Time Capsule light sequences and what they indicate. Light Status/description Off Your Time Capsule is unplugged. Solid amber Your Time Capsule is completing its startup sequence. Flashing amber Your Time Capsule can’t establish a connection to the network or the Internet, or is encountering a problem. Make sure you have installed AirPort Utility and use it to get information about what might cause the status light to flash amber. See “If Your Time Capsule Status Light Flashes Amber” on page 27. Solid green Your Time Capsule is on and working properly. If you choose Flash On Activity from the Status Light pop-up menu (in the Base Station pane of AirPort settings in AirPort Utility), the status light may flash green to indicate normal activity. Flashing amber and green There may be a problem starting up. Your Time Capsule will restart and try again.12 Chapter 1 Getting Started What’s Next After you plug in your Time Capsule, use AirPort Utility to set it up to work with your Internet connection, USB printer or hard disk, or an existing network. AirPort Utility is located in the Utilities folder in the Applications folder on a computer using Mac OS X, and in Start > All Programs > AirPort on a computer using Windows XP or Windows Vista. Solid blue Your Time Capsule is ready to allow a wireless client access to the network. See “Allowing Wireless Clients to Access Your Network Without Entering a Password” on page 22. Light Status/description2 13 2 Setting Up Your Time Capsule This chapter provides information and instructions for connecting your Time Capsule to the Internet, and using AirPort Utility to set it up to create or join a wireless network. This chapter provides an overview of connecting your Time Capsule to the Internet, and using the setup assistant in AirPort Utility to set up your network and other features of your Time Capsule. For more information about wireless networking, and for information about the advanced features of AirPort Utility, refer to “Designing AirPort Networks Using AirPort Utility (Mac OS X v10.5 + Windows)” at www.apple.com/support/airport. After you install AirPort Utility from the CD that came with your Time Capsule, you can do most of your network setup and configuration tasks using the setup assistant in AirPort Utility. To set advanced options, choose Manual Setup from the Base Station menu of AirPort Utility. See “Setting Advanced Options” on page 21.14 Chapter 2 Setting Up Your Time Capsule Using Your Time Capsule to Create Your Wireless Network When you set up your Time Capsule to provide network and Internet access, the following computers and devices can access the wireless AirPort network to share files, play games, and use Internet applications such as web browsers and email applications:  Macintosh computers with AirPort or AirPort Extreme Cards  802.11a, 802.11b, 802.11g, and IEEE 802.11n draft specification wireless-equipped computers  Other Wi-Fi devices Computers connected to your Time Capsule using Ethernet can also access the network to share files and connect to the Internet. With Mac OS X v10.5.2 or later you can set up Time Machine to back up all the computers on the network to your Time Capsule. See “Using Time Machine with Your Time Capsule” on page 23 for more information. When you connect a compatible USB printer to your Time Capsule, supported computers on the network (wired and wireless) can print to it.Chapter 2 Setting Up Your Time Capsule 15 Using Time Capsule to create a wireless network To set it up: 1 Connect your DSL or cable modem to your Time Capsule using the Ethernet WAN (<) port. to Internet DSL or cable modem < Internet WAN port Shared printer Time Capsule to USB ports 2.4 or 5 GHz 2.4 GHz 2.4 or 5 GHz16 Chapter 2 Setting Up Your Time Capsule 2 If you plan to share a USB printer on the network, connect it to the Time Capsule USB (d) port or to a USB hub, using a USB cable. 3 Open AirPort Utility (located in the Utilities folder in the Applications folder on a computer using Mac OS X, and in Start > All Programs > AirPort on a computer using Windows), select your Time Capsule, and then click Continue. 4 Follow the onscreen instructions to create a new network. To print from a computer using Mac OS X v10.5: 1 Choose Apple > System Preferences, and then click Print & Fax. 2 Click Add (+) and select your printer from the list. 3 Click the Add button. If your printer isn’t in the list, use the buttons in the toolbar to search for it. To print from a computer using Mac OS X v10.3 or 10.4: 1 Open Printer Setup Utility (located in the Utilities folder in the Applications folder). 2 Select the printer from the list. If the printer isn’t in the list, click Add and choose Bonjour from the pop-up menu, and then select the printer from the list. To print from a computer using Windows XP or Windows Vista: 1 Install Bonjour for Windows from the CD that came with your Time Capsule. 2 Follow the onscreen instructions to connect to your printer. Computers using AirPort or other compatible wireless cards or adapters can connect to the Internet through your Time Capsule. Computers connected to the Time Capsule Ethernet ports can also access the network and connect to the Internet.Chapter 2 Setting Up Your Time Capsule 17 Wireless computers and computers connected to the Ethernet ports can also communicate with each other through your Time Capsule. Using AirPort Utility To set up and configure your Time Capsule, use the setup assistant in AirPort Utility. AirPort Utility is installed on your computer when you install the software from the Time Capsule CD. On a Macintosh computer using Mac OS X v10.4 or later: 1 Open AirPort Utility, located in the Utilities folder in the Applications folder. 2 Select your Time Capsule and click Continue. If you don’t see the Time Capsule you want to configure, click Rescan to scan for available wireless devices, and then select your Time Capsule from the list. 3 Follow the onscreen instructions to set up your Time Capsule and your wireless network. On a computer using Windows XP (with Service Pack 2) or Windows Vista: 1 Open AirPort Utility, located in Start > All Programs > AirPort. 2 Select your Time Capsule and click Continue.18 Chapter 2 Setting Up Your Time Capsule 3 Follow the onscreen instructions to set up your Time Capsule and your wireless network. The AirPort Utility setup assistant asks you questions about the type of network you want to use and the services you want to set up, and helps you enter the appropriate settings. If you’re using your Time Capsule to connect to the Internet, you need a broadband (DSL or cable modem) account with an Internet service provider (ISP), or a connection to the Internet using an existing Ethernet network. If you received specific information from your ISP (such as a static IP address or a DHCP client ID), you may need to enter it in AirPort Utility. Have this information available when you set up your Time Capsule.Chapter 2 Setting Up Your Time Capsule 19 Creating a New Wireless Network You can use the AirPort Utility setup assistant to create a new wireless network. The setup assistant guides you through the steps necessary to name your network, protect your network with a password, and set other options. If you plan to share a USB printer or USB hard disk on your network: 1 Connect the printer or hard disk to the Time Capsule USB (d) port. 2 Open AirPort Utility, located in the Utilities folder in the Applications folder on a Macintosh, or in Start > All Programs > AirPort on a computer using Windows XP. 3 Select your Time Capsule and click Continue. If you don’t see the Time Capsule you want to configure, click Rescan to scan for available wireless devices, and then select your Time Capsule from the list. 4 Follow the onscreen instructions to create a new network. Configuring and Sharing Internet Access If you plan to share your Internet connection with wireless-enabled computers on your network or with computers connected to the Ethernet ports, you need to set up your Time Capsule as an AirPort Base Station. After your Time Capsule is set up, computers access the Internet through the AirPort network. Your Time Capsule connects to the Internet and transmits information to the computers over the wireless network. Before you use AirPort Utility to set up your Time Capsule, connect your DSL or cable modem to the Time Capsule Ethernet WAN (<) port. If you’re connecting your Time Capsule to an Ethernet network that already has Internet access, connect it to the Ethernet network.20 Chapter 2 Setting Up Your Time Capsule Use the AirPort Utility setup assistant to enter your ISP settings and configure how your Time Capsule shares the settings with other computers. 1 Open AirPort Utility, located in the Utilities folder in the Applications folder on a computer using Mac OS X, or in Start > All Programs > AirPort on a computer using Windows XP. 2 Select your Time Capsule and click Continue. If you’re making changes to a Time Capsule that has already been set up, you might have to connect to the network it’s created before making changes to the Time Capsule. To choose the wireless network you want to change on a Macintosh, use the AirPort status menu in the menu bar. On a computer using Windows XP, hold the pointer over the wireless connection icon until you see the network name (SSID), and then choose it from the list if there are multiple networks available. 3 Follow the onscreen instructions to configure and share Internet access on your Time Capsule. AirPort Utility provides a quick and easy way to set up your Time Capsule and network. If you want to set additional options for your network, such as restricting access to your network or setting advanced DHCP options, choose Manual Setup from the Base Station menu of AirPort Utility. Chapter 2 Setting Up Your Time Capsule 21 Setting Advanced Options Use AirPort Utility to set up your Time Capsule manually if you want to set advanced Time Capsule options such as advanced security options, closed networks, DHCP lease time, access control, power controls, user accounts, and more. To set advanced options: 1 Open AirPort Utility, located in the Utilities folder in the Applications folder on a Macintosh, and in Start > All Programs > AirPort on a computer using Windows XP. 2 If there’s more than one wireless device in the list, select the one you want to configure. If you don’t see the Time Capsule you want to configure, click Rescan to scan for available wireless devices, and then select your Time Capsule from the list. If you’re making changes to a Time Capsule that has already been set up, you might have to connect to the network it’s created before making changes to your Time Capsule. To choose the wireless network you want to change, on a Macintosh use the AirPort status menu in the menu bar. On a computer using Windows XP, hold the pointer over the wireless connection icon until you see the network name (SSID), and then choose it from the list if there are multiple networks available. 3 Choose Manual Setup from the Base Station menu. If you’re prompted for a password, enter it. For more about the manual setup features in AirPort Utility, see “Designing AirPort Networks Using AirPort Utility (Mac OS X v10.5 + Windows)” at www.apple.com/ support/airport.22 Chapter 2 Setting Up Your Time Capsule Allowing Wireless Clients to Access Your Network Without Entering a Password If your network is password-protected using WPA Personal or WPA/WPA2 Personal, you can provide wireless clients access to your network without requiring them to enter the network password. When you allow a client access to your network, the client’s name and wireless MAC address (or AirPort ID) are stored in the access control list of AirPort Utility until you remove the client from the list. You can also provide 24 hours of access, after which time the client will no longer be able to access your network. When you give a client access to your wireless network, the client doesn’t need to enter the network password. To allow a client to access your network without entering the network password: 1 Open AirPort Utility, select your Time Capsule, and then choose Manual Setup from the Base Station menu. Enter the password if necessary. 2 Choose Add Wireless Clients from the Base Station menu. 3 Select how you want the client to access the network:  Select PIN to enter the eight-digit number provided by the client requesting network access.  Select “First attempt” to allow network access to the first client attempting to join the network. While the Time Capsule waits for a client to join the network, the LED glows blue.Chapter 2 Setting Up Your Time Capsule 23 Select “Limit client’s access to 24 hours” if you want to provide just one day of access to your network. If you don’t select this option, the client will have access until you remove the client from the list. Using Time Machine with Your Time Capsule With the Time Machine application in Mac OS X Leopard you can back up everything on your computer, including your photos, music, movies, and documents. After you set up Time Machine, it automatically backs up your computer on a regular basis. If you’re using Mac OS X v10.5.2 or later, the first time you connect to your Time Capsule, Time Machine asks if you’d like to use it to back up your files. Click “Use as Backup Disk,” and Time Machine takes care of the rest. Use the Time Machine pane of System Preferences in Mac OS X Leopard to set up automatic backups, change to a different backup disk, or adjust other settings. To set up or adjust Time Machine on a computer using Mac OS X Leopard: 1 Choose Apple > System Preferences, and then click Time Machine. 2 Slide the switch to ON. 3 Click Change Disk. 4 Choose your Time Capsule and click “Use for Backup.”24 Chapter 2 Setting Up Your Time Capsule Your first backup with Time Capsule and Time Machine could take overnight or longer, depending on how much data you’re backing up. To speed up the initial backup, connect your Time Capsule to your computer using Ethernet. In each subsequent backup, Time Machine backs up only files that have changed since the previous backup, so the backups don’t take as long. Time Capsule is a great wireless backup solution for portable computers. Since the first backup can take some time, plug your portable into a power adapter—this conserves battery power and guarantees that backups won’t be interrupted. Also, for the best wireless performance, place your portable computer in the same room as your Time Capsule. If you shut down your Mac or put it to sleep during a backup, Time Machine stops the backup and then continues from where it left off after your Mac starts up again. For more information about Time Machine, choose Help > Mac Help from the Finder menu on a computer using Mac OS X Leopard, and then type Time Machine in the search field.3 25 3 Tips and Troubleshooting You can quickly solve most problems with your Time Capsule by following the advice in this chapter. If You Can’t Connect to the Internet  Try connecting to the Internet directly from your computer. If you can’t connect, check to make sure your network settings are correct. If they appear to be correct and you still can’t connect, contact your Internet service provider (ISP).  Make sure you’re connecting to the correct wireless network. If You Forgot Your Network Password or Time Capsule Password You can clear the AirPort network password or Time Capsule password by resetting your Time Capsule. To reset the Time Capsule password: 1 Use something pointed (such as a ballpoint pen) to press and hold down the reset button for one second. Important: If you hold the reset button for more than one second, you may lose your network settings.26 Chapter 3 Tips and Troubleshooting 2 Select your AirPort network.  On a Macintosh, use the AirPort status menu in the menu bar to select the network created by your Time Capsule (the network name doesn’t change).  On a computer using Windows XP, hold the pointer over the wireless connection icon until you see your AirPort network name (SSID), and choose it from the list if there are multiple networks available. 3 Open AirPort Utility (in the Utilities folder in the Applications folder on a Macintosh, and in Start > All Programs > AirPort on a computer using Windows XP). 4 Select your Time Capsule, and then choose Manual Setup from the Base Station menu. 5 Click AirPort in the toolbar, and then click Base Station. 6 Enter a new password for your Time Capsule. 7 Click Wireless and choose an encryption method from the Wireless Security pop-up menu to turn on encryption and activate password protection for your AirPort network. If you turn on encryption, enter a new password for your AirPort network. 8 Click Update to restart your Time Capsule and load the new settings. If Your Time Capsule Isn’t Responding Try unplugging it and plugging it back in. If your Time Capsule stops responding completely, you may need to reset it to the factory default settings. Important: Resetting your Time Capsule to factory default settings erases all of the current settings and resets them to the settings that came with your Time Capsule.Chapter 3 Tips and Troubleshooting 27 To return your Time Capsule to the factory settings: m Use something pointed (such as a ballpoint pen) to press down and hold the reset button until the status light flashes quickly (about 5 seconds). Your Time Capsule resets with the following settings:  Your Time Capsule receives its IP address using DHCP.  The network name is reset to Apple Network XXXXXX (where XXXXXX is replaced with the last six digits of the AirPort ID).  The Time Capsule password is reset to public. If your Time Capsule still isn’t responding, try the following: 1 Unplug your Time Capsule. 2 Use something pointed to press and hold down the reset button while you plug in your Time Capsule. If Your Time Capsule Status Light Flashes Amber The Ethernet cable may not be connected properly, your Time Capsule may be out of range of an AirPort network, or there may be a problem with your Internet service provider. If you’re connected to the Internet with a DSL or cable modem, the modem may have lost its connection to the network or the Internet. Even if the modem seems to be working properly, try disconnecting it from its power supply, waiting a few seconds, and then reconnecting it. Make sure your Time Capsule is connected directly to the modem via Ethernet before reconnecting power to the modem.28 Chapter 3 Tips and Troubleshooting For more information about why the light is flashing, open AirPort Utility, select your Time Capsule, and then choose Manual Setup from the Base Station menu. Click Base Station Status to display information about the flashing light. You can also select “Monitor base station for problems” in AirPort preferences. If the base station has a problem, AirPort Utility opens and walks you through solving the problem. If Your Printer Isn’t Responding If you connected a printer to the USB port on your Time Capsule and the computers on the AirPort network can’t print, try the following: 1 Make sure the printer is plugged in and turned on. 2 Make sure the cables are securely connected to the printer and to the Time Capsule USB port. 3 Make sure the printer is selected in the Printer List window on client computers. On a Macintosh using Mac OS X v10.5 or later:  Choose Apple > System Preferences, and then click Print & Fax.  Click Add (+) and select your printer in the list, and then click Add (+). On a Macintosh using Mac OS X v10.2.7 or later:  Open Printer Setup Utility, located in the Utilities folder in the Applications folder.  If the printer isn’t in the list, click Add.  Choose Bonjour from the pop-up menu, select the printer and click Add (+).Chapter 3 Tips and Troubleshooting 29 On a computer using Windows XP:  Open “Printers and Faxes” from the Start menu.  Select the printer. If the printer isn’t in the list, click Add Printer and then follow the onscreen instructions. 4 Turn off the printer, wait a few seconds, and then turn it back on. Updating AirPort Software Apple periodically updates AirPort software. It is recommended that you update your Time Capsule to use the latest software. You can select “Check for updates when opening AirPort Utility,” or “Check for updates” in AirPort preferences. If you select “Check for updates,” choose an increment of time, such as weekly, from the pop-up menu to automatically check for updates. Time Capsule Placement Considerations The following recommendations can help your Time Capsule achieve the best wireless range and network coverage.  Place your Time Capsule in an open area where there are few obstructions, such as large pieces of furniture or walls. Try to place it away from metallic surfaces.  If you place your Time Capsule behind furniture, keep at least an inch of space between the Time Capsule and the edge of the furniture.  Avoid placing your Time Capsule in areas surrounded by metal surfaces on three or more sides. 30 Chapter 3 Tips and Troubleshooting  If you place your Time Capsule in an entertainment center with your stereo equipment, avoid surrounding your Time Capsule with audio, video, or power cables. Place your Time Capsule so that the cables are to one side. Maintain as much space as possible between your Time Capsule and the cables.  Try to place your Time Capsule at least 25 feet (7.6 meters) from any microwave oven, 2.4 or 5 gigahertz (GHz) cordless phone, and other sources of interference.  Do not place other objects (books, papers, small pets, etc.) on top of the Time Capsule. It may interfere with Time Capsule cooling. Items That Can Cause Interference with AirPort The farther away the interference source, the less likely it is to cause a problem. The following can interfere with AirPort communication:  Microwave ovens  Direct Satellite Service (DSS) radio frequency leakage  The original coaxial cable that came with certain types of satellite dishes. Contact the device manufacturer and obtain newer cables.  Certain electrical devices such as power lines, electrical railroad tracks, and power stations  Cordless telephones that operate in the 2.4 or 5 GHz range. If you have problems with your phone or AirPort communication, change the channel your base station or Time Capsule uses, or change the channel your phone uses.  Nearby base stations using adjacent channels. For example, if base station A is set to channel 1, base station B should be set to channel 6 or 11.4 31 4 Learning More, Service, and Support You can find more information about using your Time Capsule on the web and in onscreen help. Online Resources For the latest information about the Time Capsule, go to www.apple.com/airport. To register your Time Capsule (if you didn’t do it when you installed the software on the Time Capsule CD), go to www.apple.com/register. For AirPort support information, forums with product-specific information and feedback, and the latest Apple software downloads, go to www.apple.com/support/ airport. For support outside of the United States, go to www.apple.com/support, and then choose your country.32 Chapter 4 Learning More, Service, and Support Onscreen Help To learn more about using AirPort Utility with your Time Capsule, open AirPort Utility and choose Help > AirPort Utility Help. Obtaining Warranty Service If your Time Capsule appears to be damaged or doesn’t function properly, please follow the advice in this booklet, the onscreen help, and the online resources. If your Time Capsule still doesn’t function, go to www.apple.com/support for information about getting warranty service. Finding the Serial Number of Your Time Capsule The serial number is printed on the bottom of your Time Capsule.33 Appendix Time Capsule Specifications and Safety Guidelines Time Capsule Specifications  Frequency Band: 2.4 and 5 GHz  Radio Output Power: Up to 23 dBm (nominal)  Standards: 802.11 DSSS 1 and 2 Mbps standard, 802.11a, 802.11b, 802.11g specifications, and a draft 802.11n specification Interfaces  1 RJ-45 10/100/1000Base-T Gigabit Ethernet WAN (<)  3 RJ-45 10/100/1000Base-T Gigabit Ethernet LAN (G)  Universal Serial Bus (USB d) 2.0  802.11 a/b/g/n AirPort Extreme wireless Environmental Specifications  Operating Temperature: 32° F to 95° F (0° C to 35° C)  Storage Temperature: –13° F to 140° F (–25° C to 60° C)  Relative Humidity (Operational): 20% to 80% relative humidity  Relative Humidity (Storage): 10% to 90% relative humidity, noncondensing34 Appendix Time Capsule Specifications and Safety Guidelines Size and Weight  Length: 7.75 inches (197.0 mm)  Width: 7.75 inches (197.0 mm)  Height: 1.43 inches (36.33 mm)  Weight: 3.5 pounds (1.6 kilograms) Hardware Media Access Control (MAC) Addresses The Time Capsule has three hardware addresses printed on the bottom of the case:  AirPort ID: The two addresses used to identify the Time Capsule on a wireless network.  Ethernet ID: You may need to provide this address to your ISP to connect your Time Capsule to the Internet. Using Your Time Capsule Safely  The only way to shut off power completely to your Time Capsule is to disconnect it from the power source.  When connecting or disconnecting your Time Capsule, always hold the plug by its sides. Keep fingers away from the metal part of the plug.  Your Time Capsule should not be opened for any reason, even when it’s unplugged. If your Time Capsule needs service, see “Learning More, Service, and Support” on page 31.  Never force a connector into a port. If the connector and port don’t join with reasonable ease, they probably don’t match. Make sure that the connector matches the port and that you’ve positioned the connector correctly in relation to the port.Appendix Time Capsule Specifications and Safety Guidelines 35 About Operating and Storage Temperatures  When you’re using your Time Capsule, it is normal for the case to get warm. The Time Capsule case functions as a cooling surface that transfers heat from inside the unit to the cooler air outside. Avoid Wet Locations  Keep your Time Capsule away from sources of liquid, such as drinks, washbasins, bathtubs, shower stalls, and so on.  Protect your Time Capsule from direct sunlight and rain or other moisture.  Take care not to spill any food or liquid on your Time Capsule. If you do, unplug it before cleaning up the spill.  Do not use your Time Capsule outdoors. The Time Capsule is an indoor product. Do Not Make Repairs Yourself About Handling Your Time Capsule may be damaged by improper storage or handling. Be careful not to drop your Time Capsule when transporting it. WARNING: To reduce the chance of shock or injury, do not use your Time Capsule in or near water or wet locations. WARNING: Do not attempt to open your Time Capsule or disassemble it. You run the risk of electric shock and voiding the limited warranty. No user-serviceable parts are inside.36 Regulatory Compliance Information Wireless Radio Use This device is restricted to indoor use due to its operation in the 5.15 to 5.25 GHz frequency range to reduce the potential for harmful interference to cochannel Mobile Satellite systems. Cet appareil doit être utilisé à l’intérieur. Exposure to Radio Frequency Energy The radiated output power of this device is well below the FCC and EU radio frequency exposure limits. However, this device should be operated with a minimum distance of at least 20 cm between its antennas and a person’s body and the antennas used with this transmitter must not be colocated or operated in conjunction with any other antenna or transmitter subject to the conditions of the FCC Grant. FCC Declaration of Conformity This device complies with part 15 of the FCC rules. Operation is subject to the following two conditions: (1) This device may not cause harmful interference, and (2) this device must accept any interference received, including interference that may cause undesired operation. See instructions if interference to radio or television reception is suspected. Radio and Television Interference This computer equipment generates, uses, and can radiate radio-frequency energy. If it is not installed and used properly—that is, in strict accordance with Apple’s instructions—it may cause interference with radio and television reception. This equipment has been tested and found to comply with the limits for a Class B digital device in accordance with the specifications in Part 15 of FCC rules. These specifications are designed to provide reasonable protection against such interference in a residential installation. However, there is no guarantee that interference will not occur in a particular installation. You can determine whether your computer system is causing interference by turning it off. If the interference stops, it was probably caused by the computer or one of the peripheral devices. If your computer system does cause interference to radio or television reception, try to correct the interference by using one or more of the following measures:  Turn the television or radio antenna until the interference stops.  Move the computer to one side or the other of the television or radio.  Move the computer farther away from the television or radio.  Plug the computer into an outlet that is on a different circuit from the television or radio. (That is, make certain the computer and the television or radio are on circuits controlled by different circuit breakers or fuses.) If necessary, consult an Apple Authorized Service Provider or Apple. See the service and support information that came with your Apple product. Or, consult an experienced radio/television technician for additional suggestions. Important: Changes or modifications to this product not authorized by Apple Inc. could void the EMC compliance and negate your authority to operate the product.37 This product was tested for FCC compliance under conditions that included the use of Apple peripheral devices and Apple shielded cables and connectors between system components. It is important that you use Apple peripheral devices and shielded cables and connectors between system components to reduce the possibility of causing interference to radios, television sets, and other electronic devices. You can obtain Apple peripheral devices and the proper shielded cables and connectors through an Apple-authorized dealer. For non-Apple peripheral devices, contact the manufacturer or dealer for assistance. Responsible party (contact for FCC matters only) Apple Inc., Corporate Compliance, 1 Infinite Loop M/S 26-A, Cupertino, CA 95014-2084 Industry Canada Statement This Class B device meets all requirements of the Canadian interference-causing equipment regulations. Cet appareil numérique de la Class B respecte toutes les exigences du Règlement sur le matériel brouilleur du Canada. VCCI Class B Statement Europe—EU Declaration of Conformity For more information, see www.apple.com/euro/ compliance. European Union — Disposal Information This symbol means that according to local laws and regulations your product should be disposed of separately from household waste. When this product reaches its end of life, take it to a collection point designated by local authorities. Some collection points accept products for free. The separate collection and recycling of your product at the time of disposal will help conserve natural resources and ensure that it is recycled in a manner that protects human health and the environment. Disposal and Recycling Information This product has an internal battery. Please dispose of it according to your local environmental laws and guidelines. For information about Apple’s recycling program, go to www.apple.com/environment. California: The coin cell battery in your product contains perchlorates. Special handling and disposal may apply. Refer to www.dtsc.ca.gov/hazardouswaste/ perchlorate. Deutschland: Dieses Gerät enthält Batterien. Bitte nicht in den Hausmüll werfen. Entsorgen Sie dieses Gerätes am Ende seines Lebenszyklus entsprechend der maßgeblichen gesetzlichen Regelungen. Nederlands: Gebruikte batterijen kunnen worden ingeleverd bij de chemokar of in een speciale batterijcontainer voor klein chemisch afval (kca) worden gedeponeerd.38 Taiwan: Singapore Wireless Certification Taiwan Warning Statements Korea Warning Statements © 2009 Apple Inc. All rights reserved. Apple, the Apple logo, AirPort, AirPort Express, AirPort Extreme, Apple TV, Bonjour, iPod, Leopard, Macintosh, Mac OS, and Time Capsule are trademarks of Apple Inc., registered in the U.S. and other countries. Finder, iPhone, and Time Machine are trademarks of Apple Inc. Other product and company names mentioned herein may be trademarks of their respective companies.www.apple.com/airport www.apple.com/support/airport 034-4704-A Printed in XXXX Code Signing GuideContents About Code Signing 4 At a Glance 5 Prerequisites 5 See Also 5 Code Signing Overview 6 The Benefits Of Signing Code 6 Digital Signatures and Signed Code 8 Code Requirements 8 The Role of Trust in Code Signing 9 Code Signing Tasks 11 Obtaining a Signing Identity 11 Adding an Info.plist to Single-File Tools 15 Signing Your Code 17 What to Sign 17 When to Sign 18 Using the codesign Command 18 Using the spctl Tool to Test Code Signing 21 Shipping and Updating Your Product 23 Code Signing Requirement Language 25 Language Syntax 25 Evaluation of Requirements 26 Constants 26 String Constants 26 Integer Constants 27 Hash Constants 27 Variables 27 Logical Operators 27 Comparison Operations 28 Equality 28 Inequality 29 Existence 29 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 2Constraints 29 Identifier 29 Info 30 Certificate 30 Trusted 32 Entitlement 33 Code Directory Hash 33 Requirement Sets 34 Document Revision History 36 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 3 ContentsCode signing is a security technology, used in OS X, that allows you to certify that an app was created by you. Once an app is signed, the system can detect any change to the app—whether the change is introduced accidentally or by malicious code. Hash Message digest Digital signature Encrypt Signer’s certificate Code-signed data Signer’s private key 10101100100 10111100001 Data Duis autem vel eum vulputate velit esse molestie consequat, vel illum dolore. 00/00/00 Lorem Ipsum Lorem Ipsum Dolor Lorem Ipsum Dolor Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. Users appreciate code signing. After installing a new version of a code-signed app, a user is not bothered with alerts asking again for permission to access the keychain or similar resources. As long as the new version uses the same digital signature, OS X can treat the new app exactly as it treated the previous one. Other OS X security features, such as App Sandbox and parental controls, also depend on code signing. In most cases, you can rely on Xcode’s automatic code signing (described in Tools Workflow Guide for Mac ), which requires only that you specify a code signing identity in the build settingsfor your project. This document is for readers who must go beyond automatic code signing—perhaps to troubleshoot an unusual problem, or to incorporate the codesign(1) tool into a build system. 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 4 About Code SigningAt a Glance The elements of code signing include code signatures, code signing identities, code signing certificates, and security trust policies. Be sure to understand these concepts if you need to perform code signing outside of Xcode. Relevant chapter: “Code Signing Overview” (page 6) Before you can sign code, you must obtain or create a code signing identity. You then sign your code and prepare it for distribution. Relevant chapter: “Code Signing Tasks” (page 11) To specify recommended criteria for verifiers to use when evaluating your app’s code signature, you use a requirements language specific to the codesign(1) and csreq(1) commands. You then save your criteria to a binary file as part of your Xcode project. Relevant chapter: “Code Signing Requirement Language” (page 25) Prerequisites Read Security Overview to understand the place of code signing in the OS X security picture. See Also For descriptions of the command-line toolsfor performing code signing,see the codesign(1) and csreq(1) man pages. About Code Signing At a Glance 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 5Code signing is a security technique that can be used to ensure code integrity, to determine who developed a piece of code, and to determine the purposes for which a developer intended a piece of code to be used. Although the code signing system performs policy checks based on a code signature, it is up to the caller to make policy decisions based on the results of those checks. When it is the operating system that makes the policy checks, whether your code will be allowed to run in a given situation depends on whether you signed the code and on the requirements you included in the signature. This chapter describes the benefits of signing code and introduces some of the basic concepts you need to understand in order to carry out the code signing process. Before you read this chapter, you should be familiar with the concepts described in Security Overview. The Benefits Of Signing Code When a piece of code has been signed, it is possible to determine reliably whether the code has been modified by someone other than the signer. The system can detect such alternation whether it was intentional (by a malicious attacker, for example) or accidental (as when a file gets corrupted). In addition, through signing, a developer can state that an app update is valid and should be considered by the system as the same app as the previous version. For example,suppose a user grantsthe SurfWriter app permission to access a keychain item. Each time SurfWriter attempts to access that item, the system must determine whether it is indeed the same app requesting access. If the app is signed, the system can identify the app with certainty. If the developer updates the app and signs the new version with the same unique identifier, the system recognizes the update as the same app and gives it access without requesting verification from the user. On the other hand, if SurfWriter is corrupted or hacked, the signature no longer matches the previous signature; the system detects the change and refuses access to the keychain item. Similarly, if you use Parental Controls to prevent your child from running a specific game, and that game has been signed by its manufacturer, your child cannot circumvent the control by renaming or moving files. Parental Controls uses the signature to unambiguously identify the game regardless of its name, location, or version number. All sorts of code can be signed, including tools, applications, scripts, libraries, plug-ins, and other “code-like” data. 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 6 Code Signing OverviewCode signing has three distinct purposes. It can be used to: ● ensure that a piece of code has not been altered ● identify code as coming from a specific source (a developer or signer) ● determine whether code is trustworthy for a specific purpose (for example, to access a keychain item). To enable signed code to fulfill these purposes, a code signature consists of three parts: ● A seal, which is a collection of checksums or hashes of the various parts of the code, such as the identifier, the Info.plist, the main executable, the resource files, and so on. The seal can be used to detect alterations to the code and to the app identifier. ● A digital signature, which signs the seal to guarantee its integrity. The signature includes information that can be used to determine who signed the code and whether the signature is valid. ● A unique identifier, which can be used to identify the code or to determine to which groups or categories the code belongs. This identifier can be derived from the contents of the Info.plist for the app, or can be provided explicitly by the signer. For more discussion of digital signatures, see the following section, “Digital Signatures and Signed Code.” To learn more about how a code signature is used to determine the signed code’s trustworthiness for a specific purpose, see “Code Requirements” (page 8). Note that code signing deals primarily with running code. Although it can be used to ensure the integrity of stored code (on disk, for example), that's a secondary use. To fully appreciate the uses of code signing, you should be aware of some things that signing cannot do: ● It can’t guarantee that a piece of code is free of security vulnerabilities. ● It can’t guarantee that an app will not load unsafe or altered code—such as untrusted plug-ins—during execution. ● It is not a digital rights management (DRM) or copy protection technology. Although the system could determine that a copy of your app had not been properly signed by you, or that its copy protection had been hacked, thus making the signature invalid, there is nothing to prevent a user from running the app anyway. Code Signing Overview The Benefits Of Signing Code 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 7Digital Signatures and Signed Code As explained in Security Overview, a digital signature uses public key cryptography to ensure data integrity. Like a signature written with ink on paper, a digital signature can be used to identify and authenticate the signer. However, a digital signature is more difficult to forge, and goes one step further: it can ensure that the signed data has not been altered. This is somewhat like designing a paper check or money order in such a way that if someone alters the written amount of money, a watermark with the text “Invalid” becomes visible on the paper. To create a digitalsignature, the signing software computes a special type of checksum called a hash (or digest) based on a piece of data or code and encrypts that hash with the signer’s private key. This encrypted hash is called a signature. To verify that signature, the verifying software computes a hash of the data or code. It then uses the signer’s public key to decrypt the signature, thus obtaining the original hash as computed by the signer. If the two hashes match, the data has not been modified since it was signed by someone in possession of the signer’s private key. Signed code contains several digital signatures: ● If the code is universal, the object code for each slice (architecture) is signed separately. This signature is stored within the binary file itself. ● Various components of the application bundle (such as the Info.plist file, if there is one) are also signed. These signatures are stored in a file called _CodeSignature/CodeResources within the bundle. Code Requirements It is up to the system or program that is launching or loading signed code to decide whether to verify the signature and, if it does, to determine how to evaluate the results of that verification. The criteria used to evaluate a code signature are called code requirements. The signer can specify requirements when signing the code; such requirements are referred to as internal requirements. A verifier can read any internal requirements before deciding how to treat signed code. However, it is up to the verifier to decide what requirements to use. For example, Safari could require a plug-in to be signed by Apple in order to be loaded, regardless of whether that plug-in’s signature included internal requirements. One major purpose of code signatures is to allow the verifier to identify the code (such as a program, plug-in, or script) to determine whether it is the same code the verifier has seen before. The criteria used to make this determination are referred to asthe code’s designated requirement. For example, the designated requirement for Apple Mail might be "was signed by Apple and the identifier is com.apple.Mail". Code Signing Overview Digital Signatures and Signed Code 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 8To see how this works in practice, assume the user has granted permission to the Apple Mail application to access a keychain item. The keychain uses Mail’s designated requirement to identify it: the keychain records the identifier (com.apple.Mail) and the signer of the application (Apple) to identify the program allowed to access the keychain item. Whenever Mail attempts to access this keychain item, the keychain looks at Mail’s signature to make sure that the program has not been corrupted, that the identifier is com.apple.Mail, and that the program wassigned by Apple. If everything checks out, the keychain gives Mail accessto the keychain item. When Apple issues a new version of Mail, the new version includes a signature, signed by Apple, that identifies the application as com.apple.Mail. Therefore, when the user installs the new version of Mail and it attempts to access the keychain item, the keychain recognizes the updated version as the same program and does not prompt the user for verification. Architecturally, a code requirement is a script, written in a dedicated language, that describes conditions (restrictions) the code mustsatisfy to be acceptable forsome purpose. It is up to you whether to specify internal requirements when you sign code. The program identifier or the entire designated requirement can be specified by the signer, or can be inferred by the codesign tool at the time of signing. In the absence of an explicitly specified designated requirement, the codesign utility typically builds a designated requirement from the name of the program found in its Info.plist file and the chain of signatures securing the code signature. Note that validation of signed code against a set of requirements is performed only when the system or some other program needs to determine whether it is safe to trust that code. For example, unsigned code injected into an application through a buffer overflow can still execute because it was not part of the application at launch time. Similarly, an app with an invalid code identifier may still run (depending on policy), but does not get automatic access to keychain items created by previous versions of the app. The Role of Trust in Code Signing Trust is determined by policy. A security trust policy determines whether a particular identity should be accepted for allowing something, such as access to a resource or service. Various parts of OS X have different policies, and make this determination differently. For example, a specialized client application might include a set of root certificatesthat it trusts when communicating with a specific set ofservers. However, these root certificates would not be trusted if those same servers were accessed using a web browser. In much the same way, many parts of OS X (the OS X keychain and parental controls, for example) do not care what entity signed an application; they care only whether the signer has changed since the last time the signature was checked. They use the code signature’s designated requirement for this purpose. Code Signing Overview The Role of Trust in Code Signing 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 9Other parts of OS X constrain acceptable signatures to only those drawn from certificate authorities (root certificates) that are trusted anchors on the system performing the validation. For those checks, the nature of the identity used matters. The Application Firewall is one example of this type of policy. Self-signed identities and self-created certificate authorities do not work for these purposes unless the user has explicitly told the operating system to trust the certificates. You can modify the code signing polices of OS X with the spctl(8) command. Code Signing Overview The Role of Trust in Code Signing 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 10This chapter gives procedures and examplesfor the code signing process. It covers what you need to do before you begin to sign code, how to sign code, and how to ship the code you signed. Obtaining a Signing Identity To sign code, you need a code signing identity, which is a private key plus a digital certificate. The digital certificate must have a usage extension that enables it to be used for signing and it must contain the public key that corresponds to the private key. You can use more than one signing identity, each for its own purpose, such as one to be used for beta seeds and one for final, released products. However, most organizations use only one identity. You can obtain two types of certificates from Apple using the developer portal: Developer ID certificates (for public distribution) and distribution certificates (for submitting to the Mac App Store). To learn more about this, read Tools Workflow Guide for Mac . Note: Apple uses the industry-standard form and format of code signing certificates. Therefore, if your company already has a third-party signing identity that you use to sign code on other systems, you can use it with the OS X codesign command. Similarly, if your company is a certificate issuing authority, contact your IT department to find out how to get a signing certificate issued by your company. If you do not have an existing identity, you should first create one using the Certificate Assistant, which is provided as part of the Keychain Access application. This tool creates a public key, puts it into your keychain, and optionally can produce a certificate signing request that you can then send to Apple (or another certificate authority). The certificate authority then sends you a certificate that, in combination with your private key, completes your digital identity. To import a signing certificate with Keychain Access 1. In Keychain Access (available in /Applications/Utilities), choose File > Import Items. 2. Choose a destination keychain for the identity. 3. Choose the certificate file. 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 11 Code Signing Tasks4. Click Open. Note: If the original private key is not already in your keychain (for example, if you are moving from one development machine to another), you must also import the private key in the same way. Before you obtain a code signing identity and sign your code, consider the following points: ● Do not ship applications signed by self-signed certificates. A self-signed certificate created with the Certificate Assistant is not recognized by users’ operating systems as a valid certificate for any purpose other than validating the designated requirement of your signed code. Because a self-signed certificate has not been signed by a recognized root certificate authority, the user can only verify that two versions of your application came from the same source; they cannot verify that your company is the true source of the code. For more information about root authorities, see “Security Concepts”. ● Depending on your company’s internal policies, you might have to involve your company’s Build and Integration, Legal, and Marketing departments in decisions about what sort of signing identity to use and how to obtain it. You should start this process well in advance of the time you need to actually sign the code for distribution to customers. ● Any signed version of your code that gets into the hands of users will appear to have been endorsed by your company for use. Therefore, you might not want to use your “final” signing identity to sign code that is still in development. ● A signing identity, no matter how obtained, is completely compromised if it is ever out of the physical control of whoever is authorized to sign the code. That means that the signing identity’s private key must never, under any circumstances, be given to end users, and should be restricted to one or a small number of trusted persons within your company. Before obtaining a signing identity and proceeding to sign code, you must determine who within your company will possess the identity, who can use it, and how it will be kept safe. For example, if the identity must be used by more than one person, you can keep it in the keychain of a secure computer and give the password of the keychain only to authorized users, or you can put the identity on a smart card to which only authorized users have the PIN. ● A self-signed certificate created by the Certificate Assistant is adequate for internal testing and development, regardless of what procedures you put in place to sign released products. To use the Certificate Assistant to create a self-signed signing identity 1. Open Applications > Utilities > Keychain Access. Code Signing Tasks Obtaining a Signing Identity 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 122. From the Keychain Access menu, choose Certificate Assistant > Create a Certificate. 3. Fill in a name for the certificate. This name appears in the Keychain Access utility as the name of the certificate. 4. Choose Self Signed Root from the Type popup menu. Code Signing Tasks Obtaining a Signing Identity 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 135. Check the Let me override defaults checkbox. Click Continue. 6. Specify a serial number for the certificate. Any number will do as long as you have no other certificate with the same name and serial number. Code Signing Tasks Obtaining a Signing Identity 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 147. Choose Code Signing from the Certificate Type popup menu. Click Continue. 8. Fill in the information for the certificate. Click Continue. 9. Accept the defaults for the rest of the dialogs. Adding an Info.plist to Single-File Tools As discussed in “Code Requirements” (page 8), the system often uses the Info.plist file of an application bundle to determine the code’s designated requirement. Although single-file tools don’t normally have an Info.plist, you can add one. To do so, use the following procedure: 1. Add an Info.plist file to your project (including adding it to your source control). 2. Make sure the Info.plist file has the following keys: ● CFBundleIdentifier ● CFBundleName Code Signing Tasks Adding an Info.plist to Single-File Tools 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 153. The value for CFBundleIdentifier is used asthe default unique name of your program for Code Signing purposes. Because the CFBundleIdentifier value is also used when your application accessesresources in the application bundle, it may sometimes be necessary to use a non-unique CFBundleIdentifier value for a helper. If you do this, you must provide a different, unique identifier for code signing purposes by passing the -i or --identifier flag to the codesign command. The identifier used for signing must be globally unique. To ensure uniqueness, you should include your company’s name in the value. The usual form for this identifier is a hierarchical name in reverse DNS notation,starting with the top level domain, followed by the company name, followed by the organization within the company, and ending with the product name. For example, the CFBundleIdentifier value for the codesign command is com.apple.security.codesign. 4. The value for CFBundleName shows up in system dialogs asthe name of your program,so itshould match your marketing name for the product. 5. Add the following arguments to your linker flags: -sectcreate __TEXT __info_plist Info.plist_path where Info.plist_path is the complete path of the Info.plist file in your project. In Xcode, for example, you would add these linker flags to the OTHER_LDFLAGS build variable (Other Linker Flags in the target’s build rules). For example, here are the contents of the Info.plist file for the codesign command: CFBundleDevelopmentRegion English CFBundleIdentifier com.apple.security.codesign CFBundleInfoDictionaryVersion 6.0 CFBundleName codesign CFBundleVersion 0.3 Code Signing Tasks Adding an Info.plist to Single-File Tools 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 16Signing Your Code You use the codesign command to sign your code. This section discusses what to sign and gives some examples of the use of codesign. See the codesign(1) manual page for a complete description of its use. What to Sign You should sign every executable in your product, including applications, tools, hidden helper tools, utilities and so forth. Signing an application bundle covers its resources, but not its subcomponents such as tools and sub-bundles. Each of these must be signed independently. If your application consists of a big UI part with one or more little helper tools that try to present a single face to the user, you can make them indistinguishable to code signing by giving them all the exact same code signing identifier. (You can do that by making sure that they all have the same CFBundleIdentifier value in their Info.plist, or by using the -i option in the codesign command, to assign the same identifier.) In that case, all your program components have access to the same keychain items and validate as the same program. Do this only if the programs involved are truly meant to form a single entity, with no distinctions made. A universal binary (bundle or tool) automatically has individual signatures applied to each architecture component. These are independent, and usually only the native architecture on the end user'ssystem is verified. In the case of installer packages (.pkg and .mpkg bundles), everything is implicitly signed: The CPIO archive containing the payload, the CPIO archive containing install scripts, and the bill of materials (BOM) each have a hash recorded in the XAR header, and that header in turn is signed. Therefore, if you modify an install script (for example) after the package has been signed, the signature will be invalid. You may also want to sign your plug-ins and libraries. Although this is not currently required, it will be in the future, and there is no disadvantage to having signatures on these components. Important: When code signing a framework, you must sign a particular version of the framework, not the framework as a whole. For example: codesign -s my-signing-identity ../MyCustomFramework/Versions/A Depending on the situation, codesign may add to your Mach-O executable file, add extended attributes to it, or create new files in your bundle's Contents directory. None of your other files is modified. Code Signing Tasks Signing Your Code 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 17When to Sign You can run codesign at any time on any system running OS X v10.5 or later, provided you have access to the signing identity. You can run it from a shell script phase in Xcode if you like, or as a step in your Makefile scripts, or anywhere else you find suitable. Signing is typically done as part of the product mastering process, after quality assurance work has been done. Avoid signing pre-final copies of your product so that no one can mistake a leaked or accidentally released incomplete version of your product for the real thing. Your final signing must be done after you are done building your product, including any post-processing and assembly of bundle resources. Code signing detects any change to your program after signing, so if you make any changes at all after signing, your code will be rejected when an attempt is made to verify it. Sign your code before you package the product for delivery. Because each architecture component is signed independently, it is all right to perform universal-binary operations (such as running the lipo command) on signed programs. The result will still be validly signed as long as you make no other changes. Using the codesign Command The codesign command is fully described in the codesign(1) manual page. This section provides some examples of common uses of the command. Note that your signing identity must be in a keychain for these commands to work. Signing Code To sign the code located at , using the signing identity , use the following command: codesign -s … The value may be a bundle folder or a specific code binary. See “What to Sign” (page 17) for more details. The identity can be named with any (case sensitive) substring of the certificate's common name attribute, as long as the substring is unique throughout your keychains. (Signing identities are discussed in “Obtaining a Signing Identity” (page 11).) As is typical of Unix-style commands, this command gives no confirmation of success. To get some feedback, include the -v option: codesign -s -v … Code Signing Tasks Signing Your Code 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 18Use the -r option to specify an internal requirement. With this option you can specify a text file containing the requirements, a precompiled requirements binary, or the actual requirement text prefixed with an equal sign (=). For example, to add an internal requirement that all libraries be signed by Apple, you could use the following option: -r="library => anchor apple" The code requirement language is described in “Code Signing Requirement Language” (page 25). If you have built your own certificate hierarchy (perhaps using Certificate Assistant—see “Obtaining a Signing Identity” (page 11)), and want to use your certificate’s anchor to form a designated requirement for your program, you could use the following command: codesign -s signing-identity -r="designated => anchor /my/anchor/cert and identifier com.mycorp.myprog" Note that the requirement source language accepts either an SHA1 hash of a certificate (for example H"abcd....") or a path to the DER encoded certificate in a file. It does not currently accept a reference to the certificate in a keychain, so you have to export the certificate before executing this command. You can also use the csreq command to write the requirements out to a file, and then use the path to that file as the input value for the -r option in the codesign command. See the manual page for csreq(1) for more information on that command. Here are some other samples of requirements: ● anchor apple –the code is signed by Apple ● anchor trusted –the anchor is trusted (for code signing) by the system ● certificate leaf = /path/to/certificate –the leaf (signing) certificate is the one specified ● certificate leaf = /path/to/certificate and identifier "com.mycorp.myprog" –the leaf certificate and program identifier are as specified ● info[mykey] = myvalue – the Info.plist key mykey exists and has the value myvalue Except for the explicit anchor trusted requirement, the system does not consult its trust settings database when verifying a code requirement. Therefore, as long as you don’t add this designated requirement to your code signature, the anchor certificate you use for signing your code does not have to be introduced to the user’s system for validation to succeed. Code Signing Tasks Signing Your Code 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 19Adding Entitlements for Sandboxing If you want to enable App Sandbox for an application, you must add an entitlement property list during the signing process. To do this, add the --entitlements flag and an appropriate property list. For example: codesign --entitlements /path/to/entitlements.plist -s … For a list of entitlement keys that can appear in the entitlement property list, see Entitlement Key Reference . Verifying Code To verify the signature on a signed binary, use the -v option with no other options: codesign -v … This checks that the code binaries at are actually signed, that the signature is valid, that all the sealed components are unaltered, and that the whole thing passes some basic consistency checks. It does not by default check that the code satisfies any requirements except its own designated requirement. To check a particular requirement, use the -R option. For example, to check that the Apple Mail application is identified as Mail,signed by Apple, and secured with Apple’srootsigning certificate, you could use the following command: codesign -v -R="identifier com.apple.mail and anchor apple" /Applications/Mail.app Note that, unlike the -r option, the -R option takes only a single requirement rather than a requirements collection (no => tags). Add one or more additional -v options to get details on the validation process. If you pass a number rather than a path to the verify option, codesign takes the number to be the process ID (pid) of a running process, and performs dynamic validation instead. Getting Information About Code Signatures To get information about a code signature, use the -d option. For example, to output the code signature’s internal requirements to standard out, use the following command: codesign -d -r code-path Note that this option does not verify the signature. Code Signing Tasks Signing Your Code 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 20Using the spctl Tool to Test Code Signing The spctl(8) tool can be used to test your code signatures against various system policies that the user may set. The basic syntax for code signing assessment is shown below: # Assess an application or tool spctl --assess --type execute myTool # Assess an installer package spctl --assess --type install myInstallerPackage.pkg If your application or package signature is valid, these tools exit silently with an exit status of 0. (Type echo $? to display the exit status of the last command.) If the signature is invalid, these tools print an error message and exit with a nonzero exit status. For more detailed information about why the assessment failed, you can add the --verbose flag. For example: spctl --assess --verbose=4 /bin/ls This prints the following output: /bin/ls: accepted source=Apple System To see everything the system has to say about an assessment, pass the --raw option. With this flag, the spctl tool prints a detailed assessment as a property list. To whitelist a program (exactly as if the UI did it), type: spctl --add --label mytest /some/program The --label is an optional tag that you can add to your own rules. This tag allows you to remove the rule easily by typing: spctl --remove --label mytest Note that this removes all rules that match the label, which means that it is a handy way to clean up after testing. You can also temporarily suspend your rules by typing: Code Signing Tasks Using the spctl Tool to Test Code Signing 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 21spctl --disable --label mytest and reenable them later by typing: spctl --enable --label mytest To see a list of the current assessment rules, use the --list flag. For example: spctl --list --type execute The resulting list of rules might look like this: 3[Apple System] P0 allow execute anchor apple 4[Mac App Store] P0 allow execute anchor apple generic and certificate leaf[field.1.2.840.113635.100.6.1.9] exists 5[Developer ID] P0 allow execute anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and certificate leaf[field.1.2.840.113635.100.6.1.13] exists 7[UNLABELED] P0 allow execute [/var/tmp/firefly/RUN-FIREFLY-JOBS/test1.app] cdhash H"f34c03450da53c07ac69282089b68723327f278a" 8[UNLABELED] P0 allow execute [/var/tmp/firefly/RUN-FIREFLY-JOBS/test1.app] identifier "org.tpatko.Run-Firefly-Job-X-Cores" and certificate root = H"5056a3983e3b7f44e17e3db8e483b35b6745b236" Notice that the list above includes a number of predefined rules that describe the handling of certain classes of code. For example, rule 5 captures all applicationssigned by a Developer ID. You can disable those applications by typing: spctl --disable --label "Developer ID" This command tells the system to no longer allow execution of any Developer ID-signed applications that the user has not previously run. This is exactly what happens when you use the preference UI to switch to "Mac App Store only". Each rule in the list has a unique number that can be used to address it. For example, if you type: Code Signing Tasks Using the spctl Tool to Test Code Signing 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 22spctl --list --label "Developer ID" you might get a list of rules that looks like this: 5[Developer ID] P0 allow execute anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and certificate leaf[field.1.2.840.113635.100.6.1.13] exists 6[Developer ID] P0 allow install anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and certificate leaf[field.1.2.840.113635.100.6.1.14] exists Notice that there are separate rules for execution (5) and installation (6), and you can enable and disable them separately. For example, to enable installation of new applications signed with a Developer ID, you can type: spctl --enable --rule 6 Finally, spctl allows you to enable or disable the security assessment policy subsystem. By default, assessment isturned off, which meansthat missing or invalid code signatures do not prevent an application from launching. However, it is strongly recommended that you test your application with assessment enabled to ensure that your application works correctly. To enable or disable assessment, issue one of the following commands. sudo spctl --master-enable # enables assessment sudo spctl --master-disable # disables assessment spctl --status # shows whether assessment is enabled For more information, see the manual page for spctl(8). Shipping and Updating Your Product The only thing that matters to the code signing system is that the signed code installed on the user’s system identical to the code that you signed. It does not matter how you package, deliver, or install your product as long as you don’t introduce any changesinto the product. Compression, encoding, encrypting, and even binary patching the code are all right as long as you end up with exactly what you started with. You can use any installer you like, as long as it doesn't write anything into the product as it installs it. Drag-installs are fine as well. Code Signing Tasks Shipping and Updating Your Product 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 23When you have qualified a new version of your product, sign it just as you signed the previous version, with the same identifier and the same designated requirement. The user’s system will consider the new version of your product to be the same program as the previous version. In particular, the keychain will not distinguish older and newer versions of your program aslong as both were signed and the unique Identifier hasn't changed. You can take a partial-update approach to revising your code on the user’s system. To do so, sign the new version as usual, then calculate the differences between the new and the old signed versions, and transmit the differences. Because the differences include the new signature data, the result of installing the changes on the end-user's system will be the newly signed version. You cannot patch a signed application in the field. If you do so, the system will notice that the application has changed and will invalidate the signature, and there is no way to re-validate or resign the application in the field. Code Signing Tasks Shipping and Updating Your Product 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 24When you use the codesign command to sign a block of code, you can specify internal requirements; that is, the criteria that you recommend should be used to evaluate the code signature. It is up to the verifier to decide whether to apply the internal requirements or some other set of requirements when deciding how to treat the signed code. You use the code requirement language described in this chapter when specifying requirementsto the codesign or csreq command (see the manual pagesfor codesign(1) and csreq(1)). This chapter describes the requirement language source code. You can compile a set of requirements and save them in binary form using the csreq command. You can provide requirements to the codesign command either as source code or as a binary file. Both the codesign and csreq commands can convert a binary requirement set to text. Although there is some flexibility in the source code syntax (for example, quotes can always be used around string constants but are not always required), conversion from binary to text always uses the same form: ● Parentheses are placed (usually only) where required to clarify operator precedence. ● String constants are quoted (usually only) where needed. ● Whether originally specified as constants or through file paths, certificate hashes are always returned as hash constants. ● Comments in the original source are not preserved in the reconstructed text. Language Syntax Some basic features of the language syntax are: ● Expressions use conventional infix notation (that is, the operator is placed between the two entities being acted on; for example quantity < constant). ● Keywords are reserved, but can be quoted to be included as part of ordinary strings. ● Comments are allowed in C, Objective C, and C++. ● Unquoted whitespace is allowed between tokens, but strings containing whitespace must be quoted. ● Line endings have no special meaning and are treated as whitespace. 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 25 Code Signing Requirement LanguageEvaluation of Requirements A requirement constitutes an expression without side effects. Each requirement can have any number of subexpressions, each of which is evaluated with a Boolean (succeed-fail) result. There is no defined order of evaluation. The subexpressions are combined using logical operators in the expression to yield an overall Boolean result for the expression. Depending on the operators used, an expression can succeed even if some subexpressions fail. For example, the expression anchor apple or anchor = "/var/db/yourcorporateanchor.cert" succeeds if either subexpression succeeds—that is, if the code was signed either by Apple or by your company—even though one of the subexpressions is sure to fail. If an error occurs during evaluation, on the other hand, evaluation stops immediately and the codesign or csreq command returns with a result code indicating the reason for failure. Constants Thissection describesthe use ofstring, integer, hash-value, and binary constantsin the code signing requirement language. String Constants String constants must be enclosed by double quotes (" ") unless the string contains only letters, digits, and periods (.), in which case the quotes are optional. Absolute file paths, which start with a slash, do not require quotes unless they contain spaces. For example: com.apple.mail //no quotes are required "com.apple.mail" //quotes are optional "My Company's signing identity" //requires quotes for spaces and apostrophe /Volumes/myCA/root.crt //no quotes are required "/Volumes/my CA/root.crt" //space requires quotes "/Volumes/my_CA/root.crt" //underscore requires quotes It’s never incorrect to enclose the string in quotes—if in doubt, use quotes. Use a backslash to “escape” any character. For example: Code Signing Requirement Language Evaluation of Requirements 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 26"one \" embedded quote" //one " embedded quote "one \\ embedded backslash" //one \ embedded backslash There is nothing special about the single quote character ('). Integer Constants Integer constants are written as decimal constants are in C. The language does not allow radix prefixes (such as 0x) or leading plus or minus (+ or -) signs. Hash Constants Hash values are written either as a hexadecimal number in quotes preceded by an H, or as a path to a file containing a binary certificate. If you use the first form, the number must include the exact number of digits in the hash value. A SHA-1 hash (the only kind currently supported) requires exactly 40 digits; for example: H"0123456789ABCDEFFEDCBA98765432100A2BC5DA" You can use either uppercase or lowercase letters (A..F or a..f) in the hexadecimal numbers. If you specify a file path, the compiler readsthe binary certificate and calculatesthe hash for you. The compiled version of the requirement code includes only the hash; the certificate file and the path are not retained. If you convert the requirement back to text, you get the hexadecimal hash constant. The file path must point to a file containing an X.509 DER encoded certificate. No container forms (PKCS7, PKCS12) are allowed, nor is the OpenSSL "PEM" form supported. Variables There are currently no variables in the requirement language. Logical Operators The requirement language includes the following logical operators, in order of decreasing precedence: ● ! (negation) ● and (logical AND) ● or (logical OR) Code Signing Requirement Language Variables 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 27These operators can be used to combine subexpressionsinto more complex expressions. The negation operator (!) is a unary prefix operator. The others are infix operators. Parentheses can be used to override the precedence of the operators. Because the language is free of side effects, evaluation order of subexpressions is unspecified. Comparison Operations The requirement language includes the following comparison operators: ● = (equals) ● < (less than) ● > (greater than) ● <= (less than or equal to) ● >= (greater than or equal to) ● exists (value is present) The value-present (exists) operator is a unary suffix operator. The others are infix operators. There are no operators for non-matches (not equal to, not greater than, and so on). Use the negation operator (!) together with the comparison operators to make non-match comparisons. Equality All equality operations compare some value to a constant. The value and constant must be of the same type: a string matches a string constant, a data value matches a hexadecimal constant. The equality operation evaluates to true if the value exists and is equal to the constant. String matching uses the same matching rules as CFString (see CFString Reference ). In match expressions (see “Info” (page 30), “Part of a Certificate” (page 31), and “Entitlement” (page 33)), substrings of string constants can be matched by using the * wildcard character: ● value = *constant* is true if the value exists and any substring of the value matches the constant; for example: ● thunderbolt = *under* ● thunderbolt = *thunder* ● thunderbolt = *bolt* ● value = constant* is true if the value exists and begins with the constant; for example: Code Signing Requirement Language Comparison Operations 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 28● thunderbolt = thunder* ● thunderbolt = thun* ● value = *constant is true if the value exists and ends with the constant; for example: ● thunderbolt = *bolt ● thunderbolt = *underbolt If the constant is written with quotation marks, the asterisks must be outside the quotes. An asterisk inside the quotation marks is taken literally. For example: ● "ten thunderbolts" = "ten thunder"* is true ● "ten thunder*bolts" = "ten thunder*"* is true ● "ten thunderbolts" = "ten thunder*" is false Inequality Inequality operations compare some value to a constant. The value and constant must be of the same type: a string matches a string constant, a data value matches a hexadecimal constant. String comparisons use the same matching rules as CFString with the kCFCompareNumerically option flag; for example, "17.4" is greater than "7.4". Existence The existence operator tests whether the value exists. It evaluates to false only if the value does not exist at all or is exactly the Boolean value false. An empty string and the number 0 are considered to exist. Constraints Several keywords in the requirement language are used to require that specific certificates be present or other conditions be met. Identifier The expression identifier = constant succeedsif the unique identifierstring embedded in the code signature is exactly equal to constant. The equal sign is optional in identifier expressions. Signing identifiers can be tested only for exact equality; the wildcard character (*) can not be used with the identifier constraint, nor can identifiers be tested for inequality. Code Signing Requirement Language Constraints 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 29Info The expression info [key]match expression succeedsif the value associated with the top-level key in the code’s info.plist file matches match expression , where match expression can include any of the operators listed in “Logical Operators” (page 27) and “Comparison Operations” (page 28). For example: info [CFBundleShortVersionString] < "17.4" or info [MySpecialMarker] exists You must specify key as a string constant. If the value of the specified key is a string, the match is applied to it directly. If the value is an array, it must be an array of strings and the match is made to each in turn, succeeding if any of them matches. Substrings of string constants can be matched by using any match expression (see “Comparison Operations” (page 28)). If the code has no info.plist file, or the info.plist does not contain the specified key, this expression evaluates to false without returning an error. Certificate Certificate constraints refer to certificates in the certificate chain used to validate the signature. Most uses of the certificate keyword accept an integer that indicatesthe position of the certificate in the chain: positive integers count from the leaf (0) toward the anchor. Negative integers count backward from the anchor (-1). For example, certificate 1 is the intermediate certificate that was used to sign the leaf (that is, the signing certificate), and certificate -2 indicates the certificate that was directly signed by the anchor. Note that this convention is the same as that used for array indexing in the Perl and Ruby programming languages: Anchor First intermediate Second intermediate Leaf certificate 3 certificate 2 certificate 1 certificate 0 certificate -1 certificate -2 certificate -3 certificate -4 Other keywords include: Code Signing Requirement Language Constraints 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 30● certificate root—the anchor certificate; same as certificate 0 ● anchor—same as certificate root ● certificate leaf—the signing certificate; same as certificate -1 Note: The short form cert is allowed for the keyword certificate. If there is no certificate at the specified position, the constraint evaluates to false without returning an error. If the code was signed using an ad-hoc signature, there are no certificates at all and all certificate constraints evaluate to false. (An ad-hoc signature is created by signing with the pseudo-identity - (a dash). An ad-hoc signature does not use or record a cryptographic identity, and thusidentifies exactly and only the one program being signed.) If the code was signed by a self-signed certificate, then the leaf and root refer to the same single certificate. Whole Certificate To require a particular certificate to be present in the certificate chain, use the form certificate position = hash or one of the equivalent forms discussed above, such as anchor = hash . Hash constants are described in “Hash Constants” (page 27). For Apple’s own code, signed by Apple, you can use the short form anchor apple For code signed by Apple, including code signed using a signing certificate issued by Apple to other developers, use the form anchor apple generic Part of a Certificate To match a well-defined element of a certificate, use the form certificate position[element]match expression where match expression can include the * wildcard character and any of the operators listed in “Logical Operators” (page 27) and “Comparison Operations” (page 28). The currently supported elements are asfollows: Code Signing Requirement Language Constraints 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 31Note: Case is significant in element names. Element name Meaning Comments subject.CN Subject common name Shown in Keychain Access utility subject.C Subject country name subject.D Subject description subject.L Subject locality subject.O Subject organization Usually company or organization subject.OU Subject organizational unit subject.STREET Subject street address Certificate field by OID To check for the existence of any certificate field identified by its X.509 object identifier (OID), use the form certificate position [field.OID] exists The object identifier must be written in numeric form (x.y.z ...) and can be the OID of a certificate extension or of a conventional element of a certificate as defined by the CSSM standard (see Chapter 31 in Common Security: CDSA and CSSM, version 2 (with corrigenda) by the Open Group (http://www.opengroup.org/security/cdsa.htm)). Trusted The expression certificate position trusted succeeds if the certificate specified by position is marked trusted for the code signing certificate policy in the system’s Trust Settings database. The position argument is an integer or keyword that indicates the position of the certificate in the chain; see the discussion under “Certificate” (page 30). The expression anchor trusted Code Signing Requirement Language Constraints 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 32succeeds if any certificate in the signature’s certificate chain is marked trusted for the code signing certificate policy in the system’s Trust Settings database, provided that no certificate closer to the leaf certificate is explicitly untrusted. Thus, using the trusted keyword with a certificate position checks only the specified certificate, while using it with the anchor keyword checks all the certificates, giving precedence to the trust setting found closest to the leaf. Important: The syntax anchor trusted is not a synonym for certificate anchor trusted. Whereas the former checks all certificates in the signature, the latter checks only the anchor certificate. Certificates can have per-user trust settings and system-wide trust settings, and trust settings apply to specific policies. The trusted keyword in the code signing requirement language causes trust to be checked for the specified certificate or certificates for the user performing the validation. If there are no settings for that user, then the system settings are used. In all cases, only the trust settings for the code-signing policy are checked. Policies and trust are discussed in Certificate, Key, and Trust Services Programming Guide . Important: If you do not include an expression using the trusted keyword in your code signing requirement, then the verifier does not check the trust status of the certificates in the code signature at all. Entitlement The expression entitlement [key] match expression succeeds if the value associated with the specified key in the signature’s embedded entitlement dictionary matches match expression , where match expression can include the * wildcard character and any of the operators listed in “Logical Operators” (page 27) and “Comparison Operations” (page 28). You must specify key as a string constant. The entitlement dictionary is included in signatures for certain platforms. Code Directory Hash The expression cdhash hash-constant computes a SHA-1 hash of the program’s CodeDirectory resource and succeeds if the value of this hash exactly equals the specified hash constant. Code Signing Requirement Language Constraints 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 33The CodeDirectory resource is the master directory of the contents of the program. It consists of a versioned header followed by an array of hashes. This array consists of a set of optionalspecial hashesfor other resources, plus a vector of hashes for pages of the main executable. The CodeSignature and CodeDirectory resources together make up the signature of the code. You can use the codesign utility with (at least) three levels of verbosity to obtain the hash constant of a program’s CodeDirectory resource: $ codesign -dvvv /bin/ls ... CodeDirectory v=20001 size=257 flags=0x0(none) hashes=8+2 location=embedded CDHash=4bccbc576205de37914a3023cae7e737a0b6a802 ... Because the code directory changes whenever the program changes in a nontrivial way, this test can be used to unambiguously identify one specific version of a program. When the operating system signs an otherwise unsigned program (so that the keychain or Parental Controls can recognize the program, for example), it uses this requirement. Requirement Sets A requirementset is a collection of distinct requirements, each indexed (tagged) with a type code. The expression tag => requirement applies requirement to the type of code indicated by tag , where possible tags are ● host—thisrequirement is applied to the direct host of this code module; each code module in the hosting path can have its own host requirement, where the hosting path isthe chain of code signing hostsstarting with the most specific code known to be running, and ending with the root of trust (the kernel) ● guest—this requirement is applied to each code module that is hosted by this code module ● library—this requirement is applied to all libraries mounted by the signed code ● designated—this is an explicitly specified designated requirement for the signed code; if there is no explicitly specified designated requirement for the code, then there is no designated internal requirement The primary use of requirement sets is to represent the internal requirements of the signed code. For example: Code Signing Requirement Language Requirement Sets 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 34codesign -r='host => anchor apple and identifier com.apple.perl designated => anchor /my/root and identifier com.bar.foo' setsthe internal requirements ofsome code, having a host requirement of anchor apple and identifier com.apple.perl (“I'm a Perlscript and I want to be run by Apple's Perl interpreter”) and an explicit designated requirement of anchor /my/root and identifier com.bar.foo. Note that this command sets no guest or library requirements. You can also put the requirement set in a file and point to the file: codesign -r myrequirements.rqset where the file myrequirements.rqset might contain: //internal requirements host => anchor apple and identifier com.apple.perl //require Apple's Perl interpreter designated => anchor /my/root and identifier com.bar.foo Code Signing Requirement Language Requirement Sets 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 35This table describes the changes to Code Signing Guide . Date Notes 2012-07-23 Added information about new spctl features in OS X v10.8. Added information about Developer IDs and explanation of how to code sign a framework. 2012-05-15 2011-09-28 Revised document to focus exclusively on code signing. Some of the content in this document was previously in Code Signing and Application Sandboxing Guide . 2011-07-11 Added information about application sandboxing. 2009-10-19 Fixed typographical errors. 2009-10-13 Clarified explanation of CFBundleIdentifier and uniqueness. 2008-11-19 Added a chapter describing the code signing requirement language. New document that explains why you should sign your code and provides code signing procedures. 2007-05-15 2012-07-23 | © 2012 Apple Inc. All Rights Reserved. 36 Document Revision HistoryApple Inc. © 2012 Apple Inc. All rights reserved. No part of this publication may be reproduced, stored in a retrievalsystem, or transmitted, in any form or by any means, mechanical, electronic, photocopying, recording, or otherwise, without prior written permission of Apple Inc., with the following exceptions: Any person is hereby authorized to store documentation on a single computer for personal use only and to print copies of documentation for personal use provided that the documentation contains Apple’s copyright notice. No licenses, express or implied, are granted with respect to any of the technology described in this document. Apple retains all intellectual property rights associated with the technology described in this document. This document is intended to assist application developers to develop applications only for Apple-labeled computers. Apple Inc. 1 Infinite Loop Cupertino, CA 95014 408-996-1010 Apple, the Apple logo, Keychain, Logic, Mac, OS X, Safari, Sand, and Xcode are trademarks of Apple Inc., registered in the U.S. and other countries. App Store and Mac App Store are service marks of Apple Inc. Even though Apple has reviewed this document, APPLE MAKES NO WARRANTY OR REPRESENTATION, EITHER EXPRESS OR IMPLIED, WITH RESPECT TO THIS DOCUMENT, ITS QUALITY, ACCURACY, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.ASARESULT, THISDOCUMENT IS PROVIDED “AS IS,” AND YOU, THE READER, ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND ACCURACY. IN NO EVENT WILL APPLE BE LIABLE FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL,OR CONSEQUENTIAL DAMAGES RESULTING FROM ANY DEFECT OR INACCURACY IN THIS DOCUMENT, even if advised of the possibility of such damages. THE WARRANTY AND REMEDIES SET FORTH ABOVE ARE EXCLUSIVE AND IN LIEU OF ALL OTHERS, ORAL OR WRITTEN, EXPRESS OR IMPLIED. No Apple dealer, agent, or employee is authorized to make any modification, extension, or addition to this warranty. Some states do not allow the exclusion or limitation of implied warranties or liability for incidental or consequential damages, so the above limitation or exclusion may not apply to you. This warranty gives you specific legal rights, and you may also have other rights which vary from state to state. View Controller Programming Guide for iOSContents About View Controllers 9 At a Glance 10 A View Controller Manages a Set of Views 10 You Manage Your Content Using Content View Controllers 10 Container View Controllers Manage Other View Controllers 10 Presenting a View Controller Temporarily Brings Its View Onscreen 11 Storyboards Link User Interface Elements into an App Interface 11 How to Use This Document 12 Prerequisites 12 See Also 12 View Controller Basics 14 Screens, Windows, and Views Create Visual Interfaces 15 View Controllers Manage Views 17 A Taxonomy of View Controllers 19 Content View Controllers Display Content 19 Container View Controllers Arrange Content of Other View Controllers 21 A View Controller’s Content Can Be Displayed in Many Ways 26 View Controllers Work Together to Create an App’s Interface 28 Parent-Child Relationships Represent Containment 29 Sibling Relationships Represent Peers Inside a Container 29 Presentation Represents a Transient Display of Another Interface 30 Control Flow Represents Overall Coordination Between Content Controllers 31 Storyboards Help You Design Your User Interface 33 Using View Controllers in Your App 35 Working with View Controllers in Storyboards 36 The Main Storyboard Initializes Your App’s User Interface 37 Segues Automatically Instantiate the Destination View Controller 37 Instantiating a Storyboard’s View Controller Programmatically 39 Containers Automatically Instantiate Their Children 41 Instantiating a Non-Storyboard View Controller 41 Displaying a View Controller’s Contents Programmatically 41 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 2Creating Custom Content View Controllers 43 Anatomy of a Content View Controller 43 View Controllers Manage Resources 44 View Controllers Manage Views 45 View Controllers Respond to Events 45 View Controllers Coordinate with Other Controllers 45 View Controllers Often Work with Containers 46 View Controllers May Be Presented by Other View Controllers 46 Designing Your Content View Controller 47 Use a Storyboard to Implement Your View Controller 48 Know When Your Controller Is Instantiated 48 Know What Data Your View Controller Shows and Returns 48 Know What Tasks Your Controller Allows the User to Perform 49 Know How Your View Controller Is Displayed Onscreen 50 Know How Your Controller Collaborates with Other Controllers 50 Examples of Common View Controller Designs 50 Example: Game Title Screen 50 Example: Master View Controller 52 Example: Detail View Controller 53 Example: Mail Compose View Controller 54 Implementation Checklist for Custom Content View Controllers 54 Resource Management in View Controllers 56 Initializing a View Controller 56 Initializing a View Controller Loaded from a Storyboard 56 Initializing View Controllers Programmatically 57 A View Controller Instantiates Its View Hierarchy When Its View is Accessed 57 Loading a View Controller’s View from a Storyboard 59 Creating a View Programmatically 60 Managing Memory Efficiently 61 On iOS 6 and Later, a View Controller Unloads Its Own Views When Desired 63 On iOS 5 and Earlier, the System May Unload Views When Memory Is Low 64 Responding to Display-Related Notifications 66 Responding When a View Appears 66 Responding When a View Disappears 67 Determining Why a View’s Appearance Changed 67 Resizing the View Controller’s Views 69 A Window Sets the Frame of Its Root View Controller’s View 69 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 3 ContentsA Container Sets the Frames of Its Children’s Views 70 A Presented View Controller Uses a Presentation Context 70 A Popover Controller Sets the Size of the Displayed View 70 How View Controllers Participate in the View Layout Process 70 Using View Controllers in the Responder Chain 72 The Responder Chain Defines How Events Are Propagated to the App 72 Supporting Multiple Interface Orientations 74 Controlling What Interface Orientations Are Supported (iOS 6) 75 Declaring a View Controller’s Supported Interface Orientations 75 Dynamically Controlling Whether Rotation Occurs 76 Declaring a Preferred Presentation Orientation 76 Declaring the App’s Supported Interface Orientations 76 Understanding the Rotation Process (iOS 5 and earlier) 77 Declaring the Supported Interface Orientations 77 Responding to Orientation Changes in a Visible View Controller 78 Rotations May Occur When Your View Controller Is Hidden 80 Creating an Alternate Landscape Interface 80 Tips for Implementing Your Rotation Code 82 Accessibility from the View Controller’s Perspective 83 Moving the VoiceOver Cursor to a Specific Element 83 Responding to Special VoiceOver Gestures 84 Escape 85 Magic Tap 85 Three-Finger Scroll 85 Increment and Decrement 86 Observing Accessibility Notifications 86 Presenting View Controllers from Other View Controllers 88 How View Controllers Present Other View Controllers 88 Presentation Styles for Modal Views 91 Presenting a View Controller and Choosing a Transition Style 93 Presentation Contexts Provide the Area Covered by the Presented View Controller 95 Dismissing a Presented View Controller 95 Presenting Standard System View Controllers 96 Coordinating Efforts Between View Controllers 98 When Coordination Between View Controllers Occurs 98 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 4 ContentsWith Storyboards, a View Controller is Configured When It Is Instantiated 99 Configuring the Initial View Controller at Launch 100 Configuring the Destination Controller When a Segue is Triggered 101 Using Delegation to Communicate with Other Controllers 103 Guidelines for Managing View Controller Data 105 Enabling Edit Mode in a View Controller 106 Toggling Between Display and Edit Mode 106 Presenting Editing Options to the User 108 Creating Custom Segues 109 The Life Cycle of a Segue 109 Implementing a Custom Segue 109 Creating Custom Container View Controllers 111 Designing Your Container View Controller 111 Examples of Common Container Designs 113 A Navigation Controller Manages a Stack of Child View Controllers 113 A Tab Bar Controller Uses a Collection of Child Controllers 115 A Page Controller Uses a Data Source to Provide New Children 116 Implementing a Custom Container View Controller 116 Adding and Removing a Child 116 Customizing Appearance and Rotation Callback Behavior 119 Practical Suggestions for Building a Container View Controller 120 Document Revision History 122 Glossary 124 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 5 ContentsFigures, Tables, and Listings View Controller Basics 14 Figure 1-1 A window with its target screen and content views 15 Figure 1-2 Classes in the view system 16 Figure 1-3 A view controller attached to a window automatically adds its view as a subview of the window 17 Figure 1-4 Distinct views managed by separate view controllers 18 Figure 1-5 View controller classes in UIKit 19 Figure 1-6 Managing tabular data 21 Figure 1-7 Navigating hierarchical data 23 Figure 1-8 Different modes of the Clock app 24 Figure 1-9 A master-detail interface in portrait and landscape modes 25 Figure 1-10 Presenting a view controller 27 Figure 1-11 Parent-child relationships 29 Figure 1-12 Sibling relationships in a navigation controller 30 Figure 1-13 Modal presentation by a content view 30 Figure 1-14 The actual presentation is performed by the root view controller. 31 Figure 1-15 Communication between source and destination view controllers 32 Figure 1-16 A storyboard diagram in Interface Builder 33 Using View Controllers in Your App 35 Figure 2-1 A storyboard holds a set of view controllers and associated objects 36 Listing 2-1 Triggering a segue programmatically 38 Listing 2-2 Instantiating another view controller inside the same storyboard 39 Listing 2-3 Instantiating a view controller from a new storyboard 40 Listing 2-4 Installing the view controller as a window’s root view controller 42 Creating Custom Content View Controllers 43 Figure 3-1 Anatomy of a content view controller 44 Figure 3-2 A container view controller imposes additional demands on its children 46 Resource Management in View Controllers 56 Figure 4-1 Loading a view into memory 58 Figure 4-2 Connections in the storyboard 60 Figure 4-3 Unloading a view from memory 65 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 6Table 4-1 Places to allocate and deallocate memory 62 Listing 4-1 Custom view controller class declaration 59 Listing 4-2 Creating views programmatically 61 Listing 4-3 Releasing the views of a view controller not visible on screen 63 Responding to Display-Related Notifications 66 Figure 5-1 Responding to the appearance of a view 66 Figure 5-2 Responding to the disappearance of a view 67 Table 5-1 Methods to call to determine why a view’s appearance changed 68 Using View Controllers in the Responder Chain 72 Figure 7-1 Responder chain for view controllers 73 Supporting Multiple Interface Orientations 74 Figure 8-1 Processing an interface rotation 79 Listing 8-1 Implementing the supportedInterfaceOrientations method 75 Listing 8-2 Implementing the preferredInterfaceOrientationForPresentation method 76 Listing 8-3 Implementing the shouldAutorotateToInterfaceOrientation: method 78 Listing 8-4 Presenting the landscape view controller 81 Accessibility from the View Controller’s Perspective 83 Listing 9-1 Posting an accessibility notification can change the first element read aloud 84 Listing 9-2 Registering as an observer for accessibility notifications 86 Presenting View Controllers from Other View Controllers 88 Figure 10-1 Presented views in the Calendar app. 89 Figure 10-2 Creating a chain of modal view controllers 90 Figure 10-3 Presenting navigation controllers modally 91 Figure 10-4 iPad presentation styles 92 Table 10-1 Transition styles for modal view controllers 93 Table 10-2 Standard system view controllers 96 Listing 10-1 Presenting a view controller programmatically 94 Coordinating Efforts Between View Controllers 98 Listing 11-1 The app delegate configures the controller 100 Listing 11-2 Creating the window when a main storyboard is not being used 101 Listing 11-3 Configuring the destination controller in a segue 102 Listing 11-4 Delegate protocol for dismissing a presented view controller 104 Listing 11-5 Dismissing a presented view controller using a delegate 104 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 7 Figures, Tables, and ListingsEnabling Edit Mode in a View Controller 106 Figure 12-1 Display and edit modes of a view 107 Creating Custom Segues 109 Listing 13-1 A custom segue 110 Creating Custom Container View Controllers 111 Figure 14-1 A container view controller’s view hierarchy contains another controller’s views 112 Figure 14-2 A navigation controller’s view and view controller hierarchy 114 Figure 14-3 A tab bar controller’s view and view controller hierarchy 115 Listing 14-1 Adding another view controller’s view to the container’s view hierarchy 117 Listing 14-2 Removing another view controller’s view to the container’s view hierarchy 117 Listing 14-3 Transitioning between two view controllers 118 Listing 14-4 Disabling automatic appearance forwarding 119 Listing 14-5 Forwarding appearance messages when the container appears or disappears 119 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 8 Figures, Tables, and ListingsView controllers are a vital link between an app’s data and its visual appearance. Whenever an iOS app displays a user interface, the displayed content is managed by a view controller or a group of view controllers coordinating with each other. Therefore, view controllers provide the skeletal framework on which you build your apps. iOS provides many built-in view controller classesto supportstandard user interface pieces,such as navigation and tab bars. As part of developing an app, you also implement one or more custom controllers to display the content specific to your app. 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 9 About View ControllersAt a Glance View controllers are traditional controller objects in the Model-View-Controller (MVC) design pattern, but they also do much more. View controllers provide many behaviors common to all iOS apps. Often, these behaviors are built into the base class. For some behaviors, the base class provides part of the solution and your view controllersubclassimplements custom code to provide the rest. For example, when the user rotatesthe device, the standard implementation attempts to rotate the user interface; however, your subclass decides whether the user interface should be rotated, and, if so, how the configuration of its views should change in the new orientation. Thus, the combination of a structured base class and specific subclassing hooks make it easy for you to customize your app’s behavior while conforming to the platform design guidelines. A View Controller Manages a Set of Views A view controller manages a discrete portion of your app’s user interface. Upon request, it provides a view that can be displayed or interacted with. Often, this view is the root view for a more complex hierarchy of views—buttons, switches, and other user interface elements with existing implementations in iOS. The view controller acts asthe central coordinating agent for this view hierarchy, handling exchanges between the views and any relevant controller or data objects. Relevant chapter: “View Controller Basics” (page 14) You Manage Your Content Using Content View Controllers To present content that is specific to your app, you implement your own content view controllers. You create new view controller classes by subclassing either the UIViewController class or the UITableViewController class, implementing the methods necessary to present and control your content. Relevant chapter: “Creating Custom Content View Controllers” (page 43) Container View Controllers Manage Other View Controllers Container view controllers display content owned by other view controllers. These other view controllers are explicitly associated with the container, forming a parent-child relationship. The combination of container and content view controllers creates a hierarchy of view controller objects with a single root view controller. Each type of container defines its own interface to manage its children. The container’s methods sometimes define specific navigational relationships between the children. A container can also set specific restrictions on the types of view controllers that can be its children. It may also expect the view controllers that are its children to provide additional content used to configure the container. About View Controllers At a Glance 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 10iOS provides many built-in container view controller types you can use to organize your user interface. Relevant chapter: “View Controller Basics” (page 14) Presenting a View Controller Temporarily Brings Its View Onscreen Sometimes a view controller wants to display additional information to the user. Or perhaps it wants the user to provide additional information or perform a task. Screen space is limited on iOS devices; the device might not have enough room to display all the user interface elements at the same time. Instead, an iOS app temporarily displays another view for the user to interact with. The view is displayed only long enough for the user to finish the requested action. To simplify the effort required to implement such interfaces, iOS allows a view controller to present another view controller’s contents. When presented, the new view controller’s views are displayed on a portion of the screen—often the entire screen. Later, when the user completes the task, the presented view controller tells the view controller that presented it that the task is complete. The presenting view controller then dismisses the view controller it presented, restoring the screen to its original state. Presentation behavior must be included in a view controller’s design in order for it to be presented by another view controller. Relevant chapter: “Presenting View Controllers from Other View Controllers” (page 88) Storyboards Link User Interface Elements into an App Interface A user interface design can be very complex. Each view controller references multiple views, gesture recognizers, and other user interface objects. In return, these objects maintain references to the view controller or execute specific pieces of code in response to actions the user takes. And view controllers rarely act in isolation. The collaboration between multiple view controllers also defines other relationships in your app. In short, creating a user interface means instantiating and configuring many objects and establishing the relationships between them, which can be time consuming and error prone. Instead, use Interface Builder to create storyboards. A storyboard holds preconfigured instances of view controllers and their associated objects. Each object’s attributes can be configured in Interface Builder, as can relationships between them. At runtime, your app loads storyboards and uses them to drive your app’s interface. When objects are loaded from the storyboard, they are restored to the state you configured in the storyboard. UIKit also provides methods you can override to customize behaviors that cannot be configured directly in Interface Builder. About View Controllers At a Glance 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 11By using storyboards, you can easily see how the objects in your app’s user interface fit together. You also write less code to create and configure your app’s user-interface objects. Relevant chapter: “View Controller Basics” (page 14), “Using View Controllers in Your App” (page 35) How to Use This Document Start by reading “View Controller Basics” (page 14), which explains how view controllers work to create your app’s interface. Next, read “Using View Controllers in Your App” (page 35) to understand how to use view controllers, both those built into iOS and those you create yourself. When you are ready to implement your app’s custom controllers, read “Creating Custom Content View Controllers” (page 43) for an overview of the tasks your view controller performs, and then read the remaining chapters in this document to learn how to implement those behaviors. Prerequisites Before reading this document, you should be familiar with the content in Start Developing iOS Apps Today and Your Second iOS App: Storyboards. The storyboard tutorial demonstrates many of the techniques described in this book, including the following Cocoa concepts: ● Defining new Objective-C classes ● The role of delegate objects in managing app behaviors ● The Model-View-Controller paradigm See Also For more information about the standard container view controllers provided by UIKit, see View Controller Catalog for iOS . For guidance on how to manipulate views in your view controller, see View Programming Guide for iOS . For guidance on how to handle events in your view controller, see Event Handling Guide for iOS . For more information about the overall structure of an iOS app, see iOS App Programming Guide . About View Controllers How to Use This Document 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 12For guidance on how to configure storyboards in your project, see Xcode 4 User Guide About View Controllers See Also 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 13Appsrunning on iOS–based devices have a limited amount ofscreen space for displaying content and therefore must be creative in how they present information to the user. Apps that have lots of information to display must therefore only show a portion to start, and then show and hide additional content as the user interacts with the app. View controller objects provide the infrastructure for managing content and for coordinating the showing and hiding of it. By having different view controller classes control separate portions of your user interface, you break up the implementation of your user interface into smaller and more manageable units. Before you can use view controllers in your app, you need a basic understanding of the major classes used to display content in an iOS app, including windows and views. A key part of any view controller’simplementation isto manage the views used to display its content. However, managing viewsis not the only job view controllers perform. Most view controllers also communicate and coordinate with other view controllers when transitions occur. Because of the many connections view controllers manage, both looking inward to views and associated objects and looking outward to other controllers, understanding the connections between objects can sometimes be difficult. Instead, use Interface Builder to create storyboards. Storyboards make it easier to visualize the relationships in your app and greatly simplify the effort needed to initialize objects at runtime. 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 14 View Controller BasicsScreens, Windows, and Views Create Visual Interfaces Figure 1-1 shows a simple interface. On the left, you can see the objects that make up this interface and understand how they are connected to each other. Figure 1-1 A window with its target screen and content views There are three major objects at work here: ● A UIScreen object that identifies a physical screen connected to the device. ● A UIWindow object that provides drawing support for the screen. ● A set of UIView objectsto perform the drawing. These objects are attached to the window and draw their contents when the window asks them to. View Controller Basics Screens, Windows, and Views Create Visual Interfaces 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 15Figure 1-2 shows how these classes (and related important classes) are defined in UIKit. Figure 1-2 Classes in the view system Although you don’t need to understand everything about views to understand view controllers, it can be helpful to consider the most salient features of views: ● A view represents a user interface element. Each view covers a specific area. Within that area, it displays contents or responds to user events. ● Views can be nested in a view hierarchy. Subviews are positioned and drawn relative to their superview. Thus, when the superview moves, its subviews move with it. This hierarchy makes it easy to assemble a group of related views by placing them in a common superview. ● Views can animate their property values. When a change to a property value is animated, the value gradually changes over a defined period of time until it reachesthe new value. Changesto multiple properties across multiple views can be coordinated in a single animation. Animation is critically important to iOS app development. Because most apps display only a portion of their contents at one time, an animation allows the user to see when a transition occurred and where the new content came from. An instantaneous transition might confuse the user. ● Views rarely understand the role they play in your app. For example, Figure 1-1 shows a button (titled Hello), which is a special kind of view, known as a control . Controls know how to respond to user interaction in their area, but they don’t know what they control. Instead, when a user interacts with a control, it sends messages to other objects in your app. This flexibility allows a single class (UIButton) to provide the implementation for multiple buttons, each configured to trigger a different action. A complex app needs many views, often assembling them into view hierarchies. It needs to animate subsets of these views onto or off the screen to provide the illusion of a single larger interface. And finally, to keep view classes reusable, the view classes need to be ignorant of the specific role they perform in the app. So the app logic—the brains—needs to be placed somewhere else. Your view controllers are the brains that tie your app’s views together. View Controller Basics Screens, Windows, and Views Create Visual Interfaces 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 16View Controllers Manage Views Each view controller organizes and controls a view; this view is often the root view of a view hierarchy. View controllers are controller objects in the MVC pattern, but a view controller also has specific tasks iOS expects it to perform. These tasks are defined by the UIViewController class that all view controllers inherit from. All view controllers perform view and resource management tasks; other responsibilities depend on how the view controller is used. Figure 1-3 shows the interface from Figure 1-1, but updated here to use a view controller. You never directly assign the views to the window. Instead, you assign a view controller to the window, and the view controller automatically adds its view to the window. Figure 1-3 A view controller attached to a window automatically adds its view as a subview of the window A view controller is careful to load its view only when the view is needed. It can also release the view under certain conditions. For these reasons, view controllers play a key part in managing resources in your app. A view controller is the natural place to coordinate actions of its connected views. For example, when a button is pressed, it sends a message to the view controller. Although the view itself may be ignorant of the task it performs, the view controller is expected to understand what the button press means and how it should respond. The controller might update data objects, animate or change property values stored in its views, or even bring another view controller’s contents to the screen. Usually, each view controller instantiated by your app sees only a subset of your app’s data. It knows how to display that particular set of data, without needing to know about other kinds of data. Thus, an app’s data model, user interface design, and the view controllers you create are all influenced by each other. View Controller Basics View Controllers Manage Views 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 17Figure 1-4 shows an example of an app that managesrecipes. This app displaysthree related but distinct views. The first view lists the recipes that the app manages. Tapping a recipe shows the second view, which describes the recipe. Tapping the recipe’s picture in the detail view shows the third view, a larger version of the photo. Each view is managed by a distinct view controller object whose job isto present the appropriate view, populate the subviews with data, and respond to user interactions within the view hierarchy. Figure 1-4 Distinct views managed by separate view controllers This example demonstrates a few factors common to view controllers: ● Every view is controlled by only one view controller. When a view is assigned to the view controller’s view property, the view controller owns it. If the view is a subview, it might be controlled by the same view controller or a different view controller. You’ll learn more about how to use multiple view controllers to organize a single view hierarchy when you learn about container view controllers. ● Each view controller interacts with a subset of your app’s data. For example, the Photo controller needs to know only the photo to be displayed. ● Because each view controller provides only a subset of the user experience, the view controllers must communicate with each other to make this experience seamless. They may also communicate with other controllers, such as data controllers or document objects. View Controller Basics View Controllers Manage Views 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 18A Taxonomy of View Controllers Figure 1-5 showsthe view controller classes available in the UIKit framework along with other classesimportant to view controllers. For example, the UITabBarController object manages a UITabBar object, which actually displays the tabs associated with the tab bar interface. Other frameworks define additional view controller classes not shown in this figure. Figure 1-5 View controller classes in UIKit View controllers, both those provided by iOS and those you define, can be divided into two general categories—content view controllers and container view controllers—which reflect the role the view controller plays in an app. Content View Controllers Display Content A content view controller presents content on the screen using a view or a group of views organized into a view hierarchy. The controllers described up to this point have been content view controllers. A content view controller usually knows about the subset of the app’s data that is relevant to the role the controller plays in the app. View Controller Basics A Taxonomy of View Controllers 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 19Here are common examples where your app uses content view controllers: ● To show data to the user ● To collect data from the user ● To perform a specific task ● To navigate between a set of available commands or options, such as on the launch screen for a game Content view controllers are the primary coordinating objects for your app because they know the specific details of the data and tasks your app offers the user. Each content view controller object you create is responsible for managing all the views in a single view hierarchy. The one-to-one correspondence between a view controller and the views in its view hierarchy is the key design consideration. You should not use multiple content view controllers to manage the same view hierarchy. Similarly, you should not use a single content view controller object to manage multiple screens’ worth of content. For information about defining your content view controller and implementing the required behaviors, see “Creating Custom Content View Controllers” (page 43). About Table View Controllers Many apps display tabular data. For this reason, iOS provides a built-in subclass of the UIViewController class designed specifically for managing tabular data. This class, UITableViewController, manages a table view and adds support for many standard table-related behaviors such as selection management, row editing, and table configuration. This additional support is there to minimize the amount of code you must write to create and initialize a table-based interface. You can also subclass UITableViewController to add other custom behaviors. View Controller Basics A Taxonomy of View Controllers 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 20Figure 1-6 shows an example using a table view controller. Because it is a subclass of the UIViewController class, the table view controller still has a pointer to the root view of the interface (through its view property) but it also has a separate pointer to the table view displayed in that interface. Figure 1-6 Managing tabular data For more information about table views, see Table View Programming Guide for iOS . Container View Controllers Arrange Content of Other View Controllers A container view controller contains content owned by other view controllers. These other view controllers are explicitly assigned to the container view controller as its children. A container controller can be both a parent to other controllers and a child of another container. Ultimately, this combination of controllers establishes a view controller hierarchy. Each type of container view controller establishes a user interface that its children operate in. The visual presentation of this user interface and the design it imposes on its children can vary widely between different types of containers. For example, here are some ways that different container view controllers may distinguish themselves: ● A container provides its own API to manage its children. ● A container decides whether the children have a relationship between them and what that relationship is. View Controller Basics A Taxonomy of View Controllers 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 21● A container manages a view hierarchy just as other view controllers do. A container can also add the views of any of its children into its view hierarchy. The container decides when such a view is added and how it should be sized to fit the container’s view hierarchy, but otherwise the child view controller remains responsible for the view and its subviews. ● A container might impose specific design considerations on its children. For example, a container might limit its children to certain view controller classes, or it might expect those controllersto provide additional content needed to configure the container’s views. The built-in container classes are each organized around an important user interface principle. You use the user interfaces managed by these containers to organize complex apps. About Navigation Controllers A navigation controller presents data that is organized hierarchically and is an instance of the UINavigationController class. The methods of this class provide support for managing a stack-based collection of content view controllers. Thisstack representsthe path taken by the user through the hierarchical data, with the bottom of the stack reflecting the starting point and the top of the stack reflecting the user’s current position in the data. Figure 1-7 shows screens from the Contacts app, which uses a navigation controller to present contact information to the user. The navigation bar at the top of each page is owned by the navigation controller. The rest of each screen displayed to the user is managed by a content view controller that presentsthe information View Controller Basics A Taxonomy of View Controllers 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 22at that specific level of the data hierarchy. As the user interacts with controls in the interface, those controls tell the navigation controller to display the next view controller in the sequence or dismiss the current view controller. Figure 1-7 Navigating hierarchical data Although a navigation controller’s primary job is to manage its child view controllers, it also manages a few views. Specifically, it manages a navigation bar (that displays information about the user’s current location in the data hierarchy), a button (for navigating back to previous screens), and any custom controls the current view controller needs. You do not directly modify the views owned by the view controller. Instead, you configure the controls that the navigation controller displays by setting properties on each child view controller. For information about how to configure and use navigation controller objects, see “Navigation Controllers”. About Tab Bar Controllers A tab bar controller is a container view controller that you use to divide your app into two or more distinct modes of operation. A tab bar controller is an instance of the UITabBarController class. The tab bar has multiple tabs, each represented by a child view controller. Selecting a tab causes the tab bar controller to display the associated view controller’s view on the screen. View Controller Basics A Taxonomy of View Controllers 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 23Figure 1-8 shows several modes of the Clock app along with the relationships between the corresponding view controllers. Each mode has a content view controller to manage the main content area. In the case of the Clock app, the Clock and Alarm view controllers both display a navigation-style interface to accommodate some additional controls along the top of the screen. The other modes use content view controllers to present a single screen. Figure 1-8 Different modes of the Clock app You use tab bar controllers when your app either presents different types of data or presents the same data in different ways. For information about how to configure and use a tab bar controller, see “Tab Bar Controllers”. About Split View Controllers A split view controller divides the screen into multiple parts, each of which can be updated separately. The appearance of a split view controller may vary depending on its orientation. A split view controller is an instance of the UISplitViewController class. The contents of a split view interface are derived from two child view controllers. View Controller Basics A Taxonomy of View Controllers 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 24Figure 1-9 shows a split view interface from the MultipleDetailViews sample app. In portait mode, only the detail view is displayed. The list view is made available using a popover. However, when displayed in landscape mode, the split view controller displays the contents of both children side by side. Figure 1-9 A master-detail interface in portrait and landscape modes Split view controllers are supported on iPad only and are designed to help you take advantage of the larger screen of that device. They are the preferred way to implement master-detail interfaces in iPad apps. For information about how to configure and use a split view controller, see “Popovers”. About Popover Controllers Look again at Figure 1-9. When the split view controller is displayed in portrait mode, the master views is displayed in a special control, known as a popover. In an iPad app, you can use popover controllers (UIPopoverController) to implement popovers in your own app. A popover controller is not actually a container; it does not inherent from UIViewController at all. But, in practice, a popover controller is similar to a container, so you apply the same programming principles when you use them. For information about how to configure and use a popover controller, see “Popovers”. View Controller Basics A Taxonomy of View Controllers 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 25About Page View Controllers A page view controller is a container view controller used to implement a page layout. That layout allows users to flip between discrete pages of content as if it were a book. A page view controller is an instance of the UIPageViewController class. Each content page is provided by a content view controller. The page view controller managesthe transitions between pages. When new pages are required, the page view controller calls an associated data source to retrieve a view controller for the next page. For information about how to configure and use a page view controller, see “Page View Controllers”. A View Controller’s Content Can Be Displayed in Many Ways For a view controller’s contents to be visible to the user, it must be associated with a window. There are many ways you can do this in your app: ● Make the view controller a window’s root view controller. ● Make the view controller a child of a container. ● Show the view controller in a popover control. ● Present it from another view controller. View Controller Basics A View Controller’s Content Can Be Displayed in Many Ways 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 26Figure 1-10 shows an example from the Contacts app. When the user clicks the plus button to add a new contact, the Contacts view controller presentsthe New Contact view controller. The New Contactscreen remains visible until the user cancels the operation or provides enough information about the contact that it can be saved to the contacts database. At that point the information is transmitted to the Contacts view controller, which then dismisses the controller it presented. Figure 1-10 Presenting a view controller A presented view controller isn’t a specific type of view controller—the presented view controller can be either a content or a container view controller with an attached content view controller. In practice, the content view controller is designed specifically to be presented by another controller, so it can be useful to think of it as a variant of a content view controller. Although container view controllers define specific relationships between the managed view controllers, using presentation allows you to define the relationship between the view controller being presented and the view controller presenting it. View Controller Basics A View Controller’s Content Can Be Displayed in Many Ways 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 27Most of the time, you present view controllersto gather information from the user or capture the user’s attention for some specific purpose. Once that purpose is completed, the presenting view controller dismisses the presented view controller and returns to the standard app interface. It is worth noting that a presented view controller can itself present another view controller. This ability to chain view controllers together can be useful when you need to perform several modal actions sequentially. For example, if the user taps the Add Photo button in the New Contact screen in Figure 1-10 and wants to choose an existing image, the New Contact view controller presents an image picker interface. The user must dismiss the image picker screen and then dismiss the New Contact screen separately to return to the list of contacts. When presenting a view controller, one view controller determines how much of the screen is used to present the view controller. The portion of the screen is called the presentation context By default, the presentation context is defined to cover the window. For more information about how to present view controllers in your app, see “Presenting View Controllers from Other View Controllers” (page 88). View Controllers Work Together to Create an App’s Interface View controllers manage their views and other associated objects, but they also work with other view controllers to provide a seamless user interface. The distribution of work and communication between your app’s view controllers is an essential part of working with them. Because these relationships are so important to building complex apps, this next section reviews the relationships already discussed and describes them in more detail. View Controller Basics View Controllers Work Together to Create an App’s Interface 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 28Parent-Child Relationships Represent Containment A view controller hierarchy starts with a single parent, the root view controller of a window. If that view controller is a container, it may have children that provide content. Those controllers, in turn, may also be containers with children of their own. Figure 1-11 shows an example of a view controller hierarchy. The root view controller is a tab view controller with four tabs. The first tab uses a navigation controller with children of its own and the other three tabs are managed by content view controllers with no children. Figure 1-11 Parent-child relationships The area each view controller fills is determined by its parent. The root view controller’s area is determined by the window. In Figure 1-11, the tab view controller gets its size from the window. It reserves space for its tab bar and gives the remainder of the space to its children. If the navigation controller were the control displayed right now, it reserves space for its navigation bar and hands the rest to its content controller. At each step, the child view controller’s view is resized by the parent and placed into the parent’s view hierarchy. This combination of views and view controllers also establishes the responder chain for events handled by your app. Sibling Relationships Represent Peers Inside a Container The kind of container defines the relationships (if any exists) shared by its children. For example, compare the tab view controller and navigation controller. ● In a tab view controller, the tabs represent distinct screens of content; tab bar controllers do not define a relationship between its children, although your app can choose to do so. ● In a navigation controller, siblings display related views arranged in a stack. Siblings usually share a connection with adjacent siblings. View Controller Basics View Controllers Work Together to Create an App’s Interface 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 29Figure 1-12 shows a common configuration of view controllers associated with a navigation controller. The first child, the master, shows the available content without showing all of the details. When an item is selected, it pushes a new sibling onto the navigation controller so that the user can see the additional details. Similarly, if the user needsto see more details, thissibling can push another view controller thatshowsthe most detailed content available. When siblings have a well defined relationship as in this example, they often coordinate with each other, either directly or through the container controller. See Figure 1-15 (page 32). Figure 1-12 Sibling relationships in a navigation controller Presentation Represents a Transient Display of Another Interface A view controller presents another view controller when it wants that view controller to perform a task. The presenting view controller is in charge of this behavior. It configures the presented view controller, receives information from it, and eventually dismisses it. However, while it is being presented, the presented view controller’s view is temporarily added to the window’s view hierarchy. In Figure 1-13, a content view controller attached to the tab view presents a view controller to perform a task. The content controller is the presenting view controller, and the modal view controller is the presented view controller. Figure 1-13 Modal presentation by a content view View Controller Basics View Controllers Work Together to Create an App’s Interface 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 30When a view controller is presented, the portion of the screen that it coversis defined by a presentation context provided to it by another view controller. The view controller that provides the presentation context does not need be the same view controller that presented it. Figure 1-14 shows the same view controller hierarchy that is presented in Figure 1-13. You can see that the content view presented the view controller, but it did not provide the presentation context. Instead, the view controller was presented by the tab controller. Because of this, even though the presenting view controller only covers the portion of the screen provided to it by the tab view controller, the presented view controller uses the entire area owned by the tab view controller. Figure 1-14 The actual presentation is performed by the root view controller. Control Flow Represents Overall Coordination Between Content Controllers In an app with multiple view controllers, view controllers are usually created and destroyed throughout the lifetime of the app. During their lifetimes, the view controllers communicate with each other to present a seamless user experience. These relationships represent the control flow of your app. Most commonly, this control flow happens when a new view controller isinstantiated. Usually, a view controller is instantiated because of actions in another view controller. The first view controller, known as the source view controller directs the second view controller, the destination view controller. If the destination view controller presents data to the user, the source view controller usually provides that data. Similarly, if the source view controller needsinformation from the destination view controller, it isresponsible for establishing the connection between the two view controllers. Figure 1-15 shows the most common examples of these relationships. In the figure: ● A child of a navigation controller pushes another child onto the navigation stack. ● A view controller presents another view controller. View Controller Basics View Controllers Work Together to Create an App’s Interface 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 31● A view controller displays another view controller in a popover. Figure 1-15 Communication between source and destination view controllers Each controller is configured by the one preceding it. When multiple controllers work together, they establish a communication chain throughout the app. The control flow at each link in this chain is defined by the destination view controller. The source view controller uses the conventions provided by the destination view controller. ● The destination view controller provides properties used to configure its data and presentation. ● If the destination view controller needs to communicate with view controllers preceding it in the chain, it uses delegation. When the source view controller configures the destination view controller’s other properties, it is also expected to provide an object that implements the delegate’s protocol. The benefit of using this control flow convention is that there is a clean division of responsibilities between each pair ofsource and destination view controllers. Data flows down the path when the source view controller asksthe destination view controller to perform a task; the source view controller drivesthe process. For example, it might provide the specific data object that the destination controller should display. In the other direction, data flows up the path when a view controller needsto communicatesinformation back to the source controller that spawned it. For example, it might communicate when the task completes. Also, by consistently implementing this control flow model, you ensure that destination view controllers never know too much about the source view controller that configured them. When it does know about a view controller earlier in the chain, it knows only that the class implements the delegate protocol, not the class of the class. By keeping view controllersfrom knowing too much about each other, individual controllers become more reusable. For someone reading your code, a consistently implemented control flow model makes it easy to see the communication path between any pair of controllers. View Controller Basics View Controllers Work Together to Create an App’s Interface 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 32Storyboards Help You Design Your User Interface When you implement your app using storyboards, you use Interface Builder to organize your app’s view controllers and any associated views. Figure 1-16 shows an example interface layout from Interface Builder. The visual layout of Interface Builder allows you to understand the flow through your app at a glance. You can see what view controllers are instantiated by your app and their order of instantiation. But more than that, you can configure complex collections of views and other objects in the storyboard. The resulting storyboard is stored as a file in your project. When you build your project, the storyboards in your project are processed and copied into the app bundle, where they are loaded by your app at runtime. Figure 1-16 A storyboard diagram in Interface Builder Often, iOS can automatically instantiate the view controllersin yourstoryboard at the moment they are needed. Similarly, the view hierarchy associated with each controller is automatically loaded when it needs to be displayed. Both view controllers and views are instantiated with the same attributes you configured in Interface Builder. Because most of this behavior is automated for you, it greatly simplifies the work required to use view controllers in your app. The full details of creating storyboards are described in Xcode 4 User Guide . For now, you need to know some of the essential terminology used when implementing storyboards in your app. A scene represents an onscreen content area that is managed by a view controller. You can think of a scene as a view controller and its associated view hierarchy. View Controller Basics Storyboards Help You Design Your User Interface 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 33You create relationships between scenes in the same storyboard. Relationships are expressed visually in a storyboard as a connection arrow from one scene to another. Interface Builder usually infers the details of a new relationship automatically when you make a connection between two objects. Two important kinds of relationships exist: ● Containment represents a parent-child relationship between two scenes. View controllers contained in other view controllers are instantiated when their parent controller is instantiated. For example, the first connection from a navigation controller to another scene defines the first view controller pushed onto the navigation stack. This controller is automatically instantiated when the navigation controller is instantiated. An advantage to using containment relationships in a storyboard is that Interface Builder can adjust the appearance of the child view controller to reflect the presence of its ancestors. This allowsInterface Builder to display the content view controller as it appears in your final app. ● A segue represents a visual transition from one scene to another. At runtime, segues can be triggered by various actions. When a segue istriggered, it causes a new view controller to be instantiated and transitioned onscreen. Although a segue is always from one view controller to another, sometimes a third object can be involved in the process. This object actually triggersthe segue. For example, if you make a connection from a button in the source view controller’s view hierarchy to the destination view controller, when the user taps the button, the segue is triggered. When a segue is made directly from the source view controller to the destination view controller, it usually represents a segue you intend to trigger programatically. Different kinds of segues provide the common transitions needed between two different view controllers: ● A push segue pushes the destination view controller onto a navigation controller’s stack. ● A modal segue presents the destination view controller. ● A popover segue displays the destination view controller in a popover. ● A custom segue allows you to design your own transition to display the destination view controller. Segues share a common programming model. In this model, the destination controller is instantiated automatically by iOS and then the source view controller is called to configure it. This behavior matches the control flow model described in “Control Flow Represents Overall Coordination Between Content Controllers” (page 31). You can also create connections between a view controller and objects stored in the same scene. These outlets and actions enable you to carefully define the relationships between the view controller and its associated objects. Connections are not normally visible in the storyboard itself but can be viewed in the Connections Inspector of Interface Builder. View Controller Basics Storyboards Help You Design Your User Interface 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 34Whether you are working with view controllers provided by iOS, or with custom controllers you’ve created to show your app’s content, you use a similar set of techniques to actually work with the view controllers. The most common technique for working with view controllers is to place them inside a storyboard. Placing view controllers in a storyboard allows you to directly establish relationships between the view controllers in your app without writing code. You can see the flow of control—from controllers created when your app first launches, to controllers that are instantiated in response to a user’s actions. iOS manages most of this process by instantiating these view controllers only when the app needs them. Sometimes you may need to create a view controller by allocating and initializing it programmatically. When working with view controllers directly, you must write code that instantiates the view controller, configures it, and displays it. 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 35 Using View Controllers in Your AppWorking with View Controllers in Storyboards Figure 2-1 shows an example of a storyboard. This storyboard includes view controllers, associated views, and connection arrows that establish relationships between the view controllers. In effect, this storyboard tells a story, starting with one scene and later showing others in response to a user’s actions. Figure 2-1 A storyboard holds a set of view controllers and associated objects A storyboard may designate one view controller to be the initial view controller. If a storyboard represents a specific workflow through part of your UI, the initial view controller represents the first scene in that workflow. You establish relationships from the initial view controller to other view controllers in the storyboard. In turn, you establish relationships from those view controllers to others, eventually connecting most or all of the storyboard’s scenes into a single connected graph. The type of relationship you establish determines when a connected view controller is instantiated by iOS, as follows: ● If the relationship is a segue, the destination view controller is instantiated when the segue is triggered. ● If the relationship represents containment, the child view controller is instantiated when its parent is instantiated. ● If the controller is not the destination or child of another controller, it is never instantiated automatically. You must instantiate it from the storyboard programmatically. Using View Controllers in Your App Working with View Controllers in Storyboards 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 36To identify a specific view controller or segue inside a storyboard, use Interface Builder to assign it an identifier string that uniquely identifies it. To programmatically load a view controller from the storyboard, you must assign it an identifier. Similarly, to trigger a segue programmatically, it must also be assigned an identifier. When a segue is triggered, that segue's identifier is passed to the source view controller, which uses it to determine which segue was triggered. For this reason, consider labeling every segue with an identifier. When you build an app using storyboards, you can use a single storyboard to hold all of its view controllers, or you can create multiple storyboards and implement a portion of the user interface in each. One storyboard in your app is almost always designated as the main storyboard. If there is a main storyboard, iOS loads it automatically; other storyboards must be explicitly loaded by your app. The Main Storyboard Initializes Your App’s User Interface The main storyboard is defined in the app’s Information property list file. If a main storyboard is declared in this file, then when your app launches, iOS performs the following steps: 1. It instantiates a window for you. 2. It loads the main storyboard and instantiates its initial view controller. 3. It assigns the new view controller to the window’s rootViewController property and then makes the window visible on the screen. Your app delegate is called to configure the initial view controller before it is displayed. The precise set of steps iOS uses to load the main storyboard is described in “Coordinating Efforts Between View Controllers” (page 98). Segues Automatically Instantiate the Destination View Controller A segue represents a triggered transition that brings a new view controller into your app’s user interface. Segues contain a lot of information about the transition, including the following: ● The object that caused the segue to be triggered, known as the sender ● The source view controller that starts the segue ● The destination view controller to be instantiated ● The kind of transition that should be used to bring the destination view controller onscreen ● An optional identifier string that identifies that specific segue in the storyboard When a segue is triggered, iOS takes the following actions: 1. It instantiates the destination view controller using the attribute values you provided in the storyboard. Using View Controllers in Your App Working with View Controllers in Storyboards 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 372. It gives the source view controller an opportunity to configure the new controller. 3. It performs the transition configured in the segue. Note: When you implement custom view controllers, each destination view controller declares public properties and methods used by the source view controller to configure its behavior. In return, your custom source view controllers override storyboard methods provided by the base class to configure the destination view controller. The precise details are in “Coordinating Efforts Between View Controllers” (page 98). Triggering a Segue Programmatically A segue is usually triggered because an object associated with the source view controller, such as a control or gesture recognizer, triggered the segue. However, a segue can also be triggered programmatically by your app, as long as the segue has an assigned identifier. For example, if you are implementing a game, you might trigger a segue when a match ends. The destination view controller then displays the match’s final scores. You programmatically trigger the segue by calling the source view controller’s performSegueWithIdentifier:sender: method, passing in the identifier for the segue to be triggered. You also pass in another object that acts as the sender. When the source controller is called to configure the destination view controller, both the sender object and the identifier for the segue are provided to it. Listing 2-1 shows a simple method that triggers a segue. This example is a portion of a larger example described in “Creating an Alternate Landscape Interface” (page 80). In this abbreviated form, you can see that the view controller is receiving an orientation notification. When the view controller is in portrait mode and the device is rotated into landscape orientation, the method uses a segue to present a different view controller onscreen. Because the notification object in this case provides no useful information for performing the segue command, the view controller makes itself the sender. Listing 2-1 Triggering a segue programmatically - (void)orientationChanged:(NSNotification *)notification { UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation; if (UIDeviceOrientationIsLandscape(deviceOrientation) && !isShowingLandscapeView) { [self performSegueWithIdentifier:@"DisplayAlternateView" sender:self]; isShowingLandscapeView = YES; } Using View Controllers in Your App Working with View Controllers in Storyboards 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 38// Remainder of example omitted. } If a segue can be triggered only programmatically, you usually draw the connection arrow directly from the source view controller to the destination view controller. Instantiating a Storyboard’s View Controller Programmatically You may want to programmatically instantiate a view controller without using a segue. A storyboard is still valuable, because you can use it to configure the attributes of the view controller as well as its view hierarchy. However, if you do instantiate a view controller programmatically, you do not get any of the behavior of a segue. To display the view controller, you must implement additional code. For this reason, you should rely on segues where possible and use this technique only when needed. Here are the steps your code needs to implement: 1. Obtain a storyboard object (an object of the UIStoryboard class). If you have an existing view controller instantiated from the same storyboard, read its storyboard property to retrieve the storyboard. To load a different storyboard, call the UIStoryboard class’s storyboardWithName:bundle: class method, passing in the name of the storyboard file and an optional bundle parameter. 2. Call the storyboard object’s instantiateViewControllerWithIdentifier: method, passing in the identifier you defined for the view controller when you created it in Interface Builder. Alternatively, you can use the instantiateInitialViewController method to instantiate the initial view controller in a storyboard, without needing to know its identifier. 3. Configure the new view controller by setting its properties. 4. Display the new view controller. See “Displaying a View Controller’s Contents Programmatically” (page 41). Listing 2-2 shows an example of this technique. It retrieves the storyboard from an existing view controller and instantiates a new view controller using it. Listing 2-2 Instantiating another view controller inside the same storyboard - (IBAction)presentSpecialViewController:(id)sender { UIStoryboard *storyboard = self.storyboard; SpecialViewController *svc = [storyboard instantiateViewControllerWithIdentifier:@"SpecialViewController"]; Using View Controllers in Your App Working with View Controllers in Storyboards 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 39// Configure the new view controller here. [self presentViewController:svc animated:YES completion:nil]; } Listing 2-3 shows another frequently used technique. This example loads a new storyboard and instantiates its initial view controller. It uses this view controller as the root view controller for a new window being placed on an external screen. To display the returned window, your app calls the window’s makeKeyAndVisible method. Listing 2-3 Instantiating a view controller from a new storyboard - (UIWindow*) windowFromStoryboard: (NSString*) storyboardName onScreen: (UIScreen*) screen { UIWindow *window = [[UIWindow alloc] initWithFrame:[screen bounds]]; window.screen = screen; UIStoryboard *storyboard = [UIStoryboard storyboardWithName:storyboardName bundle:nil]; MainViewController *mainViewController = [storyboard instantiateInitialViewController]; window.rootViewController = mainViewController; // Configure the new view controller here. return window; } Transitioning to a New Storyboard Requires a Programmatic Approach Segues connect only scenes that are stored in the same storyboard. To display a view controller from another storyboard, you must explicitly load the storyboard file and instantiate a view controller inside it. There is no requirement that you create multiple storyboards in your app. Here, though, are a few cases where multiple storyboards might be useful to you: Using View Controllers in Your App Working with View Controllers in Storyboards 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 40● You have a large programming team, with different portions of the user interface assigned to different parts of the team. In this case, each subteam owns a storyboard limiting the number of team members working on any specific storyboard’s contents. ● You purchased or created a library that predefines a collection of view controller types; the contents of those view controllers are defined in a storyboard provided by the library. ● You have content that needs to be displayed on an external screen. In this case, you might keep all of the view controllers associated with the alternate screen inside a separate storyboard. An alternative pattern for the same scenario is to write a custom segue. Containers Automatically Instantiate Their Children When a container in a storyboard is instantiated, its children are automatically instantiated at the same time. The children must be instantiated at the same time to give the container controller some content to display. Similarly, if the child that was instantiated is also a container, its children are also instantiated, and so on, until no more containment relationships can be traced to new controllers. If you place a content controller inside a navigation controller inside a tab bar controller, when the tab bar is instantiated, the three controllers are simultaneously instantiated. The container and its descendants are instantiated before your view controller is called to configure them. Your source view controller (or app delegate) can rely on all the children being instantiated. This instantiation behavior is important, because your custom configuration code rarely configures the container(s). Instead, it configures the content controllers attached to the container. Instantiating a Non-Storyboard View Controller To create a view controller programmatically without the use of the storyboard, you use Objective-C code to allocate and initialize the view controller. You gain none of the benefits of storyboards, meaning you have to implement additional code to configure and display the new view controller. Displaying a View Controller’s Contents Programmatically For a view controller’s content to be useful, it needs to be displayed on screen. There are several options for displaying a view controller’s contents: ● Make the view controller the root view controller of a window. ● Make it a child of a visible container view controller. ● Present it from another visible view controller. Using View Controllers in Your App Instantiating a Non-Storyboard View Controller 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 41● Present it using a popover (iPad only). In all cases, you assign the view controller to another object—in this case, a window, a view controller, or a popover controller. This object resizes the view controller’s view and adds it to its own view hierarchy so that it can be displayed. Listing 2-4 showsthe most common case, which isto assign the view controller to a window. This code assumes that a storyboard is not being used, so it performs the same steps that are normally done on your behalf by the operating system: It creates a window and setsthe new controller asthe root view controller. Then it makes the window visible. Listing 2-4 Installing the view controller as a window’s root view controller - (void)applicationDidFinishLaunching:(UIApplication *)application { UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; levelViewController = [[LevelViewController alloc] init]; window.rootViewController = levelViewController; [window makeKeyAndVisible]; } Important: Never install the view controller’s view into a view hierarchy directly. To present and manage views properly, the system makes a note of each view (and its associated view controller) that you display. It uses this information later to report view controller–related events to your app. For example, when the device orientation changes, a window uses this information to identify the frontmost view controller and notify it of the change. If you incorporate a view controller’s view into your hierarchy by other means, the system may handle these events incorrectly. If you are implementing your own custom container controller, you add another view controller’s view to your own view hierarchy, but you also create a parent-child relationship first. This ensures that events are delivered correctly. See “Creating Custom Container View Controllers” (page 111). Using View Controllers in Your App Displaying a View Controller’s Contents Programmatically 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 42Custom content view controllers are the heart of your app. You use them to present your app’s unique content. All apps need at least one custom content view controller. Complex apps divide the workload between multiple content controllers. A view controller has many responsibilities. Some of these responsibilities are things that iOS requires the view controller to do. Other responsibilities are things you assign to the view controller when you define its role in your app. Anatomy of a Content View Controller The UIViewController class provides the fundamental infrastructure for implementing all custom view controllers. You define a custom subclass of UIViewController. That subclass provides the necessary code to populate views with data and respond to user actions. When you want to make adjustments to the default behavior of the view controller, you override methods of the UIViewController class. Your view controller may also interact with other UIKit classes to implement the behavior you want. 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 43 Creating Custom Content View ControllersFigure 3-1 shows some of the key objects associated directly with a content view controller. These are the objectsthat are essentially owned and managed by the view controller itself. The view (accessible via the view property) is the only object that must be provided, although most view controllers have additional subviews attached to this view as well as custom objects containing the data they need to display. Figure 3-1 Anatomy of a content view controller View View View View Content view controller Custom data objects When you design a new view controller, it potentially has many responsibilities. Some of those responsibilities look inward, to the views and other objects it controls. Other responsibilities look outward to other controllers. The following sections enumerate many of the common responsibilities for a view controller. View Controllers Manage Resources Some objects are instantiated when the view controller is initialized and are disposed of when your view controller is released. Other objects, like views, are needed only when the view controller’s contents are visible onscreen. As a result, view controllers use resources efficiently and should be prepared to release resources when memory is scarce. Properly implementing this behavior in your app's view controllers makes it so your app uses memory and other resources—such as CPU, GPU, and battery—more efficiently. See “Resource Management in View Controllers” (page 56). Creating Custom Content View Controllers Anatomy of a Content View Controller 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 44View Controllers Manage Views View controllers manage their view and its subviews, but the view’s frame—its position and size in its parent’s view—is often determined by other factors, including the orientation of the device, whether or not the status bar is visible and even how the view controller’s view is displayed in the window. Your view controller should be designed to layout its view to fit the frame provided to it. View management has other aspects as well. Your view controller is notified when its view is about to appear and disappear from the screen. Your view controller can use this notification to perform other actions necessary to its operation. See “Resizing the View Controller’s Views” (page 69), “Supporting Multiple Interface Orientations” (page 74), “Responding to Display-Related Notifications” (page 66). View Controllers Respond to Events Your view controller is often the central coordinating object for its views and controls. Typically, you design your user interface so that controls send messages to the controller when a user manipulates them. Your view controller is expected to handle the message, making any necessary changes to the views or data stored in the view controller. Your view controller also participates in the responder chain used to deliver events to your app. You can override methodsin your view controller classto have it participate directly in event handling. View controllers also are good objects to implement other behaviors—such as responding to system notifications, timers or events specific to your app. See “Using View Controllers in the Responder Chain” (page 72). View Controllers Coordinate with Other Controllers Although a view controller may create and manage many other objects, it does not usually need to expose these objects publicly to inspection or modification. It may collaborate with other objects (especially other view controllers), but it should expose the fewest number of properties and methods necessary to allow its collaborators to communicate with it. Exposing too many implementation details in your view controller class makes it difficult to modify your view controller’s implementation. Collaborators that rely on these implementation details would need to be modified to continue to work with your view controller class. See “Coordinating Efforts Between View Controllers” (page 98). Creating Custom Content View Controllers Anatomy of a Content View Controller 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 45View Controllers Often Work with Containers If your view controller is placed inside a container view controller, the container imposes additional constraints, as shown in Figure 3-2. The container may ask your view controller to provide other objects used to configure the container’s user interface. For example, a content view controller placed inside a tab view controller provides a tab bar item to display for that tab. Figure 3-2 A container view controller imposes additional demands on its children The properties used to configure the containers provided by UIKit are defined by the UIViewController class. For more information on specific types of containers and the properties you configure to support them, see View Controller Catalog for iOS . View Controllers May Be Presented by Other View Controllers Some view controllers you design are intended to be presented by other view controllers. You might present your view controller directly, or you might make it a child of a container view controller and present the container instead. When presented, it moves onscreen, remaining there until it is dismissed. There are several reasons you might present a view controller: Creating Custom Content View Controllers Anatomy of a Content View Controller 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 46● To gather information from the user immediately. ● To present some content temporarily. ● To change work modes temporarily. ● To implement alternate interfaces for different device orientations. ● To present a new view hierarchy with a specific type of animated transition (or no transition). Most of these reasons involve interrupting your app’s workflow temporarily in order to gather or display some information. In almost all cases, the presented view controller implements a delegate. The presented view controller uses the delegate to communicate with the presenting view controller. After your app has the information it needs (or the user finishes viewing the presented information), the presented view controller communicates this back to the presenting view controller. The presenting view controller dismisses the presented view controller to return the app to its previous state. See “Presenting View Controllers from Other View Controllers” (page 88). Designing Your Content View Controller Before writing any code in your view controller, you should be able to answer some basic questions about how you intend to use it. The questions provided below are designed to help you narrow the focus of your view controller and to help you understand the role it plays in your app. In particular, it helps you identify connections—usually to other controllers—your view controller needs to perform its tasks. ● Are you using a storyboard to implement the view controller? ● When is it instantiated? ● What data does it show? ● What tasks does it perform? ● How is its view displayed onscreen? ● How does it collaborate with other view controllers? Your answers to these questions need not be precise if you are still working out the role it plays. Still, it helps to have a general sense of what your view controller does and how other objects interact with it. The questions above don’t ask you to define the appearance of your view controller or to be precise about the implementation details of how it performs the tasks you’ve assigned to it. Those are important questions you need to answer, but neither of these things should affect your view controller’s public interface. You want the flexibility to be able to change the visual design of your view controller without changing the class declaration that defines how other controllers collaborate with it. Creating Custom Content View Controllers Designing Your Content View Controller 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 47Use a Storyboard to Implement Your View Controller You might consider whether or not to use a storyboard as an implementation detail, but the approach you take affects how you implement the view controller and how other objects collaborate with it. You always use a storyboard unless you have a strong reason not to. When you use storyboards: ● iOS usually instantiates your view controller for you automatically. ● To finish instantiating it, you override its awakeFromNib method. ● Other objects configure it through its properties. ● You create its view hierarchy and other related objects in Interface Builder. These objects are loaded automatically when the view is needed. ● Relationships with other view controllers are created in the storyboard. If you design your view controller to be used programmatically: ● The view controller is instantiated by allocating and initializing it. ● You create an custom initialization method to initialize the view controller. ● Other objects configure the view controller using itsinitialization method and by configuring its properties. ● You override the loadView method to programmatically create and configure its view hierarchy. ● Relationships with other view controllers are created by writing code. Know When Your Controller Is Instantiated Knowing when your view controller is instantiated usually implies other details for how your app operates. For example, you might know that your view controller is alwaysinstantiated by the same object. Often the objects that instantiate view controllers are themselves view controllers; this is almost always the case in an app that uses storyboards. In any case, knowing when, why, and by what object your view controller is instantiated gives you insight into the information exchanged between your view controller and the object that created it. Know What Data Your View Controller Shows and Returns When you answer these two questions, you are working to understand the data model for your app and also whether that data needs to be exchanged between your view controllers. Here are some common patterns you should expect to see in your view controllers: Creating Custom Content View Controllers Designing Your Content View Controller 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 48● The view controller receives data from another controller and displays it, without offering a way to edit it. No data is returned. ● The view controller allows the user to enter new data. After the user finishes editing the data, it sends the new data to another controller. ● The view controller receives data from another controller and allows the user to edit it. After the user finishes editing the data, it sends the new data to another controller. ● The view controller doesn’t send or receive data. Instead, it shows static views. ● The view controller doesn’tsend or receive data. Instead, itsimplementation loadsits data without exposing this mechanism to other view controllers. For example, the GKAchievementViewController class has built-in functionality to determine which player is authenticated on the device. It also knows how to load that player’s data from Game Center. The presenting view controller does not need to know what data is loaded or how it was loaded. You are not constrained to use only these designs. When data travels into or out of your view controller, consider defining a data model class to hold the data to be transferred to the new controller. For example, in Your Second iOS App: Storyboards, the master controller uses a BirdSighting object to send data associated with a sighting to the detail controller. Using an object for this makes it easier to update the data to include additional properties without changing the method signatures in your controller classes. Know What Tasks Your Controller Allows the User to Perform Some view controllers allow users to view, create, or edit data. Other view controllers allow users to navigate to otherscreens of content. And some allow usersto perform tasks provided by the view controller. For example, the MFMailComposeViewController class allows a user to compose and send emails to other users. It handles the low-level details of sending mail messages. As you determine which tasks your view controller performs, decide how much control over those tasks your view controller exposes to other controllers. Many view controllers can perform tasks without exposing configuration data to other controllers. For example, the GKAchievementViewController class displays achievements to the user without exposing any properties to configure how it loads or presents its data. The MFMailComposeViewController class presents a slightly different scenario by exposing some properties that another controller can use to configure the initial content it displays. After that, a user can edit the content and send the email message without giving other controller objects a chance to affect that process. Creating Custom Content View Controllers Designing Your Content View Controller 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 49Know How Your View Controller Is Displayed Onscreen Some view controllers are designed to be root view controllers. Others expect to be presented by another view controller or placed in a container controller. Occasionally, you design controllers that can be displayed in multiple ways. For example, a split view controller’s master view is displayed in the split view in landscape mode and in a popover control in portrait mode. Knowing how your view controller is displayed gives you insight into how its view issized and placed onscreen. It also affects other areas, such as determining what other controllers your view controller collaborates with. Know How Your Controller Collaborates with Other Controllers By this point, you already know some things about collaboration. For example, if your view controller is instantiated from a segue, then it probably collaborates with the source view controller that configures it. And if your controller is a child of a container, then it collaborates with the container. But there are relationships in the other direction as well. For example, your view controller might defer some of its work and hand it off to another view controller. It might even exchange data with an existing view controller. With all of these connections, your view controller provides an interface that other controllers use, or it is aware of other controllers and it uses their interfaces. These connections are essential to providing a seamless experience, but they also represent design challenges because they introduce dependencies between classes in your app. Dependencies are a problem because they make it more difficult to change any one class in isolation from the other classes that make up your app. For this reason, you need to balance the needs of your app now against the potential need to keep your app design flexible enough to change later. Examples of Common View Controller Designs Designing a new view controller can be challenging. It helps to look at existing designs and understand what they do and why. This next section talks about some common view controller styles used in iOS apps. Each example includes a description of the role the view controller plays, a brief description of how it works at a high level, and one possible list of answers to the design questions listed above. Example: Game Title Screen Mission Statement A view controller that allows the user to select between different styles of game play. Creating Custom Content View Controllers Examples of Common View Controller Designs 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 50Description When a game is launched, it rarely jumps right into the actual game. Instead, it displays a title screen that identifies the game and presents a set of game variants to the player. For example, a game might offer buttons that allow a player to start a single player or multiplayer game. When the user selects one of the options, the app configures itself appropriately and launches into its gameplay. A title screen is interesting specifically because its contents are static; they don’t need data from another controller. As such, this view controller is almost entirely self-sufficient. It does, however, know about other view controllers, because it instantiates other view controllers to launch its gameplay. Design ● Are you using a storyboard to implement the view controller? Yes. ● When is it instantiated? This view controller is the initial scene in the main storyboard. ● What data does it show? This class displays preconfigured controls and images; it does not present user data. It does not include configurable properties. ● What tasks does it perform? When a user taps on a button, it triggers a segue to instantiate another view controller. Each segue is identified so that the appropriate game play can be configured. ● How is its view displayed onscreen? It isinstalled automatically asthe root view controller of the window. ● How does it collaborate with other view controllers? It instantiates another view controller to present a gameplay screen. When gameplay ends, the other view controller sends a message to the title screen controller to inform it that play has ended. The title screen controller then dismisses the other view controller. Alternative Design Considerations The default answers assume that no user data is displayed. Some games include player data to configure the views or controls. For example: ● You might want the view controller to display the user’s Game Center alias. ● You might want it to enable or disable buttons based on whether the device is connected to Game Center. ● You might want it to enable or disable buttons based on In-App Purchase items the user has purchased. When these additional items are added to the design, the view controller takes on a more traditional role. It might receive data objects or data controllers from the app delegate so that it can query and update this state as necessary. Or, as it is the root view controller for the window, you might simply implement those behaviors directly in the title screen controller. The actual design likely depends on how flexible you need your code to be. Creating Custom Content View Controllers Examples of Common View Controller Designs 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 51Example: Master View Controller Mission Statement The initial view controller of a navigation controller, used to display a list of the app’s available data objects. Description A master view controller is a very common part of a navigation-based app. For example, Your Second iOS App: Storyboards uses a master view to display the list of bird sightings. When a user selects a sighting from the list, the master view controller pushes a new detail controller onto the screen. Because this view controller displays a list of items, it subclasses UITableViewController instead of UIViewController. Design ● Are you using a storyboard to implement the view controller? Yes. ● When is it instantiated? Asthe root view controller of a navigation controller, it isinstantiated at the same time as its parent. ● What data does it show? A high-level view of the app’s data. It implements properties that the app delegate uses to provide data to it. For example, the bird watching app provides a custom data controller object to the master view controller. ● What tasks does it perform? It implements an Add button to allow users to create new records. ● How is its view displayed onscreen? It is a child of a navigation controller. ● How does it collaborate with other view controllers? When the user taps on an item in the list, it uses a push segue to show a detail controller. When the user taps on the Add button, it uses a modal segue to present a new view controller that edits a new record. It receives data back from this modal view controller and sends this data to the data controller to create a new bird sighting. Alternative Design Considerations A navigation controller and an initial view controller is used when building an iPhone app. When designing the same app for the iPad, the master view controller is a child of a split view controller instead. Most other design decisions stay the same. Creating Custom Content View Controllers Examples of Common View Controller Designs 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 52Example: Detail View Controller Mission Statement A controller pushed onto a navigation stack to display the details for a list item selected from the master view controller. Description The detail view controller represents a more detailed view of a list item displayed by the master view controller. As with the master view controller, the list appears inside a nav bar interface. When the user finishes viewing the item they click a button in the nav bar to return to the master view. Your Second iOS App: Storyboards uses the UITableViewController class to implement its detail view. It uses a static table cells, each of which accesses one piece of the bird sighting data. A static table view is a good way to implement this design. Design ● Are you using a storyboard to implement the view controller? Yes. ● When is it instantiated? It is instantiated by a push segue from the master view controller. ● What data does it show? Itshowsthe data stored in a custom data object. It declares properties configured by the source view controller to provide this data. ● What tasks does it perform? It allows the user to dismiss the view. ● How is its view displayed onscreen? It is a child of a navigation controller. ● How does it collaborate with other view controllers? It receives data from the master view controller. Alternative Design Considerations A navigation controller is most often used when building an iPhone app. When designing the same app for the iPad, the detail view controller is a child of a split view controller instead. Many of the other implementation details stay the same. If your app needs more custom view behavior, it mightsubclassthe UIViewController class and implement its own custom view hierarchy. Creating Custom Content View Controllers Examples of Common View Controller Designs 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 53Example: Mail Compose View Controller Mission Statement A view controller that allows the user to compose and send an email. Description The Message UI framework provides the MFMailComposeViewController class. This class allows a user to compose and send an email. This view controller is interesting because it does more than simply show or edit data—it actually sends the email. Another interesting design choice in this class is that it allows an app to provide an initial configuration for the email message. After the initial configuration has been presented, the user can override these choices before sending the mail. Design ● Are you using a storyboard to implement the view controller? No. ● When is it instantiated? It is instantiated programmatically. ● What data does it show? It shows the various parts of an email message, including a recipients list, title, attachments and the email message itself. The class provides propertiesthat allow another view controller to preconfigure the email message. ● What tasks does it perform? It sends email. ● How is its view displayed onscreen? The view controller is presented by another view controller. ● How does it collaborate with other view controllers? It returns status information to its delegate. This status allows the presenting view controller to know whether an email was sent. Implementation Checklist for Custom Content View Controllers For any custom content view controllers you create, there are a few tasks that you must have your view controller handle: ● You must configure the view to be loaded by your view controller. Your custom class may need to override specific methods to manage how its view hierarchy is loaded and unloaded. These same methods might manage other resources that are created at the same time. See “Resource Management in View Controllers” (page 56). Creating Custom Content View Controllers Implementation Checklist for Custom Content View Controllers 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 54● You must decide which device orientations your view controller supports and how it reacts to a change in device orientation; see “Supporting Multiple Interface Orientations” (page 74). As you implement your view controller, you will likely discover that you need to define action methods or outlets to use with its views. For example, if the view hierarchy contains a table, you probably want to store a pointer to that table in an outletso that you can accessit later. Similarly, if your view hierarchy contains buttons or other controls, you probably want those controls to call an associated action method on the view controller. As you iterate through the definition of your view controller class, you may therefore find that you need to add the following items to your view controller class: ● Declared properties pointing to the objects containing the data to be displayed by the corresponding views ● Public methods and propertiesthat expose your view controller’s custom behavior to other view controllers ● Outlets pointing to views in the view hierarchy with which your view controller must interact ● Action methods that perform tasks associated with buttons and other controls in the view hierarchy Important: Clients of your view controller class do not need to know what views your view controller displays or what actions those views might trigger. Whenever possible, outlets and actions should be declared in a category inside your class’s implementation file. For example, if your class is named MyViewController, you implement the category by adding the following declaration to MyViewController.m: @interface MyViewController() // Outlets and actions here. @end @implementation MyViewController // Implementation of the privately declared category must go here. @end When you declare a category without a name, the properties and actions must be implemented in the same implementation block as any methods or properties declared in your public interface. The outlets and actions defined in the private category are visible to Interface Builder, but not to other classes in your app. This strategy allows you to gain the benefits of Interface Builder without exposing your class’s secrets. If another class needs access to your view controller’s functionality, add public methods and properties to access this functionality instead. Creating Custom Content View Controllers Implementation Checklist for Custom Content View Controllers 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 55View controllers are an essential part of managing your app’s resources. View controllers allow you to break your app up into multiple parts and instantiate only the parts that are needed. But more than that, a view controller itself manages different resources and instantiates them at different times. For example, a view controller’s view hierarchy is instantiated only when the view is accessed; typically, this occurs only when the view is displayed on screen. If multiple view controllers are pushed onto a navigation stack at the same time, only the topmost view controller’s contents are visible, which means only its views are accessed. Similarly, if a view controller is not presented by a navigation controller, it does not need to instantiate its navigation item. By deferring most resource allocation until it is needed, view controllers use less resources. When memory available to the app runs low, all view controllers are automatically notified by the system. This allows the view controller to purge caches and other objects that can be easily recreated later when memory is more plentiful. The exact behavior varies depending on which version of iOS your app is running on, and this has implications for your view controller design. Carefully managing the resources associated with your view controllers is critical to making your app run efficiently. You should also prefer lazy allocation; objects that are expensive to create or maintain should be allocated later and only when needed. For this reason, your view controllers should separate objects needed throughout the lifetime of the view controller from objects that are only necessary some of the time. When your view controller receives a low-memory warning, it should be prepared to reduce its memory usage if it is not visible onscreen. Initializing a View Controller When a view controller is first instantiated, it creates or loads objects it needs through its lifetime. It should not create its view hierarchy or objects associated with displaying content. It should focus on data objects and objects needed to implement its critical behaviors. Initializing a View Controller Loaded from a Storyboard When you create a view controller in a storyboard, the attributes you configure in Interface Builder are serialized into an archive. Later, when the view controller isinstantiated, this archive isloaded into memory and processed. The result is a set of objects whose attributes match those you set in Interface Builder. The archive is loaded 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 56 Resource Management in View Controllersby calling the view controller’s initWithCoder: method. Then, the awakeFromNib method is called on any object that implements that method. You use this method to perform any configuration steps that require other objects to already be instantiated. For more on archiving and archiving, see Archives and Serializations Programming Guide . Initializing View Controllers Programmatically If a view controller allocatesitsresources programmatically, create a custom initialization method that isspecific to your view controller. This method should call the super class’s init method and then perform any class specific initialization. In general, do not write complex initialization methods. Instead, implement a simple initialization method and then provide properties for clients of your view controller to configure its behaviors. A View Controller Instantiates Its View Hierarchy When Its View is Accessed Whenever some part of your app asks the view controller for its view object and that object is not currently in memory, the view controller loads the view hierarchy into memory and stores it in its view property for future reference. The steps that occur during the load cycle are: 1. The view controller calls its loadView method. The default implementation of the loadView method does one of two things: ● If the view controller is associated with a storyboard, it loads the views from the storyboard. ● If the view controller is not associated with a storyboard, an empty UIView object is created and assigned to the view property. 2. The view controller callsits viewDidLoad method, which enables yoursubclassto perform any additional load-time tasks. Resource Management in View Controllers A View Controller Instantiates Its View Hierarchy When Its View is Accessed 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 57Figure 4-1 shows a visual representation of the load cycle, including several of the methods that are called. Your app can override both the loadView and the viewDidLoad methods as needed to facilitate the behavior you want for your view controller. For example, if your app does not use storyboards but you want additional views to be added to the view hierarchy, you override the loadView method to instantiate these views programatically. Figure 4-1 Loading a view into memory Resource Management in View Controllers A View Controller Instantiates Its View Hierarchy When Its View is Accessed 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 58Loading a View Controller’s View from a Storyboard Most view controllersload their view from an associated storyboard. The advantage of using storyboardsisthat they allow you to lay out and configure your views graphically, making it easier and faster to adjust your layout. You can iterate quickly through different versions of your user interface to end up with a polished and refined design. Creating the View in Interface Builder Interface Builder is part of Xcode and provides an intuitive way to create and configure the views for your view controllers. Using Interface Builder, you assemble views and controls by manipulating them directly, dragging them into the workspace, positioning them, sizing them, and modifying their attributes using an inspector window. The results are then saved in a storyboard file, which stores the collection of objects you assembled along with information about all the customizations you made. Configuring the View Display Attributes in Interface Builder To help you layout the contents of your view properly, Interface Builder provides controls that let you specify whether the view has a navigation bar, a toolbar, or other objectsthat might affect the position of your custom content. If the controller is connected to container controllersin the storyboard, it can infer these settingsfrom the container, making it easier to see exactly how it should appear at runtime. Configuring Actions and Outlets for Your View Controller Using Interface Builder, you create connections between the views in your interface and your view controller. Listing 4-1 shows the declaration of a custom MyViewController class’s two custom outlets (designated by the IBOutlet keyword) and a single action method (designated by the IBAction return type). The declarations are made in a category inside the implementation file. The outlets store references to a button and a text field in the storyboard, while the action method responds to taps in the button. Listing 4-1 Custom view controller class declaration @interface MyViewController() @property (nonatomic) IBOutlet id myButton; @property (nonatomic) IBOutlet id myTextField; - (IBAction)myAction:(id)sender; @end Resource Management in View Controllers A View Controller Instantiates Its View Hierarchy When Its View is Accessed 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 59Figure 4-2 shows the connections you would create among the objects in such a MyViewController class. Figure 4-2 Connections in the storyboard When the previously configured MyViewController class is created and presented, the view controller infrastructure automatically loads the views from the storyboard and reconfigures any outlets or actions. Thus, by the time the view is presented to the user, the outlets and actions of your view controller are set and ready to be used. This ability to bridge between your runtime code and your design-time resource files is one of the things that makes storyboards so powerful. Creating a View Programmatically If you prefer to create views programmatically, instead of using a storyboard, you do so by overriding your view controller’s loadView method. Your implementation of this method should do the following: 1. Create a root view object. The root view contains all other views associated with your view controller. You typically define the frame for this view to match the size of the app window, which itself should fill the screen. However, the frame is adjusted based on how your view controller is displayed. See “Resizing the View Controller’s Views” (page 69). You can use a generic UIView object, a custom view you define, or any other view that can scale to fill the screen. 2. Create additional subviews and add them to the root view. Resource Management in View Controllers A View Controller Instantiates Its View Hierarchy When Its View is Accessed 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 60For each view, you should: a. Create and initialize the view. b. Add the view to a parent view using the addSubview: method. 3. If you are using auto layout, assign sufficient constraints to each of the views you just created to control the position and size of your views. Otherwise, implement the viewWillLayoutSubviews and viewDidLayoutSubviews methods to adjust the frames of the subviews in the view hierarchy. See “Resizing the View Controller’s Views” (page 69). 4. Assign the root view to the view property of your view controller. Listing 4-2 shows an example implementation of the loadView method. This method creates a pair of custom views in a view hierarchy and assigns them to the view controller. Listing 4-2 Creating views programmatically - (void)loadView { CGRect applicationFrame = [[UIScreen mainScreen] applicationFrame]; UIView *contentView = [[UIView alloc] initWithFrame:applicationFrame]; contentView.backgroundColor = [UIColor blackColor]; self.view = contentView; levelView = [[LevelView alloc] initWithFrame:applicationFrame viewController:self]; [self.view addSubview:levelView]; } Note: When overriding the loadView method to create your views programmatically, you should not call super. Doing so initiates the default view-loading behavior and usually just wastes CPU cycles. Your own implementation of the loadView method should do all the work that is needed to create a root view and subviewsfor your view controller. For more information on the view loading process, see “A View Controller Instantiates Its View Hierarchy When Its View is Accessed” (page 57). Managing Memory Efficiently When it comes to view controllers and memory management, there are two issues to consider: ● How to allocate memory efficiently Resource Management in View Controllers Managing Memory Efficiently 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 61● When and how to release memory Although some aspects of memory allocation are strictly yours to decide, the UIViewController class provides some methods that usually have some connection to memory management tasks. Table 4-1 lists the places in your view controller object where you are likely to allocate or deallocate memory, along with information about what you should be doing in each place. Table 4-1 Places to allocate and deallocate memory Task Methods Discussion Your custom initialization method (whether it is named init or something else) is always responsible for putting your view controller object in a known good state. This includes allocating whatever data structures are needed to ensure proper operation. Allocating critical Initialization methods data structures required by your view controller Overriding the loadView method is required only if you intend to create your views programmatically. If you are using storyboards, the views are loaded automatically from the storyboard file. Creating your view loadView objects Although you are free to use other designs, consider using a pattern similar the loadView method. Create a property that holds the method and a matched method to initialize the object. When the property is read and its value is nil, call the associated load method. Custom properties and methods Creating custom objects Data objects are typically provided by configuring your view controller’s properties. Any additional data objects your view controller wants to create should be done by overriding the viewDidLoad method. By the time this method is called, your view objects are guaranteed to exist and to be in a known good state. Allocating or viewDidLoad loading data to be displayed in your view Use this method to deallocate all noncritical objects associated with your view controller. On iOS 6, you can also use this method to release references to view objects. didReceiveMemoryWarning Responding to low-memory notifications Resource Management in View Controllers Managing Memory Efficiently 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 62Task Methods Discussion Override this method only to perform any last-minute cleanup of your view controller class. Objects stored in instance variables and properties are automatically released; you do not need to release them explicitly. Releasing critical dealloc data structures required by your view controller On iOS 6 and Later, a View Controller Unloads Its Own Views When Desired The default behavior for a view controller is to load its view hierarchy when the view property is first accessed and thereafter keep it in memory until the view controller is disposed of. The memory used by a view to draw itself onscreen is potentially quite large. However, the system automatically releasesthese expensive resources when the view is not attached to a window. The remaining memory used by most views is small enough that it is not worth it for the system to automatically purge and recreate the view hierarchy. You can explicitly release the view hierarchy if that additional memory is necessary for your app. Listing 4-3 overrides the didReceiveMemoryWarning method to accomplish this. First, is calls the superclass’s implementation to get any required default behavior. Then, it cleans up the view controller’s resources. Finally, it teststo see if the view controller’s view is not onscreen. If the view is associated with a window, then it cleans up any of the view controller’s strong references to the view and its subviews. If the views stored data that needs to be recreated, the implementation of this method should save that data before releasing any of the references to those views. Listing 4-3 Releasing the views of a view controller not visible on screen - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Add code to clean up any of your own resources that are no longer necessary. if ([self.view window] == nil) { // Add code to preserve data stored in the views that might be // needed later. // Add code to clean up other strong references to the view in // the view hierarchy. self.view = nil; } Resource Management in View Controllers Managing Memory Efficiently 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 63The next time the view property is accessed, the view is reloaded exactly as it was the first time. On iOS 5 and Earlier, the System May Unload Views When Memory Is Low In earlier versions of iOS, the system automatically attempts to unload a view controller’s views when memory is low. The steps that occur during the unload cycle are as follows: 1. The app receives a low-memory warning from the system. 2. Each view controller calls its didReceiveMemoryWarning method. If you override this method, you should use it to release any memory or objects that your view controller object no longer needs. You must call super at some point in your implementation to ensure that the default implementation runs. On iOS 5 and earlier, the default implementation attempts to release the view. On iOS 6 and later, the default implementation exits. 3. If the view cannot be safely released (for example, it is visible onscreen), the default implementation exits. 4. The view controller calls its viewWillUnload method. A subclass typically overrides this method when it needs to save any view properties before the views are destroyed. 5. It sets its view property to nil. 6. The view controller callsits viewDidUnload method. A subclasstypically overridesthis method to release any strong references it has to those views. Resource Management in View Controllers Managing Memory Efficiently 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 64Figure 4-3 shows a visual representation of the unload cycle for a view controller. Figure 4-3 Unloading a view from memory Resource Management in View Controllers Managing Memory Efficiently 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 65When the visibility of a view controller’s view changes, the view controller callssome built-in methodsto notify subclasses of the changes. You can override these methodsto override how yoursubclassreactsto the change. For example, you can use these notifications to change the color and orientation of the status bar so that it matches the presentation style of the view that is about to be displayed. Responding When a View Appears Figure 5-1 shows the sequence of events that occurs when a view controller’s view is added to a window’s view hierarchy. The viewWillAppear: and viewDidAppear: methods give subclasses a chance to perform any additional actions related to the appearance of the view. Figure 5-1 Responding to the appearance of a view 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 66 Responding to Display-Related NotificationsResponding When a View Disappears Figure 5-2 shows the sequence of events that occurs when a view is removed from its window. When the view controller detects that its view is about to be removed or hidden, it calls the viewWillDisappear: and viewDidDisappear: methods to give subclasses a chance to perform any relevant tasks. Figure 5-2 Responding to the disappearance of a view Determining Why a View’s Appearance Changed Occasionally, it can be useful to know why a view is appearing or disappearing. For example, you might want to know whether a view appeared because it was just added to a container or whether it appeared because some other content that obscured it wasremoved. This particular example often appears when using navigation controllers; your content controller’s view may appear because the view controller was just pushed onto the navigation stack or it might appear because controllers previously above it were popped from the stack. The UIViewController class provides methods your view controller can call to determine why the appearance change occurred. Table 5-1 describes the methods and their usage. These methods can be called from inside your implementation of the viewWillAppear:, viewDidAppear:, viewWillDisappear: and viewDidDisappear: methods. Responding to Display-Related Notifications Responding When a View Disappears 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 67Table 5-1 Methods to call to determine why a view’s appearance changed Method Name Usage You call this method inside your viewWillDisappear: and viewDidDisappear: methodsto determine if the view controller’s view is being hidden because the view controller was removed from its container view controller. isMovingFromParentViewController You call this method inside your viewWillAppear: and viewDidAppear: methods to determine if the view controller’s view is being shown because the view controller was just added to a container view controller. isMovingToParentViewController You call this method inside your viewWillAppear: and viewDidAppear: methods to determine if the view controller’s view is being shown because the view controller was just presented by another view controller. isBeingPresented You call this method inside your viewWillDisappear: and viewDidDisappear: methodsto determine if the view controller’s view is being hidden because the view controller was just dismissed. isBeingDismissed Responding to Display-Related Notifications Determining Why a View’s Appearance Changed 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 68A view controller owns its own view and manages the view’s contents. In the process, the view controller also manages the view’s subviews. But in most cases, the view’s frame is not set directly by the view controller. Instead, the view’s frame is determined by how the view controller’s view is displayed. More directly, it is configured by the object used to display it. Other conditions in the app, such as the presence of the status bar, can also cause the frame to change. Because of this, your view controller should be prepared to adjust the contents of its view when the view’s frame changes. A Window Sets the Frame of Its Root View Controller’s View The view associated with the window’s root view controller gets a frame based on the characteristics of the window. The frame set by the window can change based on a number of factors: ● The frame of the window ● Whether or not the status bar is visible ● Whether or not the status bar is showing additional transient information (such as when a phone call is in progress) ● The orientation of the user interface (landscape or portrait) ● The value stored in the root view controller’s wantsFullScreenLayout property If your app displays the status bar, the view shrinks so that it does not underlap the status bar. After all, if the status bar is opaque, there is no way to see or interact with the content lying underneath it. However, if your app displays a translucentstatus bar, you can set the value of your view controller’s wantsFullScreenLayout property to YES to allow your view to be displayed full screen. The status bar is drawn over the top of the view. Full screen is useful when you want to maximize the amount of space available for displaying your content. When displaying content under the status bar, place that content inside a scroll view so that the user can scroll it out from under the status bar. Being able to scroll your content isimportant because the user cannot interact with content that is positioned behind the status bar or any other translucent views (such as translucent navigation bars and toolbars). Navigation bars automatically add a scroll content inset to your scroll view (assuming it is the root view of your view controller) to account for the height of the navigation bar; otherwise, you must manually modify the contentInset property of your scroll view. 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 69 Resizing the View Controller’s ViewsA Container Sets the Frames of Its Children’s Views When a view controller is a child of a container view controller, its parent decides which children are visible. When it wants to show the view, it adds it as a subview in its own view hierarchy and sets its frame to fit it into its user interface. For example: ● A tab view controller reserves space at the bottom of its view for the tab bar. It sets the currently visible child’s view to use the remainder of the space. ● A navigation view controller reserves space at the top for the navigation bar. If the currently visible child wants a navigation bar to be displayed, it also places a view at the bottom of the screen. The remainder of its view is given to the child to fill. A child gets its frame from the parent all the way up to the root view controller, which gets its frame from the window. A Presented View Controller Uses a Presentation Context When a view controller is presented by another view controller, the frame it receivesis based on the presentation context used to display the view controller. See “Presentation Contexts Provide the Area Covered by the Presented View Controller” (page 95). A Popover Controller Sets the Size of the Displayed View A view controller displayed by a popover controller can determine the size of its view’s area by setting its own contentSizeForViewInPopover property value to the size it wants. If the popover controller sets its own popoverContentSize property to a different view size, its size value overrides the view controller’s setting. To match the model used by other view controllers, use the popover controller’s properties to control its size and position. How View Controllers Participate in the View Layout Process When the size of a view controller’s view changes, its subviews are repositioned to fit the new space available to them. The views in the controller’s view hierarchy perform most of this work themselves through the use of layout constraints and autoresizing masks. However, the view controller is also called at various points so that it can participate in the process. Here’s what happens: 1. The view controller’s view is resized to the new size. Resizing the View Controller’s Views A Container Sets the Frames of Its Children’s Views 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 702. If autolayout is not in use, the views are resized according to their autoresizing masks. 3. The view controller’s viewWillLayoutSubviews method is called. 4. The view’s layoutSubviews method is called. If autolayout is used to configure the view hierarchy, it updates the layout constraints by executing the following steps: a. The view controller’s updateViewConstraints method is called. b. The UIViewController class’simplementation of the updateViewConstraints method callsthe view’s updateConstraints method. c. After the layout constraints are updated, a new layout is calculated and the views are repositioned. 5. The view controller’s viewDidLayoutSubviews method is called. Ideally, the views themselves perform all of the necessary work to reposition themselves, without requiring the view controller to participate in the process at all. Often, you can configure the layout entirely within Interface Builder. However, if the view controller adds and removes views dynamically, a static layout in Interface Builder may not be possible. In this case, the view controller is a good place to control the process, because often the views themselves only have a limited picture of the other views in the scene. Here are the best approaches to this in your view controller: ● Use layout constraints to automatically position the views (iOS 6 and later). You override updateViewConstraints to add any necessary layout constraints not already configured by the views. Your implementation of this method must call [super updateViewConstraints]. For more information on layout constraints, see Cocoa Auto Layout Guide . ● Use a combination of autoresizing masks and code to manually position the views (iOS 5.x). You override layoutSubviews and use it to reposition any views whose positions cannot be set automatically through the use of resizing masks. For more information on the autoresizing properties of views and how they affect the view, see View Programming Guide for iOS . Resizing the View Controller’s Views How View Controllers Participate in the View Layout Process 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 71View controllers are descendants of the UIResponder class and are therefore capable of handling all sorts of events. When a view does not respond to a given event, it passes that event to its superview, traveling up the view hierarchy all the way to the root view. However, if any view in the chain is managed by a view controller, it passes the event to the view controller object before passing it up to the superview. In this way, the view controller can respond to events that are not handled by its views. If the view controller does not handle the event, that event moves on to the view’s superview as usual. The Responder Chain Defines How Events Are Propagated to the App Figure 7-1 demonstrates the flow of events within a view hierarchy. Suppose you have a custom view that is embedded inside a screen-sized generic view object, which in turn is managed by your view controller. Touch events arriving in your custom view’s frame are delivered to that view for processing. If your view does not 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 72 Using View Controllers in the Responder Chainhandle an event, it is passed along to the parent view. Because the generic view does not handle events, it passes those events along to its view controller first. If the view controller does not handle the event, the event isfurther passed along to the superview of the generic UIView object, which in this case isthe window object. Figure 7-1 Responder chain for view controllers Note: The message-passing relationship between a view controller and its view is managed privately by the view controller and cannot be programmatically modified by your app. Although you might not want to handle touch events specifically in your view controller, you could use it to handle motion-based events. You might also use it to coordinate the setting and changing of the first responder. For more information about how events are distributed and handled in iOS apps, see Event Handling Guide for iOS . Using View Controllers in the Responder Chain The Responder Chain Defines How Events Are Propagated to the App 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 73The accelerometers in iOS–based devices make it possible to determine the current orientation of the device. By default, an app supports both portrait and landscape orientations. When the orientation of an iOS–based device changes, the system sends out a UIDeviceOrientationDidChangeNotification notification to let any interested parties know that the change occurred. By default, the UIKit framework listens for this notification and uses it to update your interface orientation automatically. This means that, with only a few exceptions, you should not need to handle this notification at all. When the user interface rotates, the window is resized to match the new orientation. The window adjusts the frame of its root view controller to match the new size, and this size in turn is propagated down the view hierarchy to other views. Thus, the simplest way to support multiple orientations in your view controller is to configure its view hierarchy so that the positions of subviews are updated whenever its root view’s frame changes. In most cases, you already need this behavior because other conditions may cause the view controller’s visible area to change. For more information on configuring your view layout,see “Resizing the View Controller’s Views” (page 69). If the default behavior is not what you want for your app, you can take control over: ● The orientations supported by your app. ● How a rotation between two orientations is animated onscreen. View controllers that do not fill the screen usually should not care about the orientation of the user interface. Instead, fill the area provided by the parent view controller. A root view controller (or a view controller presented full screen) is more likely to be interested in the orientation of the device. 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 74 Supporting Multiple Interface OrientationsControlling What Interface Orientations Are Supported (iOS 6) When UIKit receives an orientation notification, it usesthe UIApplication object and the root view controller to determine whether the new orientation is allowed. If both objects agree that the new orientation issupported, then the user interface is rotated to the new orientation. Otherwise the device orientation is ignored. When a view controller is presented over the root view controller, the system behavior changes in two ways. First, the presented view controller is used instead of the root view controller when determining whether an orientation is supported. Second, the presented view controller can also provide a preferred orientation. If the view controller is presented full screen, the user interface is presented in the preferred orientation. The user is expected to see that the orientation is different from the device orientation and rotate the device. A preferred orientation is most often used when the content must be presented in the new orientation. Declaring a View Controller’s Supported Interface Orientations A view controller that acts as the root view controller of the main window or is presented full screen on the main window can declare what orientations it supports. It does this by overriding the supportedInterfaceOrientations method. By default, view controllers on devices that use the iPad idiom support all four orientations. On devices that use the iPhone idiom, all interface orientations but upside-down portrait are supported. You should always choose the orientations your view supports at design time and implement your code with those orientationsin mind. There is no benefit to choosing which orientations you want to support dynamically based on runtime information. Even if your app did this, you would still have to implement the necessary code to support all possible orientations,so you might as well just choose to support the orientation or not up front. Listing 8-3 shows a fairly typical implementation of the supportedInterfaceOrientations method for a view controller that supports the portrait orientation and the landscape-left orientation. Your own implementation of this method should be just as simple. Listing 8-1 Implementing the supportedInterfaceOrientations method - (NSUInteger)supportedInterfaceOrientations { return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft; } Supporting Multiple Interface Orientations Controlling What Interface Orientations Are Supported (iOS 6) 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 75Dynamically Controlling Whether Rotation Occurs Sometimes you may want to dynamically disable automatic rotation. For example, you might do this when you want to suppress rotation completely for a short period of time. You must temporarily disable orientation changes you want to manually control the position of the status bar (such as when you call the setStatusBarOrientation:animated: method). If you want to temporarily disable automatic rotation, avoid manipulating the orientation masks to do this. Instead, override the shouldAutorotate method on the topmost view controller. This method is called before performing any autorotation. If it returns NO, then the rotation is suppressed. Declaring a Preferred Presentation Orientation When a view controller is presented full-screen to show its content, sometimes the content appears best when viewed in a particular orientation in mind. If the content can only be displayed in that orientation, then you simply return that as the only orientation from your supportedInterfaceOrientations method. If the view controller supports multiple orientations but appears better in a different orientation, you can provide a preferred orientation by overriding the preferredInterfaceOrientationForPresentation method. Listing 8-2 shows an example used by a view controller whose content should be presented in landscape orientation. The preferred interface orientation must be one of the orientationssupported by the view controller. Listing 8-2 Implementing the preferredInterfaceOrientationForPresentation method - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation { return UIInterfaceOrientationLandscapeLeft; } For more on presentation, see “Presenting View Controllers from Other View Controllers” (page 88). Declaring the App’s Supported Interface Orientations The easiest way to set an app’s app’s supported interface orientations is to edit the project’s Info.plist file. As in the case of the view controller, you define which of the four interface orientations are permitted. For more information, see Information Property List Key Reference . Supporting Multiple Interface Orientations Controlling What Interface Orientations Are Supported (iOS 6) 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 76If you restrict the app’s supported orientations, then those restrictions apply globally to all of the app’s view controllers, even when your app uses system view controllers. At any given time, the mask of the topmost view controller is logically ANDed with the app’s mask to determine what orientations are permitted. The result of this calculation must never be 0. If it is, the system throws a UIApplicationInvalidInterfaceOrientationException exception. Because the app’s mask is applied globally, use it sparingly. Important: The combination of the app and the view controller’s orientation masks must result in at least one useable orientation. An exception is thrown if there is no available orientation. Understanding the Rotation Process (iOS 5 and earlier) On iOS 5 and earlier, a view controller can sometimes participate in the rotation process even when it isn’t the topmost full-screen view controller. This generally occurs when a container view controller asks its children for their supported interface orientations. In practice, the ability for children to override the parents is rarely useful. With that in mind, you should consider emulating the iOS 6 behavior as much as possible in an app that must also support iOS 5: ● In a root view controller or a view controller that is presented full screen, choose a subset of interface orientations that make sense for your user interface. ● In a child controller, support all the default resolutions by designing an adaptable view layout. Declaring the Supported Interface Orientations To declare your supported interface orientations, override the shouldAutorotateToInterfaceOrientation:method and indicate which orientations your view supports. You should always choose the orientations your view supports at design time and implement your code with those orientationsin mind. There is no benefit to choosing which orientations you want to support dynamically based on runtime information. Even if you did so, you would still have to implement the necessary code to support all possible orientations, and so you might as well just choose to support the orientation or not up front. Listing 8-3 shows a fairly typical implementation of the shouldAutorotateToInterfaceOrientation: method for a view controller that supports the default portrait orientation and the landscape-left orientation. Your own implementation of this method should be just as simple. Supporting Multiple Interface Orientations Understanding the Rotation Process (iOS 5 and earlier) 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 77Listing 8-3 Implementing the shouldAutorotateToInterfaceOrientation: method - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orientation { if ((orientation == UIInterfaceOrientationPortrait) || (orientation == UIInterfaceOrientationLandscapeLeft)) return YES; return NO; } Important: You must always return YES for at least one interface orientation. If your app supports both landscape orientations, you can use the UIInterfaceOrientationIsLandscape macro as a shortcut, instead of explicitly comparing the orientation parameter against both landscape constants. The UIKit framework similarly defines a UIInterfaceOrientationIsPortrait macro to identify both variants of the portrait orientation. Responding to Orientation Changes in a Visible View Controller When a rotation occurs, the view controllers play an integral part of the process. Visible view controllers are notified at various stages of the rotation to give them a chance to perform additional tasks. You might use these methods to hide or show views, reposition or resize views, or notify other parts of your app about the orientation change. Because your custom methods are called during the rotation operation, you should avoid performing any time-consuming operations there. You should also avoid replacing your entire view hierarchy with a new set of views. There are better ways to provide unique views for different orientations, such as presenting a new view controller (as described in “Creating an Alternate Landscape Interface” (page 80)). The rotation methods are sent to the root view controller. The root view controller passes these events on as necessary to its children, and so on down the view controller hierarchy. Here is the sequence of events that occur when a rotation is triggered: 1. The window callsthe root view controller’s willRotateToInterfaceOrientation:duration:method. Container view controllers forward this message on to the currently displayed content view controllers. You can override this method in your custom content view controllersto hide views or make other changes to your view layout before the interface is rotated. Supporting Multiple Interface Orientations Responding to Orientation Changes in a Visible View Controller 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 782. The window adjusts the bounds of the view controller’s view. This causes the view to layout its subviews, triggering the view controller’s viewWillLayoutSubviews method. When this method runs, you can query the app object’s statusBarOrientation property to determine the current user interface layout. See “How View Controllers Participate in the View Layout Process” (page 70). 3. The view controller’s willAnimateRotationToInterfaceOrientation:duration: method is called. This method is called from within an animation block so that any property changes you make are animated at the same time as other animations that comprise the rotation. 4. The animation is executed. 5. The window calls the view controller’s didRotateFromInterfaceOrientation: method. Container view controllers forward this message to the currently displayed content view controllers. This action marks the end of the rotation process. You can use this method to show views, change the layout of views, or make other changes to your app. Figure 8-1 shows a visual representation of the preceding steps. It also shows how the interface looks at various stages of the process. Figure 8-1 Processing an interface rotation Supporting Multiple Interface Orientations Responding to Orientation Changes in a Visible View Controller 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 79Rotations May Occur When Your View Controller Is Hidden If your view controller’s contents are not onscreen when a rotation occurs, then it does not see the list of rotation messages. For example, consider the following sequence of events: 1. Your view controller presents another view controller’s contents full screen. 2. The user rotates the device so that the user interface orientation changes. 3. Your app dismisses the presented view controller. In this example, the presenting view controller was not visible when the rotation occurred, so it does not receive any rotation events. Instead, when it reappears, its views are simply resized and positioned using the normal view layout process. If your layout code needs to know the current orientation of the device, it can read the app object’s statusBarOrientation property to determine the current orientation. Creating an Alternate Landscape Interface If you want to present the same data differently based on whether a device is in a portrait or landscape orientation, the way to do so is using two separate view controllers. One view controller should manage the display of the data in the primary orientation (typically portrait), while the other manages the display of the data in the alternate orientation. Using two view controllers is simpler and more efficient than making major changes to your view hierarchy each time the orientation changes. It allows each view controller to focus on the presentation of data in one orientation and to manage things accordingly. It also eliminates the need to litter your view controller code with conditional checks for the current orientation. To support an alternate landscape interface, you must do the following: ● Implement two view controller objects. One to present a portrait-only interface, and the other to present a landscape-only interface. ● Register for the UIDeviceOrientationDidChangeNotification notification. In your handler method, present or dismiss the alternate view controller based on the current device orientation. Because view controllers normally manage orientation changesinternally, you have to tell each view controller to display itself in one orientation only. The implementation of the primary view controller then needsto detect device orientation changes and present the alternate view controller when the appropriate orientation change occurs. The primary view controller dismisses the alternate view controller when the orientation returns to the primary orientation. Supporting Multiple Interface Orientations Rotations May Occur When Your View Controller Is Hidden 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 80Listing 8-4 showsthe key methods you need to implement in a primary view controller thatsupports a portrait orientation. When the primary view controller is loaded from the storyboard, it registers to receive orientation-changed notifications from the shared UIDevice object. When such a notification arrives, the orientationChanged: method then presents or dismisses the landscape view controller depending on the current orientation. Listing 8-4 Presenting the landscape view controller @implementation PortraitViewController - (void)awakeFromNib { isShowingLandscapeView = NO; [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil]; } - (void)orientationChanged:(NSNotification *)notification { UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation; if (UIDeviceOrientationIsLandscape(deviceOrientation) && !isShowingLandscapeView) { [self performSegueWithIdentifier:@"DisplayAlternateView" sender:self]; isShowingLandscapeView = YES; } else if (UIDeviceOrientationIsPortrait(deviceOrientation) && isShowingLandscapeView) { [self dismissViewControllerAnimated:YES completion:nil]; isShowingLandscapeView = NO; } } Supporting Multiple Interface Orientations Creating an Alternate Landscape Interface 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 81Tips for Implementing Your Rotation Code Depending on the complexity of your views, you may need to write a lot of code to support rotations—or no code at all. When figuring out what you need to do, you can use the following tips as a guide for writing your code. ● Disable event delivery temporarily during rotations. Disabling event delivery for your views prevents unwanted code from executing while an orientation change is in progress. ● Store the visible map region. If your app contains a map view, save the visible map region value prior to beginning any rotations. When the rotations finish, use the saved value as needed to ensure that the displayed region is approximately the same as before. ● For complex view hierarchies, replace your views with a snapshot image. If animating large numbers of views is causing performance issues, temporarily replace those views with an image view containing an image of the viewsinstead. After the rotations are complete, reinstall your views and remove the image view. ● Reload the contents of any visible tables after a rotation. Forcing a reload operation when the rotations are finished ensures that any new table rows exposed are filled appropriately. ● Use rotation notifications to update your app’s state information. If your app usesthe current orientation to determine how to present content, use the rotation methods of your view controller (or the corresponding device orientation notifications) to note those changes and make any necessary adjustments. Supporting Multiple Interface Orientations Tips for Implementing Your Rotation Code 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 82Aside from managing a view’s behavior, a view controller can also help control an app’s accessibility. An accessible app is one that can be used by everyone, regardless of disability or physical impairment, while retaining its functionality and usability as a helpful tool. To be accessible, an iOS app must supply information about its user interface elements to VoiceOver users. VoiceOver, a screen-reading technology designed to assist the visually impaired, speaks aloud text, images, and UI controls displayed the screen, so that people who cannot see can still interact with these elements. UIKit objects are accessible by default, but there are still things you can do from the view controller’s perspective to address accessibility. At a high level, this means you should make sure that: ● Every user interface element users can interact with is accessible. Thisincludes elementsthat merely supply information, such as static text, as well as controls that perform actions. ● All accessible elements supply accurate and helpful information. In addition to these fundamentals, a view controller can enhance the VoiceOver user’s experience by setting the position of the VoiceOver focus ring programmatically, responding to special VoiceOver gestures, and observing accessibility notifications. Moving the VoiceOver Cursor to a Specific Element When the layout of a screen changes, the VoiceOver focus ring, also known as the VoiceOver cursor, resets its position to the first element displayed on the screen from left to right and top to bottom. You might decide to change the first element the VoiceOver cursor lands on when views are presented onscreen. For example, when a navigation controller pushes a view controller onto the navigation stack, the VoiceOver cursor falls on the Back button of the navigation bar. Depending on your app, it might make more sense to move it to the heading of the navigation bar instead, or to any other element. To do so, call UIAccessibilityPostNotification using both the notification UIAccessibilityScreenChangedNotification (which tells VoiceOver that the contents of the screen has changed) and the element you’d like to give focus to, as shown in Listing 9-1. 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 83 Accessibility from the View Controller’s PerspectiveListing 9-1 Posting an accessibility notification can change the first element read aloud @implementation MyViewController - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, self.myFirstElement); } @end If only the layout changes rather than the contents of the screen, such as when switching from portrait to landscape mode, use the notification UIAccessibilityLayoutChangedNotification instead of UIAccessibilityScreenChangedNotification. Note: Device rotation triggers a layout change, which resets the VoiceOver cursor’s position. Responding to Special VoiceOver Gestures There are special gestures that VoiceOver users can perform to trigger custom actions. These gestures are special because you are allowed to define their behavior, unlike standard VoiceOver gestures. You can detect the gestures by overriding certain methods in your views or view controllers. A gesture first checks the view that has VoiceOver focus for instruction and continues up the responder chain until it finds an implementation of the corresponding VoiceOver gesture method. If no implementation is found, the system default action for that gesture is triggered. For example, the Magic Tap gesture plays and pauses music playback from the Music app if no Magic Tap implementation is found from the current view to the app delegate. Although you can provide any custom logic you want, VoiceOver users expect the actions of these special gestures to follow certain guidelines. Like any gesture, your implementation of a VoiceOver gesture should follow a pattern so that interaction with an accessible app remains intuitive. There are five special VoiceOver gestures: ● Escape. A two-finger Z-shaped gesture that dismisses a modal dialog, or goes back one level in a navigation hierarchy. Accessibility from the View Controller’s Perspective Responding to Special VoiceOver Gestures 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 84● Magic Tap. A two-finger double-tap that performs the most-intended action. ● Three-Finger Scroll. A three-finger swipe that scrolls content vertically or horizontally. ● Increment and Decrement. A one-finger swipe up or down that adds or subtracts a given value from an element with the adjustable trait. Elements with the Adjustable accessibility trait must implement these methods. Note: All special VoiceOver gesture methods return a Boolean value that determine whether to propagate through the responder chain. To halt propagation, return YES; otherwise, return NO. Escape If you present a view that overlays content—such as a modal dialog or an alert—you should override the accessibilityPerformEscape method to dismiss the overlay. The function of the Escape gesture is like the function of the Esc key on a computer keyboard; it cancels a temporary dialog or sheet to reveal the main content. Another use case to override the Escape gesture would be to go back up one level in a navigation hierarchy. UINavigationController implements this functionality by default. If you’re designing your own kind of navigation controller, you should set the Escape gesture to traverse up one level of your navigation stack, because that is the functionality VoiceOver users expect. Magic Tap The purpose of the Magic Tap gesture isto quickly perform an often-used or most-intended action. For example, in the Phone app, it picks up or hangs up a phone call. In the Clock app, it starts and stops the stopwatch. If you want an action to fire from a gesture regardless of the view the VoiceOver cursor is on, you should implement the accessibilityPerformMagicTap method in your view controller. Note: If you’d like the Magic Tap gesture to perform the same action from anywhere within your app, it is more appropriate to implement the accessibilityPerformMagicTap method in your app delegate. Three-Finger Scroll The accessibilityScroll: method fires when a VoiceOver user performs a three-finger scroll. It accepts a UIAccessibilityScrollDirection parameter from which you can determine the direction of the scroll. If you have a custom scrolling view, it may be more appropriate to implement this on the view itself. Accessibility from the View Controller’s Perspective Responding to Special VoiceOver Gestures 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 85Increment and Decrement The accessibilityIncrement and accessibilityDecrement methods are required for elements with the adjustable trait and should be implemented on the views themselves. Observing Accessibility Notifications You can listen for accessibility notifications to trigger callback methods. Under certain circumstances, UIKit fires accessibility notifications which your app can observe to extend its accessible functionality. For example, if you listen for the notification UIAccessibilityAnnouncementDidFinishNotification, you can trigger a method to follow up the completion of VoiceOver’s speech. Apple does this in the iBooks app. iBooks fires a notification when VoiceOver finishes speaking a line in a book that triggers the next line to be spoken. If it is the last line on the page, the logic in the callback tells iBooks to turn the page and continue reading as soon as the last line ends speaking. This allows for a line-by-line degree of granularity for navigating text while providing a seamless, uninterrupted reading experience. To register as an observer for accessibility notifications, use the default notification center. Then create a method with the same name that you provide for the selector argument, as shown in Listing 9-2. Listing 9-2 Registering as an observer for accessibility notifications @implementation MyViewController - (void)viewDidLoad { [super viewDidLoad]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didFinishAnnouncement:) name:UIAccessibilityAnnouncementDidFinishNotification object:nil]; } - (void)didFinishAnnouncement:(NSNotification *)dict { NSString *valueSpoken = [[dict userInfo] objectForKey:UIAccessibilityAnnouncementKeyStringValue]; Accessibility from the View Controller’s Perspective Observing Accessibility Notifications 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 86NSString *wasSuccessful = [[dict userInfo] objectForKey:UIAccessibilityAnnouncementKeyWasSuccessful]; // ... } @end UIAccessibilityAnnouncementDidFinishNotification expects an NSNotification dictionary as a parameter from which you can determine the value spoken and whether or not the speaking has completed uninterrupted. Speaking may become interrupted if the VoiceOver user performs the stop speech gesture or swipes to another element before the announcement finishes. Another helpful notification to subscribe to is UIAccessibilityVoiceOverStatusChanged. It can detect when VoiceOver becomes toggled on or off. If VoiceOver is toggled outside of your app, you receive the notification when your app is brought back into the foreground. Because UIAccessibilityVoiceOverStatusChanged doesn’t expect any parameters, the method in your selector doesn’t need to append a trailing colon (:). For a full list of possible notifications you can observe, consult“Notifications”in UIAccessibility Protocol Reference . Remember that you may only observe the notifications that can be posted by UIKit, which are NSString objects, and not notifications that can be posted by your app, which are of type int. Accessibility from the View Controller’s Perspective Observing Accessibility Notifications 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 87The ability to present view controllers is a tool that you have at your disposal for interrupting the current workflow and displaying a new set of views. Most commonly, an app presents a view controller as a temporary interruption to obtain important information from the user. However, you can also use presented view controllers to implement alternate interfaces for your app at specific times. How View Controllers Present Other View Controllers A presented view controller is not a specific subclass of UIViewController (as UITabBarController or UINavigationController is). Instead, any view controller can be presented by your app. However, like tab bar and navigation controllers, you present view controllers when you want to convey a specific meaning about the relationship between the previous view hierarchy and the newly presented view hierarchy. When you present a modal view controller, the system creates a relationship between the view controller that did the presenting and the view controller that was presented. Specifically, the view controller that did the presenting updates its presentedViewController property to point to its presented view controller. 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 88 Presenting View Controllers from Other View ControllersSimilarly, the presented view controller updates its presentingViewController property to point back to the view controller that presented it. Figure 10-1 showsthe relationship between the view controller managing the main screen in the Calendar app and the presented view controller used to create new events. Figure 10-1 Presented views in the Calendar app. Any view controller object can present a single view controller at a time. This is true even for view controllers that were themselves presented by another view controller. In other words, you can chain presented view controllers together, presenting new view controllers on top of other view controllers as needed. Figure 10-2 shows a visual representation of the chaining process and the actions that initiate it. In this case, when the user taps the icon in the camera view, the app presents a view controller with the user’s photos. Tapping the action button in the photo library’s toolbar prompts the user for an appropriate action and then presents Presenting View Controllers from Other View Controllers How View Controllers Present Other View Controllers 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 89another view controller (the people picker) in response to that action. Selecting a contact (or canceling the people picker) dismisses that interface and takes the user back to the photo library. Tapping the Done button then dismisses the photo library and takes the user back to the camera interface. Figure 10-2 Creating a chain of modal view controllers Camera view controller Photo library navigation controller Action sheet People picker navigation controller present modally present modally Each view controller in a chain of presented view controllers has pointers to the other objects surrounding it in the chain. In other words, a presented view controller that presents another view controller has valid objects in both its presentingViewController and presentedViewController properties. You can use these relationships to trace through the chain of view controllers as needed. For example, if the user cancels the current operation, you can remove all objects in the chain by dismissing the first presented view controller. Dismissing a view controller dismisses not only that view controller but also any view controllers it presented. In Figure 10-2 (page 90), a point worth noting is that the presented view controllers are both navigation controllers. You can present UINavigationController objects in the same way that you would present a content view controller. When presenting a navigation controller, you always present the UINavigationController object itself, rather than presenting any of the view controllers on its navigation stack. However, individual view controllers on the navigation stack may present other view controllers, including other navigation controllers. Figure 10-3 Presenting View Controllers from Other View Controllers How View Controllers Present Other View Controllers 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 90shows more detail of the objects that are involved in the preceding example. As you can see, the people picker is not presented by the photo library navigation controller but by one of the content view controllers on its navigation stack. Figure 10-3 Presenting navigation controllers modally Presentation Styles for Modal Views For iPad apps, you can present content using several different styles. In iPhone apps, presented views always cover the visible portion of the window, but when running on an iPad, view controllers use the value in their modalPresentationStyle property to determine their appearance when presented. Different options for this property allow you to present the view controller so that it fills all or only part of the screen. Presenting View Controllers from Other View Controllers Presentation Styles for Modal Views 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 91Figure 10-4 shows the core presentation styles that are available. (The UIModalPresentationCurrentContext style lets a view controller adopt the presentation style of its parent.) In each presentation style, the dimmed areas show the underlying content but do not allow taps in that content. Therefore, unlike a popover, your presented views must still have controls that allow the user to dismiss the view. Figure 10-4 iPad presentation styles For guidance on when to use the different presentation styles, see “Popover (iPad Only)” in iOS Human Interface Guidelines. Presenting View Controllers from Other View Controllers Presentation Styles for Modal Views 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 92Presenting a View Controller and Choosing a Transition Style When a view controller is presented using a storyboard segue, it is automatically instantiated and presented. The presenting view controller can configure the destination view controller before it is presented. For more information, see “Configuring the Destination Controller When a Segue is Triggered” (page 101). If you need to present a view controller programmatically, you must do the following: 1. Create the view controller you want to present. 2. Set the modalTransitionStyle property of the view controller to the desired value. 3. Assign a delegate object to the view controller. Typically, the delegate is the presenting view controller. The delegate is used by the presented view controllers to notify the presenting view controller when it is ready to be dismissed. It may also communicate other information back to the delegate. 4. Call the presentViewController:animated:completion: method of the current view controller, passing in the view controller you want to present. The presentViewController:animated:completion: method presents the view for the specified view controller object and configures the presenting-presented relationships between the new view controller and the current view controller. Unless you are restoring your app to some previous state, you usually want to animate the appearance of the new view controller. The transition style you should use depends on how you plan to use the presented view controller. Table 10-1 lists the transition styles you can assign to the modalTransitionStyle property of the presented view controller and describes how you might use each one. Table 10-1 Transition styles for modal view controllers Transition style Usage Use this style when you want to interrupt the current workflow to gather information from the user. You can also use it to present content that the user might or might not modify. For thisstyle of transition, content view controllersshould provide buttons to dismissthe view controller explicitly. Typically, these are a Done button and an optional Cancel button. If you do not explicitly set a transition style, this style is used by default. UIModalTransitionStyleCoverVertical Use thisstyle to change the work mode of your app temporarily. The most common usage for this style is to display settings that might change frequently, such as in the Stocks and Weather apps. These settings can be meant for the entire app or they can be specific to the current screen. For this style of transition, you usually provide some sort of button to return the user to the normal running mode of your app. UIModalTransitionStyleFlipHorizontal Presenting View Controllers from Other View Controllers Presenting a View Controller and Choosing a Transition Style 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 93Transition style Usage Use this style to present an alternate interface when the device changes orientations. In such a case, your app is responsible for presenting and dismissing the alternate interface in response to orientation change notifications. Media-based apps can also use this style to fade in screens displaying media content. For an example of how to implement an alternate interface in response to device orientation changes, see “Creating an Alternate Landscape Interface” (page 80). UIModalTransitionStyleCrossDissolve Listing 10-1 shows how to present a view controller programmatically. When the user adds a new recipe, the app promptsthe user for basic information about the recipe by presenting a navigation controller. A navigation controller was chosen so that there would be a standard place to put a Cancel and Done button. Using a navigation controller also makes it easier to expand the new recipe interface in the future. All you would have to do is push new view controllers on the navigation stack. Listing 10-1 Presenting a view controller programmatically - (void)add:(id)sender { // Create the root view controller for the navigation controller // The new view controller configures a Cancel and Done button for the // navigation bar. RecipeAddViewController *addController = [[RecipeAddViewController alloc] init]; // Configure the RecipeAddViewController. In this case, it reports any // changes to a custom delegate object. addController.delegate = self; // Create the navigation controller and present it. UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:addController]; [self presentViewController:navigationController animated:YES completion: nil]; } Presenting View Controllers from Other View Controllers Presenting a View Controller and Choosing a Transition Style 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 94When the user taps either the Done or the Cancel button from the new recipe entry interface, the app dismisses the view controller and returns the user to the main view. See “Dismissing a Presented View Controller” (page 95). Presentation Contexts Provide the Area Covered by the Presented View Controller The area of the screen used to define the presentation area is determined by the presentation context. By default, the presentation context is provided by the root view controller, whose frame is used to define the frame of the presentation context. However, the presenting view controller, or any other ancestor in the view controller hierarchy, can choose to provide the presentation context instead. In that case, when another view controller provides the presentation context, its frame is used instead to determine the frame of the presented view. This flexibility allows you to limit the modal presentation to a smaller portion of the screen, leaving other content visible. When a view controller is presented, iOS searches for a presentation context. It starts at the presenting view controller by reading its definesPresentationContext property. If the value of this property is YES, then the presenting view controller defines the presentation context. Otherwise, it continues up through the view controller hierarchy until a view controller returns YES or until it reaches the window’s root view controller. When a view controller defines a presentation context, it can also choose to define the presentation style. Normally, the presented view controller determines how it presented using its modalTransitionStyle property. A view controller that sets definesPresentationContext to YES can also set providesPresentationContextTransitionStyle to YES. If providesPresentationContextTransitionStyle is set to YES, iOS uses the presentation context’s modalPresentationStyle to determine how the new view controller is presented. Dismissing a Presented View Controller When it comes time to dismiss a presented view controller, the preferred approach is to let the presenting view controller dismiss it. In other words, whenever possible, the same view controller that presented the view controller should also take responsibility for dismissing it. Although there are several techniques for notifying the presenting view controller that its presented view controller should be dismissed, the preferred technique is delegation. For more information, see “Using Delegation to Communicate with Other Controllers” (page 103). Presenting View Controllers from Other View Controllers Presentation Contexts Provide the Area Covered by the Presented View Controller 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 95Presenting Standard System View Controllers A number of standard system view controllers are designed to be presented by your app. The basic rules for presenting these view controllers are the same asthe rulesfor presenting your custom content view controllers. However, because your app does not have accessto the view hierarchy managed by the system view controllers, you cannotsimply implement actionsfor the controlsin the views. Interactions with the system view controllers typically take place through a delegate object. Each system view controller defines a corresponding protocol, whose methods you implement in your delegate object. Each delegate usually implements a method to either accept whatever item was selected or cancel the operation. Your delegate object should always be ready to handle both cases. One of the most important things the delegate must do is dismiss the presented view controller by calling the dismissModalViewControllerAnimated: method of the view controller that did the presenting (in other words, the parent of the presented view controller.) Table 10-2 lists several of the standard system view controllers found in iOS. For more information about each of these classes, including the features it provides, see the corresponding class reference documentation. Table 10-2 Standard system view controllers Framework View controllers ABNewPersonViewController ABPeoplePickerNavigationController ABPersonViewController ABUnknownPersonViewController Address Book UI EKEventEditViewController EKEventViewController Event Kit UI GKAchievementViewController GKLeaderboardViewController GKMatchmakerViewController GKPeerPickerController GKTurnBasedMatchmakerViewController Game Kit MFMailComposeViewController MFMessageComposeViewController Message UI MPMediaPickerController MPMoviePlayerViewController Media Player Presenting View Controllers from Other View Controllers Presenting Standard System View Controllers 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 96Framework View controllers UIImagePickerController UIVideoEditorController UIKit Note: Although the MPMoviePlayerController class in the Media Player framework might technically be thought of as a modal controller, the semantics for using it are slightly different. Instead of presenting the view controller yourself, you initialize it and tell it to play its media file. The view controller then handles all aspects of presenting and dismissing its view. (However, the MPMoviePlayerViewController class can be used instead of MPMoviePlayerController as a standard view controller for playing movies.) Presenting View Controllers from Other View Controllers Presenting Standard System View Controllers 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 97Few iOS apps show only a single screenful of content. Instead, they show some content when first launched and then show and hide other content in response to user actions. These transitions provide a single unified user interface that display a lot of content, just not all at once. By convention,smaller pieces of content are managed by different view controller classes. This coding convention allows you to create smaller and simpler controller classes that are easy to implement. However, dividing the work between multiple classesimposes additional requirements on your class designs. To maintain the illusion of a single interface, your view controllers must exchange messages and data to coordinate transitions from controller to another. Thus, even as your view controller classes look inwards to control views and perform the tasks assigned to them, they also look outwards to communicate with other collaborating view controllers. When Coordination Between View Controllers Occurs Communication between view controllers is tied to the role those view controllers play in your app. It would be impossible to describe all of the possible interactions between view controllers, because the number and nature of these relationships is dependent on the design of your app. However, it is possible to describe when these interactions occur and to give some examples of the kinds of coordination that might take place in your app. The lifetime of a view controller has three stages during which it might coordinate with other objects: View controller instantiation. In this stage, when a view controller is created, an existing view controller or another object was responsible for its creation. Usually, this object knows why the view controller was created and what task itshould perform. Thus, after a view controller isinstantiated, thisintent must be communicated to it. The exact details of this initial configuration vary. Sometimes, the existing view controller passes data objects to the new controller. At other times, it may configure the presentation style for that, or establish lasting links between the two view controllers. These links allow further communication later in the view controller’slifetime. During the view controller’s lifetime. In this stage, some view controllers communicate with other view controllers during their lifetime. The recipient of these messages could be the view controller that created it, peers with similar lifetimes, or even a new view controller that it itself created. Here are a few common designs: 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 98 Coordinating Efforts Between View Controllers● The view controllersends notificationsthat the user performed a specific action. Because thisis a notification, the object receiving this message is just being notified that something happened. ● The view controllersends data to another view controller. For example, a tab bar controller doesn’t establish a built-in relationship between its children, but your app might establish such a relationship when the tabs are displaying the same data object, just in different ways. When a user leaves one tab, the view controller associated with that tab sends the selection information to the view controller about to be displayed. In return, the new view controller uses this data to configure its views so that the transition appears seamless. In this particular case, no new view controller is instantiated by the action. Instead, the two view controllers are peers with the same lifetime and can continue to coordinate as the user switches between them. ● A view controller sends messages to give another view controller authority over its actions. For example, if a view controller allows usersto enter data, it mightsend messagesto allow another controller to decide whether the data the user entered is valid. If the data is invalid, the view controller can disallow the user from accepting the invalid data or adjust its interface to display an error. View controller destruction. In this stage, many view controllers send messages when their task completes. These messages are common because the convention is for the controller that created a view controller to also release it. Sometimes, these messages simply convey that the user finished the task. At other times, such as when the task being performed generated new data objects, the message communicatesthe new data back to another controller. During a view controller’s lifetime, it is common for it to exchange information with other view controllers. These messages are used to notify other controllers when things happen, send them data, or even ask them to exert control over the controller’s activities. With Storyboards, a View Controller is Configured When It Is Instantiated Storyboards provide direct support for configuring newly instantiated controllers before they are displayed. When a storyboard instantiates new view controllers automatically, it calls an object in your app to allow it to configure the new controller or to create links to or from the new controller. When your app first launches, the app delegate configures the initial view controller. When a segue is triggered, the source view controller configures the destination view controller. There are a few conventions used to implement destination view controllers: ● A destination view controller exposes properties and methods used to configure it. Coordinating Efforts Between View Controllers With Storyboards, a View Controller is Configured When It Is Instantiated 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 99● A destination view controller communicates as little as possible with view controllers that it did not create personally. When it does so, these communication paths should use delegation. The destination view controller’s delegate is configured as one of its properties. Carefully following these conventions helps organize your configuration code and carefully limitsthe direction of dependencies between view controller classes in your app. By isolating dependencies in your app, you increase the opportunity for code reuse. You also design view controllers that are easier to test in isolation from the rest of your app. Configuring the Initial View Controller at Launch If you define a main storyboard in your project, iOS automatically does a lot of work for you to set up your app. When your app calls the UIApplicationMain function, iOS performs the following actions: 1. It instantiates the app delegate based on the class name you passed into the UIApplicationMain function. 2. It creates a new window attached to the main screen. 3. If your app delegate implements a window property, iOS sets this property to the new window. 4. It loads the main storyboard referenced in the app’s information property list file. 5. It instantiates the main storyboard’s initial view controller. 6. It sets the window’s rootViewController property to the new view controller. 7. It calls the app delegate’s application:didFinishLaunchingWithOptions: method. Your app delegate is expected to configure the initial view controller (and its children, if it is a container view controller). 8. It calls the window’s makeKeyAndVisible method to display the window. Listing 11-1 shows an implementation of the application:didFinishLaunchingWithOptions: method from the Your Second iOS App: Storyboards tutorial. In this example, the storyboard’s initial view controller is a navigation controller with a custom content controller that displays the master view. The code first retrieves references to the view controller it is interested in. Then, it performs any configuration that could not be performed in Interface Builder. In this example, a custom data controller object is provided to the master view controller by a custom data controller object. Listing 11-1 The app delegate configures the controller - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { Coordinating Efforts Between View Controllers With Storyboards, a View Controller is Configured When It Is Instantiated 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 100UINavigationController *navigationController = (UINavigationController*) self.window.rootViewController; BirdsMasterViewController * firstViewController = [[navigationController viewControllers] objectAtIndex:0]; BirdSightingDataController *dataController = [[BirdSightingDataController alloc] init]; firstViewController.dataController = dataController; return YES; } If your project does not identify the main storyboard, the UIApplicationMain function creates the app delegate and calls it but does not perform any of the other steps described earlier. You would need to write code to perform those steps yourself. Listing 11-2 shows the code you might implement if you needed to perform these steps programmatically. Listing 11-2 Creating the window when a main storyboard is not being used - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MyStoryboard" bundle:nil]; MainViewController *mainViewController = [storyboard instantiateInitialViewController]; self.window.rootViewController = mainViewController; // Code to configure the view controller goes here. [self.window makeKeyAndVisible]; return YES; } Configuring the Destination Controller When a Segue is Triggered iOS performs the following tasks when a segue is triggered: Coordinating Efforts Between View Controllers With Storyboards, a View Controller is Configured When It Is Instantiated 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 1011. It instantiates the destination view controller. 2. It instantiates a new segue object that holds all the information for the segue being triggered. Note: A popover segue also provides a property that identifies the popover controller used to control the destination view controller. 3. It callsthe source view controller’s prepareForSegue:sender: method, passing in the new segue object and the object that triggered the segue. 4. It callsthe segue’s perform method to bring the destination controller onto the screen. The actual behavior depends on the kind ofsegue being performed. For example, a modalsegue tellsthe source view controller to present the destination view controller. 5. It releases the segue object and the segue is complete. The source view controller’s prepareForSegue:sender: method performs any necessary configuration of the destination view controller’s properties, including a delegate if the destination view controller implements one. Listing 11-3 shows an implementation of the prepareForSegue:sender: method from the Your Second iOS App: Storyboards tutorial. Listing 11-3 Configuring the destination controller in a segue - (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if ([[segue identifier] isEqualToString:@"ShowSightingsDetails"]) { DetailViewController *detailViewController = [segue destinationViewController]; detailViewController.sighting = [self.dataController objectInListAtIndex:[self.tableView indexPathForSelectedRow].row]; } if ([[segue identifier] isEqualToString:@"ShowAddSightingView"]) { AddSightingViewController *addSightingViewController = [[[segue destinationViewController] viewControllers] objectAtIndex:0]; addSightingViewController.delegate = self; Coordinating Efforts Between View Controllers With Storyboards, a View Controller is Configured When It Is Instantiated 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 102} } This implementation, from the master view controller for the app, actually handles two different segues configured in the storyboard. It distinguishes between the two segues using the segue’s identifier property. In both cases, it follows the coding convention established earlier, by first retrieving the view controller and then configuring it. When the segue is to the detail view controller, the segue occurred because the user selected a row in the table view. In this case, the code transfers enough data to the destination view controllerso that the destination view controller can display the sighting. The code uses the user’s selection to retrieve a sighting object from the master view controller’s data controller. It then assigns this sighting to the destination controller. In the other case, the new view controller allows the user to add a new bird sighting. No data needs to be sent to this view controller. However, the master view controller needs to receive data when the user finishes entering the data. To receive that information, the source view controller implements the delegate protocol defined by the Add view controller (notshown here) and makesitself the destination view controller’s delegate. Using Delegation to Communicate with Other Controllers In a delegate-based model, the view controller defines a protocol for its delegate to implement. The protocol defines methods that are called by the view controller in response to specific actions, such as taps in a Done button. The delegate is then responsible for implementing these methods. For example, when a presented view controller finishesitstask, itsends a message to the presenting view controller and that controller dismisses it. Using delegation to manage interactions with other app objects has key advantages over other techniques: ● The delegate object has the opportunity to validate or incorporate changes from the view controller. ● The use of a delegate promotes better encapsulation because the view controller does not have to know anything about the class of the delegate. This enables you to reuse that view controller in other parts of your app. To illustrate the implementation of a delegate protocol, consider the recipe view controller example that was used in “Presenting a View Controller and Choosing a Transition Style” (page 93). In that example, a recipes app presented a view controller in response to the user wanting to add a new recipe. Prior to presenting the view controller, the current view controller made itself the delegate of the RecipeAddViewController object. Listing 11-4 shows the definition of the delegate protocol for RecipeAddViewController objects. Coordinating Efforts Between View Controllers Using Delegation to Communicate with Other Controllers 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 103Listing 11-4 Delegate protocol for dismissing a presented view controller @protocol RecipeAddDelegate // recipe == nil on cancel - (void)recipeAddViewController:(RecipeAddViewController *)recipeAddViewController didAddRecipe:(MyRecipe *)recipe; @end When the user taps the Cancel or Done button in the new recipe interface, the RecipeAddViewController object calls the preceding method on its delegate object. The delegate is then responsible for deciding what course of action to take. Listing 11-5 shows the implementation of the delegate method that handles the addition of new recipes. This method is implemented by the view controller that presented the RecipeAddViewController object. If the user accepted the new recipe—that is, the recipe object is not nil—this method addsthe recipe to itsinternal data structures and tells its table view to refresh itself. (The table view subsequently reloads the recipe data from the same recipesController object shown here.) Then the delegate method dismisses the presented view controller. Listing 11-5 Dismissing a presented view controller using a delegate - (void)recipeAddViewController:(RecipeAddViewController *)recipeAddViewController didAddRecipe:(Recipe *)recipe { if (recipe) { // Add the recipe to the recipes controller. int recipeCount = [recipesController countOfRecipes]; UITableView *tableView = [self tableView]; [recipesController insertObject:recipe inRecipesAtIndex:recipeCount]; [tableView reloadData]; } [self dismissViewControllerAnimated:YES completion: nil]; } Coordinating Efforts Between View Controllers Using Delegation to Communicate with Other Controllers 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 104Guidelines for Managing View Controller Data Carefully managing how data and control flows between your view controllersis critical to understanding how your app operates and avoiding subtle errors. Consider the following guidelines when designing your view controllers: ● A destination view controller’s references to app data should come from the source view controller unless the destination view controller represents a self-contained (and therefore self-configuring) view controller. ● Perform as much configuration as possible using Interface Builder, rather than configuring your controller programmatically in your code. ● Always use a delegate to communicate information back to other controllers. Your content view controller should never need to know the class of the source view controller or any controllers it doesn’t create. ● Avoid unnecessary connections to objects external to your view controller. Each connection represents a dependency that makes it harder to change your app design. For example, the children of a navigation controller should be aware of the parent navigation controller and of the siblings immediately above and below them on the stack. They rarely need to communicate with other siblings. Coordinating Efforts Between View Controllers Guidelines for Managing View Controller Data 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 105You can use the same view controller both to display and to edit content. When the editing mode is toggled, your custom view controller performs the necessary work to transition its view from a display mode to an editing mode (or vice versa). Toggling Between Display and Edit Mode To allow a custom view controller class to be used to both display and edit content, override the setEditing:animated: method. When called, your implementation of this method should add, hide, and adjust the view controller’s views to match the specified mode. For example, you might want to change the content or appearance of views to convey that the view is now editable. If your view controller manages a table, you can also call the table’s own setEditing:animated: method in order to put the table into the appropriate mode. 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 106 Enabling Edit Mode in a View ControllerNote: You typically do not swap out your entire view hierarchy when toggling back and forth between display and edit modes. The point of using the setEditing:animated: method is so that you can make small changes to existing views. If you would prefer to display a new set of views for editing, you should either present a new view controller or use a navigation controller to present the new views. Figure 12-1 shows a view from the Contacts app that supports in-place editing. Tapping the Edit button in the upper-right corner tells the view controller to update itself for editing; the Done button returns the user to display mode. In addition to modifying the table, the view also changes the content of the image view and the view displaying the user’s name. It also configures the assorted views and cells so that tapping them edits their contents instead of performing other actions. Figure 12-1 Display and edit modes of a view The implementation of your own setEditing:animated: method is relatively straightforward—you check to see which mode your view controller is entering and adjust the contents of your view accordingly. - (void)setEditing:(BOOL)flag animated:(BOOL)animated { Enabling Edit Mode in a View Controller Toggling Between Display and Edit Mode 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 107[super setEditing:flag animated:animated]; if (flag == YES){ // Change views to edit mode. } else { // Save the changes if needed and change the views to noneditable. } } Presenting Editing Options to the User A common place in which to use an editable view is in a navigation interface. When implementing your navigation interface, you can include a special Edit button in the navigation bar when your editable view controller is visible. (You can get this button by calling the editButtonItem method of your view controller.) When tapped, this button automatically toggles between an Edit and Done button and calls your view controller’s setEditing:animated: method with appropriate values. You can also call this method from your own code (or modify the value of your view controller’s editing property) to toggle between modes. For more information about adding an Edit button to a navigation bar, see View Controller Catalog for iOS . Enabling Edit Mode in a View Controller Presenting Editing Options to the User 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 108Interface Builder provides segues for all of the standard ways to transition from one view controller to another—from presenting a view controller to displaying a controller in a popover. However, if one of those segues doesn’t do what you want, you can create a custom segue. The Life Cycle of a Segue To understand how custom segues work, you need to understand the life cycle of a segue object. Segue objects are instances of UIStoryboardSegue or one of its subclasses. Your app never creates segue objects directly; they are always created on your behalf by iOS when a segue is triggered. Here’s what happens: 1. The destination controller is created and initialized. 2. The segue object is created and its initWithIdentifier:source:destination: method is called. The identifier is the unique string you provided for the segue in Interface Builder, and the two other parameters represent the two controller objects in the transition. 3. The source view controller’s prepareForSegue:sender: method is called. See “Configuring the Destination Controller When a Segue is Triggered” (page 101). 4. The segue object’s perform method is called. This method performs a transition to bring the destination view controller on-screen. 5. The reference to the segue object is released, causing it to be deallocated. Implementing a Custom Segue To implement a custom segue, you subclass UIStoryboardSegue and implement the two methods described earlier: ● If you override the initWithIdentifier:source:destination: method, call the superclass’s implementation, then initialize your subclass. ● Your perform method must make whatever view controller calls are necessary to perform the transition you want. Typically, you use any of the standard ways to display a new view controller, but you can embellish this design with animations and other effects. 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 109 Creating Custom SeguesNote: If your implementation adds properties to configure the segue, you cannot configure these attributes in Interface Builder. Instead, configure the custom segue’s additional properties in the prepareForSegue:sender: method of the source view controller that triggered the segue. “Creating Custom Segues” shows a very simple custom segue. This example simply presents the destination view controller without any sort of animation, but you can extend this idea with your own animations as necessary. Listing 13-1 A custom segue - (void)perform { // Add your own animation code here. [[self sourceViewController] presentModalViewController:[self destinationViewController] animated:NO]; } Creating Custom Segues Implementing a Custom Segue 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 110Container view controllers are a critical part of iOS app design. They allow you to decompose your app into smaller and simpler parts, each controlled by a view controller dedicated to that task. Containers allow these view controllers to work together to present a seamless interface. iOS provides many standard containers to help you organize your apps. However, sometimes you need to create a custom workflow that doesn’t match that provided by any of the system containers. Perhaps in your vision, your app needs a specific organization of child view controllers with specialized navigation gestures or animation transitions between them. To do that, you implement a custom container. Designing Your Container View Controller In most ways, a container view controller is just like a content view controller. It manages views and content, coordinates with other objects in your app, and responds to events in the responder chain. Before designing a container controller, you should already be familiar with designing content view controllers. The design questions in “Creating Custom Content View Controllers” (page 43) also apply when creating containers. When you design a container, you create explicit parent-child relationships between your container, the parent, and other view controllers, its children. More specifically, Figure 14-1 shows that there are explicit connections between the views as well. Your container adds the content views of other view controllers in its own view 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 111 Creating Custom Container View Controllershierarchy. Whenever a child’s view is displayed in the container’s view hierarchy, your container also establishes a connection to the child view controller and ensures that all appropriate view controller events are sent to the child. Figure 14-1 A container view controller’s view hierarchy contains another controller’s views Your containershould make the rules and its children should follow them; it is up to the parent to decide when a child’s content is visible in its own view hierarchy. The container decides where in the hierarchy that view is placed and how it is sized and positioned there. This design principle is no different from that of a content view controller. The view controller isresponsible for managing its own view hierarchy and other classesshould never manipulate its contents. Where necessary, your container class can expose public methods and properties to allow its behavior to be controlled. For example, if another object needs to be able to tell your container to display a new view, then your container class should expose a public method to allow this transition to occur. The actual implementation that changes the view hierarchy should be in the container class. This guiding principle cleanly separates responsibilities between the container and its children by always making each view controller responsible for its own view hierarchy. Here are some specific questions you should be able to answer about your container class: ● What is the role of the container and what role do its children play? ● Is there a relationship between siblings? ● How are child view controllers added to or removed from the container? Your container class must provide public properties and methods to allow children to be displayed by it. ● How many children are displayed by the container? Creating Custom Container View Controllers Designing Your Container View Controller 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 112● Are the contents of the container static or dynamic? In a static design, the children are more or less fixed, whereasin a dynamic design, transitions between siblings may occur. You define what triggers a transition to a new sibling. It might be programmatic or it might happen when a user interacts with the container. ● Does the container own any of its own views? For example, your container’s user interface may include information about the child view controller or controls to allow navigation. ● Does the container require its children to provide methods or properties other than those found on the UIViewController class? There are many reasons why a container might do this. It might need specific information from the child to used to configure other aspects of container display, or it might allow the child to modify the container’s behavior. It even might call the child view controller when container-specific events occur. ● Does your container allow its behavior to be configured? ● Are all its children treated identically or does it have multiple types of children, each with specialized behaviors? For example, you might create a container that displays two children, coordinating actions between the two children. Each child implements a distinct set of methods to allow its behavior to be configured. In summary, a container controller often has more relationships with other objects (especially other view controllers) than a content controller. So, you need to put additional effort into understanding how the container works. Ideally, as with a content controller, you want to hide many of those behaviors behind an excellent public class API. Examples of Common Container Designs The easiest way to understand how to design a new container class is to examine the behavior and public API of the existing system container classes. Each definesits own navigation metaphor and a programming interface used to configure it. This section takes a look at a few of these classes from the viewpoint of container design. It does not provide a complete description of each class’s programming interface, but just looks at some of the critical concepts. For detailed information about using these system containers,see ViewController Catalog for iOS . A Navigation Controller Manages a Stack of Child View Controllers A navigation controller allows a sequence of distinct user interface screens to be displayed to the user. The metaphor used by a navigation controller is a stack of child view controllers. The topmost view controller’s view is placed in the navigation controller’s view hierarchy. To display a new view controller, you push it onto the stack. When you are done, you remove the view controller from the stack. Creating Custom Container View Controllers Examples of Common Container Designs 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 113Figure 14-2 shows that only a single child’s view is visible and that the child’s view is part of a more complex hierarchy of views provided by the navigation controller. Figure 14-2 A navigation controller’s view and view controller hierarchy When a view controller is pushed onto or popped from the stack, the transition can be animated, which means the views of two children are briefly displayed together. In addition to the child views, a navigation controller also includes its own content views to display a navigation bar. The contents of the navigation bar are updated based on the child being displayed. Here are some of the important methods and properties that the UINavigationController class uses to define its behavior: ● The topViewController property states which controller is at the top of the stack. ● The viewControllers property lists all the children in the stack. ● The pushViewController:animated: method pushes a new view controller on the stack. This method does all the work necessary to update the view hierarchy to display the new child’s view. ● The popViewControllerAnimated: method removes the top view controller from the stack. ● The delegate property allows a client of the container to be notified when state transitions occur. The navigation controller uses properties on the child view controller to adjust the content it displays. These properties are defined by UIViewController base classso thatsome default behavior is available; this allows any view controller to be made a child of a navigation controller. Here are some of the propertiesthe navigation controller looks for: Creating Custom Container View Controllers Examples of Common Container Designs 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 114● The navigationItem property provides the contents of the navigation toolbar. ● The toolbarItems property provides the contents of the bottom bar. ● The editButtonItem property provides access to a view in the navigation item so that the navigation controller can toggle the child view’s edit mode. A Tab Bar Controller Uses a Collection of Child Controllers A tab view controller allows a set of distinct user interface screensto be displayed to the user. However, instead of a stack of view controllers, a tab view controller uses a simple array. Figure 14-3 shows that again, only one child view controller’s view is displayed at a time. However, these views do not need to be accessed sequentially, and the transition to the new child is usually not animated. Figure 14-3 A tab bar controller’s view and view controller hierarchy Here are some of the important methods and properties that UITabBarController class uses to allow apps to control what a tab bar controller displays: ● The viewControllers property holds the list of child view controllers that act as the tabs of content. ● The selectedViewController property allows you to read or change which child is visible. ● The delegate property allows a client of the container to be notified when state transitions occur. A tab bar controller uses the child’s tabBarItem property to determine how it is displayed in the appropriate tab. Creating Custom Container View Controllers Examples of Common Container Designs 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 115A Page Controller Uses a Data Source to Provide New Children A page controller uses pages of content as its metaphor, like the pages of a book. Each page displayed by the container is provided by a child view controller. Books can have many pages—far more than the number of screens of content in a navigation controller—so keeping all the pages in memory at once may not be possible. Instead, the page view controller keeps child controllers for the visible pages and fetches other pages on demand. When the user wants to see a new page, the container calls the object associated with its dataSource property to get the new controller. Thus, a page view controller using a data source uses a pull model rather than having your app directly push new pages onto itself. A page view controller can also be customized for different kinds of book layouts. The number of pages and the size of the pages can differ. Here are two key properties that affect the page view controller’s behavior: ● The spineLocation property determines how the pages are organized. Some layouts only display one page at a time. Other layouts display multiple pages. ● The transitionStyle property determines how transitions between pages are animated. Implementing a Custom Container View Controller Once you’ve designed your class’s behavior and determined many aspects of its public API, you are ready to start implementing the container. The goal of implementing a container is to be able to add another view controller’s view (and associated view hierarchy) as a subtree in your container’s view hierarchy. The child remainsresponsible for its own view hierarchy,save for where the container decidesto place it onscreen. When you add the child’s view, you need to ensure that events continue to be distributed to both view controllers. You do this by explicitly associating the new view controller as a child of the container. The UIViewController class provides methods that a container view controller uses to manage the relationship between itself and its children. The complete list of methods and properties is in the reference; see “Managing Child View Controllers in a Custom Container” in UIViewController Class Reference Important: These UIViewController methods are only intended to be used to implement container view controllers; do not call them in a content view controller. Adding and Removing a Child Listing 14-1 shows a typical implementation that adds a view controller as a child of another view controller. Each numbered step in the listing is described in more detail following the listing. Creating Custom Container View Controllers Implementing a Custom Container View Controller 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 116Listing 14-1 Adding another view controller’s view to the container’s view hierarchy - (void) displayContentController: (UIViewController*) content; { [self addChildViewController:content]; // 1 content.view.frame = [self frameForContentController]; // 2 [self.view addSubview:self.currentClientView]; [content didMoveToParentViewController:self]; // 3 } Here’s what the code does: 1. It calls the container’s addChildViewController: method to add the child. Calling the addChildViewController: method also calls the child’s willMoveToParentViewController: method automatically. 2. It accessesthe child’s view property to retrieve the view and addsit to its own view hierarchy. The container sets the child’s size and position before adding the view; containers always choose where the child’s content appears. Although this example doesthis by explicitly setting the frame, you could also use layout constraints to determine the view’s position. 3. It explicitly calls the child’s didMoveToParentViewController: method to signal that the operation is complete. Eventually, you want to be able to remove the child’s view from the view hierarchy. In this case, shown in Listing 14-2, you perform the steps in reverse. Listing 14-2 Removing another view controller’s view to the container’s view hierarchy - (void) hideContentController: (UIViewController*) content { [content willMoveToParentViewController:nil]; // 1 [content.view removeFromSuperview]; // 2 [content removeFromParentViewController]; // 3 } Here’s what this code does: 1. Callsthe child’s willMoveToParentViewController: method with a parameter of nil to tell the child that it is being removed. 2. Cleans up the view hierarchy. Creating Custom Container View Controllers Implementing a Custom Container View Controller 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 1173. Calls the child’s removeFromParentViewController method to remove it from the container. Calling the removeFromParentViewController method automatically calls the child’s didMoveToParentViewController: method. For a container with essentially static content, adding and removing view controllers is as simple as that. Whenever you want to add a new view, add the new view controller as a child first. After the view is removed, remove the child from the container. However, sometimes you want to animate a new child onto the screen while simultaneously removing another child. Listing 14-3 shows an example of how to do this. Listing 14-3 Transitioning between two view controllers - (void) cycleFromViewController: (UIViewController*) oldC toViewController: (UIViewController*) newC { [oldC willMoveToParentViewController:nil]; // 1 [self addChildViewController:newC]; newC.view.frame = [self newViewStartFrame]; // 2 CGRect endFrame = [self oldViewEndFrame]; [self transitionFromViewController: oldC toViewController: newC // 3 duration: 0.25 options:0 animations:^{ newC.view.frame = oldC.view.frame; // 4 oldC.view.frame = endFrame; } completion:^(BOOL finished) { [oldC removeFromParentViewController]; // 5 [newC didMoveToParentViewController:self]; }]; } Here’s what this code does: 1. Starts both view controller transitions. 2. Calculates two new frame positions used to perform the transition animation. Creating Custom Container View Controllers Implementing a Custom Container View Controller 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 1183. Calls the transitionFromViewController:toViewController:duration:options:animations:completion: method to perform the swap. This method automatically adds the new view, performs the animation, and then removes the old view. 4. The animation step to perform to get the views swapped. 5. When the transition completes, the view hierarchy isin itsfinalstate,so it finishesthe operation by sending the final two notifications. Customizing Appearance and Rotation Callback Behavior Once you add a child to a container, the container automatically forwards rotation and appearance callbacks to the child view controllers as soon as an event occurs that requires the message to be forwarded. This is normally the behavior you want, because it ensures that all events are properly sent. However, sometimes the default behavior may send those events in an order that doesn’t make sense for your container. For example, if multiple children are simultaneously changing their view state, you may want to consolidate the changes so that the appearance callbacks all happen at the same time in a more logical order. To do this, you modify your container class to take over responsibility for appearance or rotation callbacks. To take over control of appearance callbacks, you override the shouldAutomaticallyForwardAppearanceMethodsmethod to return NO. Listing 14-4 showsthe necessary code. Listing 14-4 Disabling automatic appearance forwarding - (BOOL) shouldAutomaticallyForwardAppearanceMethods { return NO; } To actually inform the child view controller that an appearance transition is occurring, you call the child’s beginAppearanceTransition:animated: and endAppearanceTransition methods. If you take over sending these messages, you are also responsible for forwarding them to children when your container view controller appears and disappears. For example, if your container has a single child referenced by a child property, your container would forward these messages to the child, as shown in Listing 14-5. Listing 14-5 Forwarding appearance messages when the container appears or disappears -(void) viewWillAppear:(BOOL)animated { Creating Custom Container View Controllers Implementing a Custom Container View Controller 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 119[self.child beginAppearanceTransition: YES animated: animated]; } -(void) viewDidAppear:(BOOL)animated { [self.child endAppearanceTransition]; } -(void) viewWillDisappear:(BOOL)animated { [self.child beginAppearanceTransition: NO animated: animated]; } -(void) viewDidDisappear:(BOOL)animated { [self.child endAppearanceTransition]; } Forwarding rotation events works almost identically and can be done independently of forwarding appearance messages. First, you override the shouldAutomaticallyForwardRotationMethods method to return NO. Then, at times appropriate to your container, you call the following methods: ● willRotateToInterfaceOrientation:duration: ● willAnimateRotationToInterfaceOrientation:duration: ● didRotateFromInterfaceOrientation: Practical Suggestions for Building a Container View Controller Designing, developing, and testing a new container view controller takestime. Although the individual behaviors are straightforward, the controller as a whole can be quite complex. Consider some of the following guidance when implementing your own container classes: ● Design the view controller first as a content view controller, using regular views owned by the container. This allows you to focus on getting layout and animation transitions correct without simultaneously needing to manage parent-child relationships. Creating Custom Container View Controllers Practical Suggestions for Building a Container View Controller 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 120● Never access any view other than the top-level view of the child view controller. Similarly, children should have only a minimal knowledge of what the parent is doing with the view; do not expose unnecessary details to the child. ● If the container needs the child to declare methods or properties, it should define a protocol to enforce this: @protocol MyContentContainerProtocol ... @end - (void) displayContentController: (UIViewController*) content; Creating Custom Container View Controllers Practical Suggestions for Building a Container View Controller 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 121This table describes the changes to View Controller Programming Guide for iOS . Date Notes Added design guidelines for custom container view controllers and accessibility in the view controller. Updated the discussions of view rotation, view layout, and resource management for iOS 6. 2012-09-19 Edited for clarity. Added new glossary entries. Added a section about determining why a view controller's view appeared or disappeared. 2012-02-16 This revised treatment has been rewritten around using storyboards and ARC to build new iOS apps. 2012-01-09 2011-01-07 Fixed several typos. 2010-11-12 Added information about iPad-only controller objects. Changed the title from "View Controller Programming Guide for iPhone OS." 2010-07-08 2010-05-03 Fixed some typos. Fixed several typos and updated the figure for the two-step rotation process. 2010-02-24 Rewrote the document and expanded the content to address iOS 3.0 changes. 2009-10-19 2009-05-28 Added a note about the lack of iOS 3.0 support. 2008-10-15 Updated obsolete references to the iOS Programming Guide. 2008-09-09 Corrected typos. 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 122 Document Revision HistoryDate Notes New document that explains how to use view controllers to implement radio, navigation, and modal interfaces. 2008-06-23 Document Revision History 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 123container view controller A view controller that coordinatesthe interaction of other view controllers in order to present a specific type of user interface. content view controller A view controller that displays some content on the screen. custom segue A segue whose transition effect is defined by a custom subclass. modal segue A segue whose transition effect presents the new view controller using an existing view controller. navigation controller A container view controller used to present hierarchical content. navigation interface The style of interface that is presented by a navigation controller’s view. A navigation interface includes a navigation bar along the top of the screen to facilitate navigating between different screens. navigation stack The list of view controllers currently being managed by a navigation controller. The view controllers on the stack represent the content currently being displayed by a navigation interface. page view controller A container view controller used to display pages of content with an artistic style similar to that of a physical book. popover controller A controller class used to present another view controller’s view in a popover control. popover segue A segue whose transition effect displays the new view controller’s content in a popover control. push segue A segue whose transition effect pushes the new view controller onto a navigation stack of a navigation controller. root view controller The topmost view controller in a view controller hierarchy. scene A visual representation in Interface Builder of a view controller and its associated objects, including the views it loads when displayed. segue A transition between two scenes, configured in Interface Builder. split view controller A container view controller used in iPad appsto present master-detail interfaces. tab bar controller A container view controller used to present a set of distinct interface screens, each represented by a tab and delivered by a separate content view controller. tab bar interface The style of interface that is presented by a tab bar controller’s view. A tab bar interface includes one or more tabs at the bottom of the screen. Tapping a tab changes the currently displayed screen contents. view controller An object that descends from the UIViewController class. View controllers coordinate the interactions between a set of views and the custom data presented by those views. 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 124 Glossaryview controller hierarchy A set of container and content view controllers arranged in a tree. Non-leaf nodes always represent container view controllers. Glossary 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 125Apple Inc. © 2012 Apple Inc. All rights reserved. No part of this publication may be reproduced, stored in a retrievalsystem, or transmitted, in any form or by any means, mechanical, electronic, photocopying, recording, or otherwise, without prior written permission of Apple Inc., with the following exceptions: Any person is hereby authorized to store documentation on a single computer for personal use only and to print copies of documentation for personal use provided that the documentation contains Apple’s copyright notice. No licenses, express or implied, are granted with respect to any of the technology described in this document. Apple retains all intellectual property rights associated with the technology described in this document. This document is intended to assist application developers to develop applications only for Apple-labeled computers. Apple Inc. 1 Infinite Loop Cupertino, CA 95014 408-996-1010 Apple, the Apple logo, Cocoa, iBook, iBooks, iPad, iPhone, Objective-C, and Xcode are trademarks of Apple Inc., registered in the U.S. and other countries. iOS is a trademark or registered trademark of Cisco in the U.S. and other countries and is used under license. Even though Apple has reviewed this document, APPLE MAKES NO WARRANTY OR REPRESENTATION, EITHER EXPRESS OR IMPLIED, WITH RESPECT TO THIS DOCUMENT, ITS QUALITY, ACCURACY, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.ASARESULT, THISDOCUMENT IS PROVIDED “AS IS,” AND YOU, THE READER, ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND ACCURACY. IN NO EVENT WILL APPLE BE LIABLE FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL,OR CONSEQUENTIAL DAMAGES RESULTING FROM ANY DEFECT OR INACCURACY IN THIS DOCUMENT, even if advised of the possibility of such damages. THE WARRANTY AND REMEDIES SET FORTH ABOVE ARE EXCLUSIVE AND IN LIEU OF ALL OTHERS, ORAL OR WRITTEN, EXPRESS OR IMPLIED. No Apple dealer, agent, or employee is authorized to make any modification, extension, or addition to this warranty. Some states do not allow the exclusion or limitation of implied warranties or liability for incidental or consequential damages, so the above limitation or exclusion may not apply to you. This warranty gives you specific legal rights, and you may also have other rights which vary from state to state. Key-Value Observing Programming GuideContents Introduction to Key-Value Observing Programming Guide 4 At a Glance 4 Registering for Key-Value Observing 7 Registering as an Observer 7 Receiving Notification of a Change 8 Removing an Object as an Observer 10 KVO Compliance 11 Automatic Change Notification 11 Manual Change Notification 12 Registering Dependent Keys 15 To-one Relationships 15 To-many Relationships 16 Key-Value Observing Implementation Details 19 Document Revision History 20 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 2Listings Registering for Key-Value Observing 7 Listing 1 Registering the inspector as an observer of the openingBalance property 7 Listing 2 Implementation of observeValueForKeyPath:ofObject:change:context: 9 Listing 3 Removing the inspector as an observer of openingBalance 10 KVO Compliance 11 Listing 1 Examples of method calls that cause KVO change notifications to be emitted 11 Listing 2 Example implementation of automaticallyNotifiesObserversForKey: 12 Listing 3 Example accessor method implementing manual notification 13 Listing 4 Testing the value for change before providing notification 13 Listing 5 Nesting change notifications for multiple keys 13 Listing 6 Implementation of manual observer notification in a to-many relationship 14 Registering Dependent Keys 15 Listing 1 Example implementation of keyPathsForValuesAffectingValueForKey: 15 Listing 2 Example implementation of the keyPathsForValuesAffecting naming convention 16 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 3Key-value observing is a mechanism that allows objects to be notified of changes to specified properties of other objects. Important: In order to understand key-value observing, you must first understand key-value coding. At a Glance Key-value observing provides a mechanism that allows objects to be notified of changes to specific properties of other objects. It is particularly useful for communication between model and controller layers in an application. (In OS X, the controller layer binding technology relies heavily on key-value observing.) A controller object typically observes properties of model objects, and a view object observes properties of model objects through a controller. In addition, however, a model object may observe other model objects (usually to determine when a dependent value changes) or even itself (again to determine when a dependent value changes). You can observe properties including simple attributes, to-one relationships, and to-many relationships. Observers of to-many relationships are informed of the type of change made—as well as which objects are involved in the change. There are three steps to setting up an observer of a property. Understanding these three steps provides a clear illustration of how KVO works. 1. First, see whether you have a scenario where key-value observing could be beneficial, for example, an object that needs to be notified when any changes are made to a specific property in another object. BankObject @property int accountBalance PersonObject For example, a PersonObject will want to be aware of any changes made to their accountBalance in the BankObject. 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 4 Introduction to Key-Value Observing Programming Guide2. The PersonObject must register as an observer of the BankObject’s accountBalance property by sending an addObserver:forKeyPath:options:context: message. BankObject PersonObject Connection established [bankInstance addObserver:personInstance forKeyPath:@"accountBalance" options:NSKeyValueObservingOptionNew context:NULL]; Note: The addObserver:forKeyPath:options:context:method establishes a connection between the instances of the objects that you specify. A connection is not established between the two classes, but rather between the two specified instances of the objects. 3. In order to respond to change notifications, the observer must implement the observeValueForKeyPath:ofObject:change:context: method. This method implementation defines how the observer responds to change notifications. It is in this method that you can customize your response to a change in one of the observed properties. BankObject PersonObject Connection established -(void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { //custom implementation //be sure to call the superclass’ implementation //if the superclass implements it } “Registering for Key-Value Observing” (page 7) describes how to register and receive observation notifications. Introduction to Key-Value Observing Programming Guide At a Glance 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 54. The observeValueForKeyPath:ofObject:change:context: method is automatically invoked when the value of an observed property is changed in a KVO-compliant manner, or if a key upon which it depends is changed. BankObject PersonObject Automatically notifies person Person can react accordingly in customized method [bankInstance setAccountBalance:50]; “Registering Dependent Keys” (page 15) explains how to specify that the value of a key is dependent on the value of another key. KVO’s primary benefit is that you don’t have to implement your own scheme to send notifications every time a property changes. Its well-defined infrastructure has framework-level support that makes it easy to adopt—typically you do not have to add any code to your project. In addition, the infrastructure is already full-featured, which makes it easy to support multiple observers for a single property, as well as dependent values. “KVO Compliance” (page 11) describes the difference between automatic and manual key-value observing, and how to implement both. Unlike notifications that use NSNotificationCenter, there is no central object that provides change notification for all observers. Instead, notifications are sent directly to the observing objects when changes are made. NSObject provides this base implementation of key-value observing, and you should rarely need to override these methods. “Key-Value Observing Implementation Details ” (page 19) describes how key-value observing is implemented. Introduction to Key-Value Observing Programming Guide At a Glance 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 6In order to receive key-value observing notifications for a property, three things are required: ● The observed class must be key-value observing compliant for the property that you wish to observe. ● You must register the observing object with the observed object, using the method addObserver:forKeyPath:options:context:. ● The observing class must implement observeValueForKeyPath:ofObject:change:context:. Important: Not all classes are KVO-compliant for all properties. You can ensure your own classes are KVO-compliant by following the steps described in “KVO Compliance” (page 11). Typically properties in Apple-supplied frameworks are only KVO-compliant if they are documented as such. Registering as an Observer In order to be notified of changes to a property, an observing object must first register with the object to be observed by sending it an addObserver:forKeyPath:options:context: message, passing the observer object and the key path of the property to be observed. The options parameter specifies the information that is provided to the observer when a change notification is sent. Using the option NSKeyValueObservingOptionOld specifies that the original object value is provided to the observer as an entry in the change dictionary. Specifying the NSKeyValueObservingOptionNew option provides the new value as an entry in the change dictionary. To receive both values, you would bitwise OR the option constants. The example in Listing 1 demonstrates registering an inspector object for the property openingBalance. Listing 1 Registering the inspector as an observer of the openingBalance property - (void)registerAsObserver { /* Register 'inspector' to receive change notifications for the "openingBalance" property of the 'account' object and specify that both the old and new values of "openingBalance" should be provided in the observe… method. 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 7 Registering for Key-Value Observing*/ [account addObserver:inspector forKeyPath:@"openingBalance" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) context:NULL]; } When you register an object as an observer, you can also provide a context pointer. The context pointer is provided to the observer when observeValueForKeyPath:ofObject:change:context: is invoked. The context pointer can be a C pointer or an object reference. The context pointer can be used as a unique identifier to determine the change that is being observed, or to provide some other data to the observer. Note: The key-value observing addObserver:forKeyPath:options:context: method does not maintain strong references to the observing object, the observed objects, or the context. You should ensure that you maintain strong references to the observing, and observed, objects, and the context as necessary. Receiving Notification of a Change When the value of an observed property of an object changes, the observer receives an observeValueForKeyPath:ofObject:change:context: message. All observers must implement this method. The observer is provided the object and key path that triggered the observer notification, a dictionary containing details about the change, and the context pointer that was provided when the observer was registered. The change dictionary entry NSKeyValueChangeKindKey provides information about the type of change that occurred. If the value of the observed object has changed, the NSKeyValueChangeKindKey entry returns NSKeyValueChangeSetting. Depending on the options specified when the observer was registered, the NSKeyValueChangeOldKey and NSKeyValueChangeNewKey entries in the change dictionary contain the values of the property before, and after, the change. If the property is an object, the value is provided directly. If the property is a scalar or a C structure, the value is wrapped in an NSValue object (as with key-value coding). Registering for Key-Value Observing Receiving Notification of a Change 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 8If the observed property is a to-many relationship, the NSKeyValueChangeKindKey entry also indicates whether objects in the relationship were inserted, removed, or replaced by returning NSKeyValueChangeInsertion, NSKeyValueChangeRemoval, or NSKeyValueChangeReplacement, respectively. The change dictionary entry for NSKeyValueChangeIndexesKey is an NSIndexSet object specifying the indexes in the relationship that changed. If NSKeyValueObservingOptionNew or NSKeyValueObservingOptionOld are specified as options when the observer is registered, the NSKeyValueChangeOldKey and NSKeyValueChangeNewKey entries in the change dictionary are arrays containing the values of the related objects before, and after, the change. The example in Listing 2 shows the observeValueForKeyPath:ofObject:change:context: implementation for an inspector that reflects the old and new values of the property openingBalance, as registered in Listing 1 (page 7). Listing 2 Implementation of observeValueForKeyPath:ofObject:change:context: - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if ([keyPath isEqual:@"openingBalance"]) { [openingBalanceInspectorField setObjectValue: [change objectForKey:NSKeyValueChangeNewKey]]; } /* Be sure to call the superclass's implementation *if it implements it*. NSObject does not implement the method. */ [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } Registering for Key-Value Observing Receiving Notification of a Change 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 9Removing an Object as an Observer You remove a key-value observer by sending the observed object a removeObserver:forKeyPath: message, specifying the observing object and the key path. The example in Listing 3 removesthe inspector as an observer of openingBalance. Listing 3 Removing the inspector as an observer of openingBalance - (void)unregisterForChangeNotification { [observedObject removeObserver:inspector forKeyPath:@"openingBalance"]; } If the context is an object, you must keep a strong reference to it until removing the observer. After receiving a removeObserver:forKeyPath: message, the observing object will no longer receive any observeValueForKeyPath:ofObject:change:context: messagesfor the specified key path and object. Registering for Key-Value Observing Removing an Object as an Observer 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 10In order to be considered KVO-compliant for a specific property, a class must ensure the following: ● The class must be key-value coding compliant for the property, as specified in “Ensuring KVC Compliance”. KVO supports the same data types as KVC. ● The class emits KVO change notifications for the property. ● Dependent keys are registered appropriately (see “Registering Dependent Keys” (page 15)). There are two techniques for ensuring the change notifications are emitted. Automatic support is provided by NSObject and is by default available for all properties of a class that are key-value coding compliant. Typically, if you follow standard Cocoa coding and naming conventions, you can use automatic change notifications—you don’t have to write any additional code. Manual change notification provides additional control over when notifications are emitted, and requires additional coding. You can control automatic notifications for properties of your subclass by implementing the class method automaticallyNotifiesObserversForKey:. Automatic Change Notification NSObject provides a basic implementation of automatic key-value change notification. Automatic key-value change notification informs observers of changes made using key-value compliant accessors, as well as the key-value coding methods. Automatic notification is also supported by the collection proxy objects returned by, for example, mutableArrayValueForKey:. The examples shown in Listing 1 result in any observers of the property name to be notified of the change. Listing 1 Examples of method calls that cause KVO change notifications to be emitted // Call the accessor method. [account setName:@"Savings"]; // Use setValue:forKey:. [account setValue:@"Savings" forKey:@"name"]; 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 11 KVO Compliance// Use a key path, where 'account' is a kvc-compliant property of 'document'. [document setValue:@"Savings" forKeyPath:@"account.name"]; // Use mutableArrayValueForKey: to retrieve a relationship proxy object. Transaction *newTransaction = <#Create a new transaction for the account#>; NSMutableArray *transactions = [account mutableArrayValueForKey:@"transactions"]; [transactions addObject:newTransaction]; Manual Change Notification Manual change notification provides more granular control over how and when notifications are sent to observers. This can be useful to help minimize triggering notifications that are unnecessary, or to group a number of changes into a single notification. A class that implements manual notification must override the NSObject implementation of automaticallyNotifiesObserversForKey:. It is possible to use both automatic and manual observer notifications in the same class. For properties that perform manual notification, the subclass implementation of automaticallyNotifiesObserversForKey: should return NO. A subclassimplementation should invoke super for any unrecognized keys. The example in Listing 2 enables manual notification for the openingBalance property allowing the superclass to determine the notification for all other keys. Listing 2 Example implementation of automaticallyNotifiesObserversForKey: + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)theKey { BOOL automatic = NO; if ([theKey isEqualToString:@"openingBalance"]) { automatic = NO; } else { automatic = [super automaticallyNotifiesObserversForKey:theKey]; } return automatic; } KVO Compliance Manual Change Notification 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 12To implement manual observer notification, you invoke willChangeValueForKey: before changing the value, and didChangeValueForKey: after changing the value. The example in Listing 3 implements manual notifications for the openingBalance property. Listing 3 Example accessor method implementing manual notification - (void)setOpeningBalance:(double)theBalance { [self willChangeValueForKey:@"openingBalance"]; _openingBalance = theBalance; [self didChangeValueForKey:@"openingBalance"]; } You can minimize sending unnecessary notifications by first checking if the value has changed. The example in Listing 4 tests the value of openingBalance and only provides the notification if it has changed. Listing 4 Testing the value for change before providing notification - (void)setOpeningBalance:(double)theBalance { if (theBalance != _openingBalance) { [self willChangeValueForKey:@"openingBalance"]; _openingBalance = theBalance; [self didChangeValueForKey:@"openingBalance"]; } } If a single operation causes multiple keysto change you must nest the change notifications asshown in Listing 5. Listing 5 Nesting change notifications for multiple keys - (void)setOpeningBalance:(double)theBalance { [self willChangeValueForKey:@"openingBalance"]; [self willChangeValueForKey:@"itemChanged"]; _openingBalance = theBalance; _itemChanged = _itemChanged+1; [self didChangeValueForKey:@"itemChanged"]; [self didChangeValueForKey:@"openingBalance"]; } KVO Compliance Manual Change Notification 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 13In the case of an ordered to-many relationship, you must specify not only the key that changed, but also the type of change and the indexes of the objects involved. The type of change is an NSKeyValueChange that specifies NSKeyValueChangeInsertion, NSKeyValueChangeRemoval, or NSKeyValueChangeReplacement. The indexes of the affected objects are passed as an NSIndexSet object. The code fragment in Listing 6 demonstrates how to wrap a deletion of objects in the to-many relationship transactions. Listing 6 Implementation of manual observer notification in a to-many relationship - (void)removeTransactionsAtIndexes:(NSIndexSet *)indexes { [self willChange:NSKeyValueChangeRemoval valuesAtIndexes:indexes forKey:@"transactions"]; // Remove the transaction objects at the specified indexes. [self didChange:NSKeyValueChangeRemoval valuesAtIndexes:indexes forKey:@"transactions"]; } KVO Compliance Manual Change Notification 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 14There are many situations in which the value of one property depends on that of one or more other attributes in another object. If the value of one attribute changes, then the value of the derived property should also be flagged for change. How you ensure that key-value observing notifications are posted for these dependent properties depends on the cardinality of the relationship. To-one Relationships To trigger notifications automatically for a to-on relationship you should either override keyPathsForValuesAffectingValueForKey: or implement a suitable method that follows the pattern it defines for registering dependent keys. For example, the full name of a person is dependent on both the first and last names. A method that returns the full name could be written as follows: - (NSString *)fullName { return [NSString stringWithFormat:@"%@ %@",firstName, lastName]; } An application observing the fullName property must be notified when either the firstName or lastName properties change, as they affect the value of the property. One solution is to override keyPathsForValuesAffectingValueForKey: specifying that the fullName property of a person is dependent on the lastName and firstName properties. Listing 1 (page 15) shows an example implementation of such a dependency: Listing 1 Example implementation of keyPathsForValuesAffectingValueForKey: + (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key { NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key]; if ([key isEqualToString:@"fullName"]) { 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 15 Registering Dependent KeysNSArray *affectingKeys = @[@"lastName", @"firstName"]; keyPaths = [keyPaths setByAddingObjectsFromArray:affectingKeys]; } return keyPaths; } Your override should typically invoke super and return a set that includes any members in the set that result from doing that (so as not to interfere with overrides of this method in superclasses). You can also achieve the same result by implementing a class method that follows the naming convention keyPathsForValuesAffecting, where is the name of the attribute (first letter capitalized) that is dependent on the values. Using this pattern the code in Listing 1 (page 15) could be rewritten as a class method named keyPathsForValuesAffectingFullName as shown in Listing 2 (page 16). Listing 2 Example implementation of the keyPathsForValuesAffecting naming convention + (NSSet *)keyPathsForValuesAffectingFullName { return [NSSet setWithObjects:@"lastName", @"firstName", nil]; } You can't override the keyPathsForValuesAffectingValueForKey: method when you add a computed property to an existing class using a category, because you're not supposed to override methods in categories. In that case, implement a matching keyPathsForValuesAffecting class method to take advantage of this mechanism. Note: You cannot set up dependencies on to-many relationships by implementing keyPathsForValuesAffectingValueForKey:. Instead, you must observe the appropriate attribute of each of the objects in the to-many collection and respond to changes in their values by updating the dependent key yourself. The following section shows a strategy for dealing with this situation. To-many Relationships The keyPathsForValuesAffectingValueForKey: method does not support key-paths that include a to-many relationship. For example, suppose you have a Department object with a to-many relationship (employees) to a Employee, and Employee has a salary attribute. You might want the Department object have Registering Dependent Keys To-many Relationships 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 16a totalSalary attribute that is dependent upon the salaries of all the Employees in the relationship. You can not do this with, for example, keyPathsForValuesAffectingTotalSalary and returning employees.salary as a key. There are two possible solutions in both situations: 1. You can use key-value observing to register the parent (in this example, Department) as an observer of the relevant attribute of all the children (Employeesin this example). You must add and remove the parent as an observer as child objects are added to and removed from the relationship (see “Registering for Key-Value Observing” (page 7)). In the observeValueForKeyPath:ofObject:change:context: method you update the dependent value in response to changes, as illustrated in the following code fragment: - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if (context == totalSalaryContext) { [self updateTotalSalary]; } else // deal with other observations and/or invoke super... } - (void)updateTotalSalary { [self setTotalSalary:[self valueForKeyPath:@"employees.@sum.salary"]]; } - (void)setTotalSalary:(NSNumber *)newTotalSalary { if (totalSalary != newTotalSalary) { [self willChangeValueForKey:@"totalSalary"]; _totalSalary = newTotalSalary; [self didChangeValueForKey:@"totalSalary"]; } } - (NSNumber *)totalSalary { return _totalSalary; Registering Dependent Keys To-many Relationships 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 17} 2. If you're using Core Data, you can register the parent with the application's notification center as an observer of its managed object context. The parentshould respond to relevant change notifications posted by the children in a manner similar to that for key-value observing. Registering Dependent Keys To-many Relationships 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 18Automatic key-value observing is implemented using a technique called isa-swizzling. The isa pointer, as the name suggests, points to the object's class which maintains a dispatch table. This dispatch table essentially contains pointers to the methods the class implements, among other data. When an observer is registered for an attribute of an object the isa pointer of the observed object is modified, pointing to an intermediate class rather than at the true class. As a result the value of the isa pointer does not necessarily reflect the actual class of the instance. You should never rely on the isa pointer to determine class membership. Instead, you should use the class method to determine the class of an object instance. 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 19 Key-Value Observing Implementation DetailsThis table describes the changes to Key-Value Observing Programming Guide . Date Notes 2012-07-17 Updated to use new Objective-C features. ARCification 2011-03-08 Clarified terminology in "Registering Dependent Keys." 2009-08-14 Added links to some key Cocoa definitions. 2009-05-09 Corrected minor typo. 2009-05-06 Clarified Core Data requirement in Registering Dependent Keys. 2009-03-04 Updated Registering Dependent Keys chapter. 2006-06-28 Updated code examples. Clarified that you should not release objects before calling willChangeValueForKey: methods. Noted that Java is not supported. 2005-07-07 2004-08-31 Corrected minor typos. Clarified the need to nest manual key-value change notifications. 2004-03-20 Modified source example in “Registering Dependent Keys” (page 15). Corrected source example in “Registering for Key-Value Observing” (page 7). Added article “Key-Value Observing Implementation Details ” (page 19). 2004-02-22 2003-10-15 Initial publication of Key-Value Observing. 2012-07-17 | © 2003, 2012 Apple Inc. All Rights Reserved. 20 Document Revision HistoryApple Inc. © 2003, 2012 Apple Inc. All rights reserved. No part of this publication may be reproduced, stored in a retrievalsystem, or transmitted, in any form or by any means, mechanical, electronic, photocopying, recording, or otherwise, without prior written permission of Apple Inc., with the following exceptions: Any person is hereby authorized to store documentation on a single computer for personal use only and to print copies of documentation for personal use provided that the documentation contains Apple’s copyright notice. No licenses, express or implied, are granted with respect to any of the technology described in this document. Apple retains all intellectual property rights associated with the technology described in this document. This document is intended to assist application developers to develop applications only for Apple-labeled computers. Apple Inc. 1 Infinite Loop Cupertino, CA 95014 408-996-1010 Apple, the Apple logo, Cocoa, Mac, and Objective-C are trademarks of Apple Inc., registered in the U.S. and other countries. Java is a registered trademark of Oracle and/or its affiliates. Even though Apple has reviewed this document, APPLE MAKES NO WARRANTY OR REPRESENTATION, EITHER EXPRESS OR IMPLIED, WITH RESPECT TO THIS DOCUMENT, ITS QUALITY, ACCURACY, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.ASARESULT, THISDOCUMENT IS PROVIDED “AS IS,” AND YOU, THE READER, ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND ACCURACY. IN NO EVENT WILL APPLE BE LIABLE FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL,OR CONSEQUENTIAL DAMAGES RESULTING FROM ANY DEFECT OR INACCURACY IN THIS DOCUMENT, even if advised of the possibility of such damages. THE WARRANTY AND REMEDIES SET FORTH ABOVE ARE EXCLUSIVE AND IN LIEU OF ALL OTHERS, ORAL OR WRITTEN, EXPRESS OR IMPLIED. No Apple dealer, agent, or employee is authorized to make any modification, extension, or addition to this warranty. Some states do not allow the exclusion or limitation of implied warranties or liability for incidental or consequential damages, so the above limitation or exclusion may not apply to you. This warranty gives you specific legal rights, and you may also have other rights which vary from state to state. Let’s get started When you start your Mac mini for the first time, Setup Assistant helps you get going. Just follow a few simple steps to quickly connect to your Wi-Fi network, transfer your stuff from another Mac or a PC, and create a user account for your Mac. You’ll also be able to log in with your Apple ID. This allows you to shop the App Store, iTunes Store, and Apple Online Store. It lets you keep in touch using Messages and FaceTime. And it lets you access iCloud, which is automatically set up on your Mac in apps like Mail, Contacts, and Calendar. If you don’t have an Apple ID, you can create one in Setup Assistant. Get to know your desktop The desktop is where you can find everything and do anything on your Mac. The Dock at the bottom is a handy place to keep the apps you use most. It’s also where you can open System Preferences, which lets you customize your desktop and other settings on your Mac. Click the Finder icon to quickly get to all your files and folders. The menu bar at the top has lots of useful information about your Mac. To check the status of your wireless Internet connection, click the Wi-Fi icon. Your Mac automatically connects to the network you chose during setup. Hello. iCloud iCloud stores your music, photos, documents, calendars, and more. And it wirelessly pushes them to your Mac, iPhone, iPad, iPod touch, and even your PC. All without docking or syncing. So when you buy a song on one device, it’s instantly available on all your other devices. When you adjust your calendar, all your devices stay up to date. And with Photo Stream, your latest photos appear everywhere you want to see them, automatically. To customize your iCloud settings, open the Apple menu, choose System Preferences, and click iCloud. Then sign in with your Apple ID and choose the iCloud features you want to use. Quick Start Guide Let’s get moving It’s easy to move files like documents, email, photos, music, and movies to your new Mac from another Mac or a PC. The first time you start your new Mac, it walks you through the process step by step. All you have to do is follow the onscreen instructions. If your Mac mini shipped with OS X Server, the Server application will open and walk you through the configuration process. Help menu Menu Dock bar Bluetooth status Finder System Preferences Launchpad Launchpad is the home for all the apps on your Mac. Just click the Launchpad icon in the Dock, and your open windows are replaced by a full-screen display of all your apps. Arrange apps any way you want, group them together in folders, or delete them from your Mac. When you download an app from the Mac App Store, it automatically appears in Launchpad. Mission Control Mission Control gives you a bird’s-eye view of everything running on your Mac. Click the Mission Control icon in the Dock, and your desktop zooms out to display all the open windows in every application, all your fullscreen apps, and Dashboard, the home of mini-apps called widgets. Click anything to zoom in on it. Think of Mission Control as the hub of your system—view everything and go anywhere with just a click. Welcome to your new Mac mini. We’d like to show you around. Removable panel USB 3 Built-in power supply HDMI Thunderbolt Audio in/out Gigabit Ethernet Power button FireWire 800 SD card slot AC power cord HDMI to DVI adapter Open Mission Control Click the Mission Control icon in the Dock. Add desktop spaces Click the + button to the right of the top row to add a new space. Dashboard Located at the top left for easy access. Wi-Fi status Open Launchpad Click the Launchpad icon in the Dock. Folders Group apps in folders by dragging one app on top of another.An important note Please read this document and the safety information in the Important Product Information Guide carefully before you first use your computer. Learn more You can find more information, watch demos, and learn even more about Mac mini features at www.apple.com/macmini. Help You can often find answers to your questions, as well as instructions and troubleshooting information, in Help Center. Click the Finder icon, click Help in the menu bar, and choose Help Center. OS X Utilities If you have a problem with your Mac, OS X Utilities can help you repair your computer’s hard drive, restore your software and data from a Time Machine backup, or erase your hard drive and reinstall OS X and Apple applications. You can also use Safari to get online help. If your Mac detects a problem, it opens OS X Utilities automatically. Or you can open it manually by restarting your computer while holding down the Command and R keys. Support Your Mac mini comes with 90 days of technical support and one year of hardware repair warranty coverage at an Apple Retail Store or an Apple Authorized Service Provider. Visit www.apple.com/support/macmini for Mac mini technical support. Or call 1-800-275-2273. In Canada, call 1-800-263-3394. Not all features are available in all areas. TM and © 2012 Apple Inc. All rights reserved. Designed by Apple in California. Printed in XXXX. 034-6575-A iTunes With iTunes, you can organize and play your digital music and videos on your Mac. And you can shop the iTunes Store for new music, movies, TV shows, books, and more. iTunes is also where you’ll find the App Store for iPad, iPhone, and iPod touch. Click the Safari icon in the Dock and surf the web quickly and easily with Multi-Touch gestures. Scroll up or down with one finger on Magic Mouse. Swipe right and left with two Safari web browser fingers to go back and forth between pages. Hold down the Control key and scroll with one finger to zoom in and out. Mail Mail lets you manage all your email accounts from a single, ad-free inbox, even when you’re not connected to the Internet. It works with most email standards— including POP3 and IMAP—and popular email services like Gmail, Yahoo! Mail, and AOL Mail. You can also use Mail with the free me.com email account you get with iCloud. The first time you open Mail, Setup Assistant will help you get started. Calendar Keep track of your busy schedule with Calendar. You can create separate calendars—one for home, another for school, a third for work. See all your calendars in a single window or choose to see only the calendars you want. Create and send invitations using contact info from the Contacts app, then see who has responded. Use iCloud to update calendars on all your devices automatically or share calendars with other iCloud users. Messages Just log in with your Apple ID, and you can send unlimited messages including text, photos, videos, and more to your friends on a Mac, iPad, iPhone, or iPod touch. With iCloud, you can start a conversation on one device and pick it up on another. And if you want to talk to someone face to face, you can start a video call* just by clicking the FaceTime icon in the top-right corner of the Messages window. iPhoto iPhoto is the best way to organize, browse, edit, and share your photos on your Mac. You can organize your photo library by Faces, Places, and Events. To send photos by email or publish them to Facebook, just select the photo and click Share in the bottom right of your screen. Or click Create to turn your favorite shots into photo books, calendars, and cards. iMovie iMovie puts all your video clips in one place and gives you the editing tools and special effects you need to quickly turn them into something memorable. You can make great-looking movies or even Hollywood-style movie trailers with just a few clicks. And iMovie lets you import video from most popular digital video cameras or your iPhone, iPad, or iPod touch. Mac App Store The Mac App Store is the best way to find and download thousands of apps for your Mac, from games and social networking to productivity apps and more. New apps install in one step to Launchpad. You can install apps on every Mac authorized for your personal use and even download them again. The Mac App Store lets you know when app and OS X updates are available, so you always have the latest versions. Open the Mac App Store by clicking its icon in the Dock. Top Sites Get a quick overview of the sites you visit most often. Reading List Click the glasses icon to save pages to read later. Full-screen view Click the full-screen button to go full screen. One-stop email View all your accounts in Mail for one-click access. Conversation view See all the email messages from a conversation thread. Search Quickly narrow search results to find exactly what you want. iTunes Store Discover and buy new music, movies, and more. Genius Mixes Let iTunes search your music library and group songs that go great together. Multiple calendars Access all your calendars from one place. Calendar view Select the view you prefer—day, week, month, or year. Add an event Double-click in a calendar to create a new event. Replies in progress Three dots mean your friend is typing a reply. Delivery receipts See when your message has arrived. FaceTime Start a video call right in Messages. *Requires FaceTime-enabled device for both caller and recipient. Not available in all areas. Create Create books, cards, and calendars. Faces iPhoto can even organize your photos based on who’s in them. Events Double-click any Event to browse photos. Event browser Your imported videos appear here so you can access all your clips. Project browser Simply drop your clips in a project to create a great movie. Always up to date Updates to your purchased apps and OS X appear automatically. Discover new apps Browse thousands of apps and download them straight to Launchpad. OS X Mountain Lion Core Technologies Overview June 20122 Core Technologies Overview OS X Mountain Lion Contents Page 3 Introduction Page 4 System Startup BootROM EFI Kernel Drivers Initialization Address Space Layout Randomization (ASLR) Page 7 Disk Layout Partition scheme Core Storage File systems Page 9 Process Control Launchd Loginwindow Grand Central Dispatch Sandboxing GateKeeper XPC Page 16 Network Access Ethernet Wi-Fi Multihoming IPv6 Remote Access Bonjour Page 21 Document Lifecycle Auto Save Automatic Versions Version Management iCloud Storage Page 24 Data Management Spotlight Time Machine Page 26 Developer Tools LLVM Xcode Instruments Accelerate Automation WebKit Page 33 For More Information3 Core Technologies Overview OS X Mountain Lion Introduction With more than 65 million users—consumers, scientists, animators, developers, system administrators, and more—OS X is the most widely used UNIX® desktop operating system. In addition, OS X is the only UNIX environment that natively runs Microsoft Office, Adobe Photoshop, and thousands of other consumer applications—all side by side with traditional command-line UNIX applications. Tight integration with hardware—from the sleek MacBook Air to the powerful Mac Pro—makes OS X the platform of choice for an emerging generation of power users. This document explores the powerful industry standards and breakthrough innovations in the core technologies that power Apple’s industry-leading user experiences. We walk you through the entire software stack, from firmware and kernel to iCloud and developer tools, to help you understand the many things OS X does for you every time you use your Mac. 4 Core Technologies Overview OS X Mountain Lion BootROM When you turn on the power to a Mac, it activates the BootROM firmware. BootROM, which is part of the computer’s hardware, has two primary responsibilities: it initializes system hardware and it selects an operating system to run. Two BootROM components carry out these functions: • Power-On Self Test (POST) initializes some hardware interfaces and verifies that sufficient memory is available and in a good state. • Extensible Firmware Interface (EFI) does basic hardware initialization and selects which operating system to use. If multiple OS installations are available, BootROM chooses the one that was last selected by the Startup Disk System Preference. The user can override this choice by holding down the Option key while the computer starts up, which causes EFI to display a screen for choosing the startup volume. EFI boot picker screen. System Startup5 Core Technologies Overview OS X Mountain Lion EFI EFI—a standard created by Intel—defines the interface between an operating system and platform firmware. It supersedes the legacy Basic Input Output System (BIOS) and OpenFirmware architectures. Once BootROM is finished and an OS X partition has been selected, control passes to the boot.efi boot loader, which runs inside EFI. The principal job of this boot loader is to load the kernel environment. As it does this, the boot loader draws the “booting” image on the screen. If full-disk encryption is enabled, the boot loader draws the login UI and prompts for the user’s password, which the system needs so it can access the encrypted disk and boot from it. Otherwise, loginwindow draws the login UI. Kernel The OS X kernel is based on FreeBSD and Mach 3.0 and features an extensible architecture based on well-defined kernel programming interfaces (KPIs). OS X was the first operating system to ship as a single install that could boot into either a 32-bit or 64-bit kernel, either of which could run 32-bit and 64-bit applications at full native performance. Starting with Mountain Lion, OS X exclusively uses a 64-bit kernel, but it continues to run both 32-bit and 64-bit applications. Drivers Drivers in OS X are provided by I/O Kit, a collection of system frameworks, libraries, tools, and other resources for creating device drivers. I/O Kit is based on an objectoriented programming model implemented in a restricted form of C++ that omits features unsuitable for use within a multithreaded kernel. By modeling the hardware connected to an OS X system and abstracting common functionality for devices in particular categories, the I/O Kit streamlines the process of device-driver development. I/O Kit helps device manufacturers rapidly create drivers that run safely in a multiprocessing, preemptive, hot-pluggable, power-managed environment. To do this, I/O Kit provides the following: • An object-oriented framework implementing common behavior shared among all drivers and types (families) of drivers • Many families of drivers for developers to build upon • Threading, communication, and data-management primitives for dealing with issues related to multiprocessing, task control, and I/O-transfers • A robust, efficient match-and-load mechanism that scales well to all bus types • The I/O Registry, a database that tracks instantiated objects (such as driver instances) and provides information about them • The I/O Catalog, a database of all I/O Kit classes available on a system • A set of device interfaces—plug-in mechanism that allows applications and other software outside the kernel to communicate with drivers • Excellent overall performance • Support for arbitrarily complex layering of client and provider objects6 Core Technologies Overview OS X Mountain Lion Initialization