ios programming: the big nerd ranch guide (big nerd ranch …englishonlineclub.com/pdf/ios...

747

Upload: others

Post on 08-Jul-2020

23 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 2: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 3: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

iOSProgramming:TheBigNerdRanchGuidebyChristianKeurandAaronHillegass

Copyright©2016BigNerdRanch,LLCAllrightsreserved.PrintedintheUnitedStatesofAmerica.Thispublicationisprotectedbycopyright,andpermissionmustbeobtainedfromthepublisherpriortoanyprohibitedreproduction,storageinaretrievalsystem,ortransmissioninanyformorbyanymeans,electronic,mechanical,photocopying,recording,orlikewise.Forinformationregardingpermissions,contact

BigNerdRanch,LLC200ArizonaAveNEAtlanta,GA30307(770)817-6373http://www.bignerdranch.com/book-comments@bignerdranch.comThe10-gallonhatwithpropellerlogoisatrademarkofBigNerdRanch,LLC.ExclusiveworldwidedistributionoftheEnglisheditionofthisbookby

PearsonTechnologyGroup800East96thStreetIndianapolis,IN46240USAhttp://www.informit.comTheauthorsandpublisherhavetakencareinwritingandprintingthisbookbutmakenoexpressedorimpliedwarrantyofanykindandassumenoresponsibilityforerrorsoromissions.Noliabilityisassumedforincidentalorconsequentialdamagesinconnectionwithorarisingoutoftheuseoftheinformationorprogramscontainedherein.AppStore,Apple,Cocoa,CocoaTouch,Finder,Instruments,iCloud,iPad,iPhone,iPod,iPodtouch,iTunes,Keychain,Mac,MacOS,Multi-Touch,Objective-C,OSX,Quartz,Retina,Safari,andXcodearetrademarksofApple,Inc.,registeredintheU.S.andothercountries.Manyofthedesignationsusedbymanufacturersandsellerstodistinguishtheirproductsareclaimedastrademarks.Wherethosedesignationsappearinthisbook,andthepublisherwasawareofatrademarkclaim,thedesignationshavebeenprintedwithinitialcapitallettersorinallcapitals.PrintISBN-10013468964X

Page 4: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

PrintISBN-13978-0134689647

Sixthedition,firstprinting,December2016ReleaseK.6.1.1

Page 5: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 6: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

AcknowledgmentsWhileournamesappearonthecover,manypeoplehelpedmakethisbookareality.Wewouldliketotakethischancetothankthem.

FirstandforemostwewouldliketothankJoeConwayforhisworkontheearliereditionsofthisbook.Heauthoredthefirstthreeeditionsandcontributedgreatlytothefourtheditionaswell.Manyofthewordsinthisbookarestillhis,andforthat,weareverygrateful.JuanPabloClaudewrotesomeofthecontentandcontributedhisexpertiseandopinionstomakethisbookevenbetter.Hisworkisgreatlyappreciated.Acoupleotherpeoplewentaboveandbeyondwiththeirhelponthisbook.TheyareMikeyWardandChrisMorris.TheotherinstructorswhoteachtheiOSBootcampfedusanever-endingstreamofsuggestionsandcorrections.TheyareBenScheirman,BolotKerimbaev,BrianHardy,ChrisMorris,JJManton,JohnGallagher,JonathanBlocksom,JosephDixon,JuanPabloClaude,MarkDalrymple,MattBezark,MattMathias,MikeZornek,MikeyWard,PouriaAlmassi,RobertEdwards,RodStrougo,ScottRitchie,StepChristopher,ThomasWard,TJUsiyan,TomHarrington,andZacharyWaldowski.Theseinstructorswereoftenaidedbytheirstudentsinfindingbookerrata,somanythanksareduetoallthestudentswhoattendtheiOSBootcamp.ThankstoalloftheemployeesatBigNerdRanchwhohelpedreviewthebook,providedsuggestions,andfounderrata.Ourtirelesseditor,ElizabethHoladay,tookourdistractedmumblingsandmadethemintoreadableprose.AnnaBentleyandSimonePaymentjumpedintoprovidecopyeditingandproofing.EllieVolckhausendesignedthecover.(Thephotoisofthebottombracketofabicycleframe.)ChrisLoperatIntelligentEnglish.comdesignedandproducedtheprintandebookversionsofthebook.TheamazingteamatPearsonTechnologyGrouppatientlyguidedusthroughthebusinessendofbookpublishing.

Thefinalandmostimportantthanksgoestoourstudents,whosequestionsinspiredustowritethisbookandwhosefrustrationsinspiredustomakeitclearandcomprehensible.

Page 7: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

TableofContentsIntroduction

PrerequisitesWhatHasChangedintheSixthEdition?OurTeachingPhilosophyHowtoUseThisBookUsinganeBookHowThisBookIsOrganizedStyleChoicesTypographicalConventionsNecessaryHardwareandSoftware

1.ASimpleiOSApplicationCreatinganXcodeProjectModel-View-ControllerDesigningQuizInterfaceBuilderBuildingtheInterface

CreatingviewobjectsConfiguringviewobjectsRunningonthesimulatorAbriefintroductiontoAutoLayoutMakingconnections

CreatingtheModelLayerImplementingactionmethodsLoadingthefirstquestion

BuildingtheFinishedApplicationApplicationIconsLaunchScreen

2.TheSwiftLanguageTypesinSwiftUsingStandardTypes

InferringtypesSpecifyingtypesLiteralsandsubscriptingInitializersPropertiesInstancemethods

OptionalsSubscriptingdictionaries

LoopsandStringInterpolationEnumerationsandtheSwitchStatement

Page 8: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

EnumerationsandrawvaluesExploringApple’sSwiftDocumentation

3.ViewsandtheViewHierarchyViewBasicsTheViewHierarchyCreatingaNewProjectViewsandFrames

CustomizingthelabelsTheAutoLayoutSystem

ThealignmentrectangleandlayoutattributesConstraintsAddingconstraintsinInterfaceBuilderIntrinsiccontentsizeMisplacedviewsAddingmoreconstraints

BronzeChallenge:MoreAutoLayoutPractice4.TextInputandDelegation

TextEditingKeyboardattributesRespondingtotextfieldchangesDismissingthekeyboard

ImplementingtheTemperatureConversionNumberformatters

DelegationConformingtoaprotocolUsingadelegateMoreonprotocols

BronzeChallenge:DisallowAlphabeticCharacters5.ViewControllers

TheViewofaViewControllerSettingtheInitialViewControllerUITabBarController

TabbaritemsLoadedandAppearingViews

AccessingsubviewsInteractingwithViewControllersandTheirViewsSilverChallenge:DarkModeFortheMoreCurious:RetinaDisplay

6.ProgrammaticViewsCreatingaViewProgrammaticallyProgrammaticConstraints

AnchorsActivatingconstraintsLayoutguides

Page 9: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

MarginsExplicitconstraints

ProgrammaticControlsBronzeChallenge:AnotherTabSilverChallenge:User ’sLocationGoldChallenge:DroppingPinsFortheMoreCurious:NSAutoresizingMaskLayoutConstraint

7.LocalizationInternationalization

FormattersBaseinternationalizationPreparingforlocalization

LocalizationNSLocalizedStringandstringstables

BronzeChallenge:AnotherLocalizationFortheMoreCurious:Bundle’sRoleinInternationalizationFortheMoreCurious:ImportingandExportingasXLIFF

8.ControllingAnimationsBasicAnimations

ClosuresAnotherLabelAnimationCompletionAnimatingConstraintsTimingFunctionsBronzeChallenge:SpringAnimationsSilverChallenge:LayoutGuides

9.DebuggingABuggyProjectDebuggingBasics

InterpretingconsolemessagesFixingthefirstbugCavemandebugging

TheXcodeDebugger:LLDBSettingbreakpointsSteppingthroughcodeTheLLDBconsole

10.UITableViewandUITableViewControllerBeginningtheHomepwnerApplicationUITableViewController

SubclassingUITableViewControllerCreatingtheItemClass

CustominitializersUITableView’sDataSource

Givingthecontrolleraccesstothestore

Page 10: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

ImplementingdatasourcemethodsUITableViewCells

CreatingandretrievingUITableViewCellsReusingUITableViewCells

ContentInsetsBronzeChallenge:SectionsSilverChallenge:ConstantRowsGoldChallenge:CustomizingtheTable

11.EditingUITableViewEditingModeAddingRowsDeletingRowsMovingRowsDisplayingUserAlertsDesignPatternsBronzeChallenge:RenamingtheDeleteButtonSilverChallenge:PreventingReorderingGoldChallenge:ReallyPreventingReordering

12.SubclassingUITableViewCellCreatingItemCellExposingthePropertiesofItemCellUsingItemCellDynamicCellHeightsDynamicType

RespondingtouserchangesBronzeChallenge:CellColors

13.StackViewsUsingUIStackView

ImplicitconstraintsStackviewdistributionNestedstackviewsStackviewspacing

SeguesHookingUptheContentPassingDataAroundBronzeChallenge:MoreStackViews

14.UINavigationControllerUINavigationControllerNavigatingwithUINavigationControllerAppearingandDisappearingViewsDismissingtheKeyboard

EventhandlingbasicsDismissingbypressingtheReturnkeyDismissingbytappingelsewhere

Page 11: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

UINavigationBarAddingbuttonstothenavigationbar

BronzeChallenge:DisplayingaNumberPadSilverChallenge:ACustomUITextFieldGoldChallenge:PushingMoreViewControllers

15.CameraDisplayingImagesandUIImageView

AddingacamerabuttonTakingPicturesandUIImagePickerController

Settingtheimagepicker ’ssourceTypeSettingtheimagepicker ’sdelegatePresentingtheimagepickermodallyPermissionsSavingtheimage

CreatingImageStoreGivingViewControllersAccesstotheImageStoreCreatingandUsingKeysWrappingUpImageStoreBronzeChallenge:EditinganImageSilverChallenge:RemovinganImageGoldChallenge:CameraOverlayFortheMoreCurious:NavigatingImplementationFiles

//MARK:16.Saving,Loading,andApplicationStates

ArchivingApplicationSandbox

ConstructingafileURLNSKeyedArchiverandNSKeyedUnarchiver

LoadingfilesApplicationStatesandTransitionsWritingtotheFilesystemwithDataErrorHandlingBronzeChallenge:PNGFortheMoreCurious:ApplicationStateTransitionsFortheMoreCurious:ReadingandWritingtotheFilesystemFortheMoreCurious:TheApplicationBundle

17.SizeClassesModifyingTraitsforaSpecificSizeClassBronzeChallenge:StackedTextFieldandLabels

18.TouchEventsandUIResponderTouchEventsCreatingtheTouchTrackerApplicationCreatingtheLineStruct

Structs

Page 12: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

ValuetypesvsreferencetypesCreatingDrawViewDrawingwithDrawViewTurningTouchesintoLines

Handlingmultipletouches@IBInspectableSilverChallenge:ColorsGoldChallenge:CirclesFortheMoreCurious:TheResponderChainFortheMoreCurious:UIControl

19.UIGestureRecognizerandUIMenuControllerUIGestureRecognizerSubclassesDetectingTapswithUITapGestureRecognizerMultipleGestureRecognizersUIMenuControllerMoreGestureRecognizers

UILongPressGestureRecognizerUIPanGestureRecognizerandsimultaneousrecognizers

MoreonUIGestureRecognizerSilverChallenge:MysteriousLinesGoldChallenge:SpeedandSizePlatinumChallenge:ColorsFortheMoreCurious:UIMenuControllerandUIResponderStandardEditActions

20.WebServicesStartingthePhotoramaApplicationBuildingtheURL

FormattingURLsandrequestsURLComponents

SendingtheRequestURLSession

ModelingthePhotoJSONData

JSONSerializationEnumerationsandassociatedvaluesParsingJSONdata

DownloadingandDisplayingtheImageDataTheMainThreadBronzeChallenge:PrintingtheResponseInformationSilverChallenge:FetchRecentPhotosfromFlickrFortheMoreCurious:HTTP

21.CollectionViewsDisplayingtheGridCollectionViewDataSourceCustomizingtheLayout

Page 13: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

CreatingaCustomUICollectionViewCellDownloadingtheImageData

ExtensionsImagecaching

NavigatingtoaPhotoSilverChallenge:UpdatedItemSizesGoldChallenge:CreatingaCustomLayout

22.CoreDataObjectGraphsEntities

ModelingentitiesTransformableattributesNSManagedObjectandsubclasses

NSPersistentContainerUpdatingItems

InsertingintothecontextSavingchanges

UpdatingtheDataSourceFetchrequestsandpredicates

BronzeChallenge:PhotoViewCountFortheMoreCurious:TheCoreDataStack

NSManagedObjectModelNSPersistentStoreCoordinatorNSManagedObjectContext

23.CoreDataRelationshipsRelationshipsAddingTagstotheInterfaceBackgroundTasksSilverChallenge:Favorites

24.AccessibilityVoiceOver

TestingVoiceOverAccessibilityinPhotorama

25.AfterwordWhattoDoNextShamelessPlugs

Index

Page 14: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 15: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

IntroductionAsanaspiringiOSdeveloper,youfacethreemajortasks:

YoumustlearntheSwiftlanguage.SwiftistherecommendeddevelopmentlanguageforiOS.ThefirsttwochaptersofthisbookaredesignedtogiveyouaworkingknowledgeofSwift.Youmustmasterthebigideas.Theseincludethingslikedelegation,archiving,andtheproperuseofviewcontrollers.Thebigideastakeafewdaystounderstand.Whenyoureachthehalfwaypointofthisbook,youwillunderstandthesebigideas.Youmustmastertheframeworks.TheeventualgoalistoknowhowtouseeverymethodofeveryclassineveryframeworkiniOS.Thisisaprojectforalifetime:TherearehundredsofclassesandthousandsofmethodsavailableiniOS,andAppleaddsmoreclassesandmethodswitheveryreleaseofiOS.Inthisbook,youwillbeintroducedtoeachofthesubsystemsthatmakeuptheiOSSDK,butyouwillnotstudyeachonedeeply.Instead,ourgoalistogetyoutothepointwhereyoucansearchandunderstandApple’sreferencedocumentation.

WehaveusedthismaterialmanytimesatouriOSbootcampsatBigNerdRanch.ItiswelltestedandhashelpedthousandsofpeoplebecomeiOSdevelopers.Wesincerelyhopethatitprovesusefultoyou.

Page 16: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Prerequisites

ThisbookassumesthatyouarealreadymotivatedtolearntowriteiOSapps.WewillnotspendanytimeconvincingyouthattheiPhone,iPad,andiPodtoucharecompellingpiecesoftechnology.Wealsoassumethatyouhavesomeexperienceprogrammingandknowsomethingaboutobject-orientedprogramming.Ifthisisnottrue,youshouldprobablystartwithSwiftProgramming:TheBigNerdRanchGuide.

Page 17: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 18: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

WhatHasChangedintheSixthEdition?

AllofthecodeinthisbookhasbeenupdatedforSwift3.0,whichwasamajorupdatetotheSwiftlanguage.Throughoutthebook,youwillseehowtouseSwift’scapabilitiesandfeaturestowritebetteriOSapplications.WehavecometoloveSwiftatBigNerdRanchandbelieveyouwill,too.OtheradditionsincludenewchaptersondebuggingandaccessibilityandimprovedcoverageofCoreData.WehavealsoupdatedvariouschapterstousethetechnologiesandAPIsintroducediniOS10.ThiseditionassumesthatthereaderisusingXcode8.1orlaterandrunningapplicationsonaniOS10orlaterdevice.Besidestheseobviouschanges,wemadethousandsoftinyimprovementsthatwereinspiredbyquestionsfromourreadersandourstudents.Everychapterofthisbookisjustalittlebetterthanthecorrespondingchapterfromthefifthedition.

Page 19: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 20: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

OurTeachingPhilosophy

ThisbookwillteachyoutheessentialconceptsofiOSprogramming.Atthesametime,youwilltypeinalotofcodeandbuildabunchofapplications.Bytheendofthebook,youwillhaveknowledgeandexperience.However,alltheknowledgeshouldnot(and,inthisbook,willnot)comefirst.Thatisthetraditionalwayoflearningwehaveallcometoknowandhate.Instead,wetakealearn-while-doingapproach.Developmentconceptsandactualcodinggotogether.HereiswhatwehavelearnedovertheyearsofteachingiOSprogramming:

Wehavelearnedwhatideaspeoplemustgrasptogetstartedprogramming,andwefocusonthatsubset.Wehavelearnedthatpeoplelearnbestwhentheseconceptsareintroducedastheyareneeded.Wehavelearnedthatprogrammingknowledgeandexperiencegrowbestwhentheygrowtogether.Wehavelearnedthat“goingthroughthemotions”ismuchmoreimportantthanitsounds.Manytimeswewillaskyoutostarttypingincodebeforeyouunderstandit.Werealizethatyoumayfeellikeatrainedmonkeytypinginabunchofcodethatyoudonotfullygrasp.Butthebestwaytolearncodingistofindandfixyourtypos.Farfrombeingadrag,thisbasicdebuggingiswhereyoureallylearntheinsandoutsofthecode.Thatiswhyweencourageyoutotypeinthecodeyourself.Youcouldjustdownloadit,butcopyingandpastingisnotprogramming.Wewantbetterforyouandyourskills.

Whatdoesthismeanforyou,thereader?Tolearnthiswaytakessometrust–andweappreciateyours.Italsotakespatience.Asweleadyouthroughthesechapters,wewilltrytokeepyoucomfortableandtellyouwhatishappening.However,therewillbetimeswhenyouwillhavetotakeourwordforit.(Ifyouthinkthiswillbugyou,keepreading–wehavesomeideasthatmighthelp.)Donotgetdiscouragedifyourunacrossaconceptthatyoudonotunderstandrightaway.Rememberthatweareintentionallynotprovidingalltheknowledgeyouwilleverneedallatonce.Ifaconceptseemsunclear,wewilllikelydiscussitinmoredetaillaterwhenitbecomesnecessary.Andsomethingsthatarenotclearatthebeginningwillsuddenlymakesensewhenyouimplementthemthefirst(orthetwelfth)time.Peoplelearndifferently.Itispossiblethatyouwilllovehowwehandoutconceptsonanas-neededbasis.Itisalsopossiblethatyouwillfinditfrustrating.Incaseofthelatter,herearesomeoptions:

Takeadeepbreathandwaititout.Wewillgetthere,andsowillyou.Checktheindex.Wewillletitslideifyoulookaheadandreadthroughamoreadvanceddiscussionthatoccurslaterinthebook.ChecktheonlineAppledocumentation.Thisisanessentialdevelopertool,andyouwillwantplentyofpracticeusingit.Consultitearlyandoften.IfSwiftorobject-orientedprogrammingconceptsaregivingyouahardtime(orifyou

Page 21: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

thinktheywill),youmightconsiderbackingupandreadingourSwiftProgramming:TheBigNerdRanchGuide.

Page 22: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 23: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

HowtoUseThisBook

ThisbookisbasedontheclassweteachatBigNerdRanch.Assuch,itwasdesignedtobeconsumedinacertainmanner.Setyourselfareasonablegoal,like,“Iwilldoonechaptereveryday.”Whenyousitdowntoattackachapter,findaquietplacewhereyouwillnotbeinterruptedforatleastanhour.Shutdownyouremail,yourTwitterclient,andyourchatprogram.Thisisnotatimeformultitasking;youwillneedtoconcentrate.Dotheactualprogramming.Youcanreadthroughachapterfirst,ifyoulike.Butthereallearningcomeswhenyousitdownandcodeasyougo.Youwillnotreallyunderstandtheideauntilyouhavewrittenaprogramthatusesitand,perhapsmoreimportantly,debuggedthatprogram.Acoupleoftheexercisesrequiresupportingfiles.Forexample,inthefirstchapteryouwillneedaniconforyourQuizapplication,andwehaveoneforyou.Youcandownloadtheresourcesandsolutionstotheexercisesfromwww.bignerdranch.com/solutions/iOSProgramming6ed.zip.Therearetwotypesoflearning.WhenyoulearnaboutthePeloponnesianWar,youaresimplyaddingdetailstoascaffoldingofideasthatyoualreadyunderstand.Thisiswhatwewillcall“EasyLearning.”Yes,learningaboutthePeloponnesianWarcantakealongtime,butyouareseldomflummoxedbyit.LearningiOSprogramming,ontheotherhand,is“HardLearning,”andyoumayfindyourselfquitebaffledattimes,especiallyinthefirstfewdays.Inwritingthisbook,wehavetriedtocreateanexperiencethatwilleaseyouoverthebumpsinthelearningcurve.Herearetwothingsyoucandotomakethejourneyeasier:

FindsomeonewhoalreadyknowshowtowriteiOSapplicationsandwillansweryourquestions.Inparticular,gettingyourapplicationontoadevicethefirsttimeisusuallyveryfrustratingifyouaredoingitwithoutthehelpofanexperienceddeveloper.Getenoughsleep.Sleepypeopledonotrememberwhattheyhavelearned.

Page 24: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 25: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

UsinganeBook

IfyouarereadingthisbookonaKindleorKindleforiPad,wewanttopointoutthatreadingthecodemaybetrickyattimes.Longerlinesofcodewillwraptoasecondlinedependingonyourselectedfontsize.ThisbothersusbecausewearereallyconscientiousatBigNerdRanchaboutthewayourcodeappearsonthepage.Clearvisualpatternsincodemakethatcodeeasiertounderstand.Thelongestlinesofcodeinthisbookare86monospacecharacters,likethisone.cell=tableView.dequeueReusableCell(withIdentifier:"UITableViewCell",for:idxPath1)

YoucanplaywithyourKindle’ssettingstofindthebestforviewinglongcodelines.Whenyougettothepointwhereyouareactuallytypingincode,wesuggestopeningthebookonyourMacinKindleforMac,afreeapplicationyoucandownloadfromAmazon.com.Maketheapplicationwindowlargeenoughsothatyoucanseethecodewithnowrappinglines.Youwillalsobeabletoseethefiguresinfulldetail.

Page 26: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 27: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

HowThisBookIsOrganized

Inthisbook,eachchapteraddressesoneormoreideasofiOSdevelopmentthroughdiscussionandhands-onpractice.Formorecodingpractice,mostchaptersincludechallengeexercises.Weencourageyoutotakeonatleastsomeofthese.TheyareexcellentforfirmingupyourgraspoftheconceptsintroducedinthechapterandformakingyouamoreconfidentiOSprogrammer.Finally,mostchaptersconcludewithoneortwoFortheMoreCurioussectionsthatexplaincertainconsequencesoftheconceptsthatwereintroducedearlier.Chapter1introducesyoutoiOSprogrammingasyoubuildanddeployatinyapplicationcalledQuiz.YouwillgetyourfeetwetwithXcodeandtheiOSsimulatoralongwithallthestepsforcreatingprojectsandfiles.ThechapterincludesadiscussionofModel-View-ControllerandhowitrelatestoiOSdevelopment.Chapter2providesanoverviewofSwift,includingbasicsyntax,types,optionals,initialization,andhowSwiftisabletointeractwiththeexistingiOSframeworks.Youwillalsogetexperienceworkinginaplayground,Xcode’sprototypingtool.InChapter3,youwillfocusontheiOSuserinterfaceasyoulearnaboutviewsandtheviewhierarchyandcreateanapplicationcalledWorldTrotter.Chapter4introducesdelegation,animportantiOSdesignpattern.YouwillalsoaddatextfieldtoWorldTrotter.InChapter5,youwillexpandWorldTrotterandlearnaboutusingviewcontrollersformanaginguserinterfaces.Youwillgetpracticeworkingwithviewsandviewcontrollersaswellasnavigatingbetweenscreensusingatabbar.InChapter6,youwilllearnhowtomanageviewsandviewcontrollersincode.YouwilladdasegmentedcontroltoWorldTrotterthatwillletyouswitchbetweenvariousmaptypes.Chapter7introducestheconceptsandtechniquesofinternationalizationandlocalization.YouwilllearnaboutLocale,stringstables,andBundleasyoulocalizepartsofWorldTrotter.InChapter8,youwilllearnaboutandadddifferenttypesofanimationstotheQuizprojectthatyoucreatedinChapter1.Chapter9willwalkyouthroughsomeofthetoolsatyourdisposalfordebugging–findingandfixingissuesinyourapplication.Chapter10introducesthelargestapplicationinthebook–Homepwner.(“Homepwner”isnotatypo;youcanfindthedefinitionof“pwn”atwww.wiktionary.org.)Thisapplicationkeepsarecordofyouritemsincaseoffireorothercatastrophe.Homepwnerwilltakeeightchapterstocomplete.InChapter10–Chapter12,youwillworkwithtables.Youwilllearnabouttableviews,theirviewcontrollers,andtheirdatasources.Youwilllearnhowtodisplaydatainatable,howtoallowtheusertoeditthetable,andhowtoimprovetheinterface.Chapter13introducesstackviews,whichwillhelpyoucreatecomplexinterfaceseasily.YouwilluseastackviewtoaddanewscreentoHomepwnerthatdisplaysanitem’sdetails.

Page 28: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Chapter14buildsonthenavigationexperiencegainedinChapter5.YouwilluseUINavigationControllertogiveHomepwneradrill-downinterfaceandanavigationbar.Chapter15introducesthecamera.YouwilltakepicturesanddisplayandstoreimagesinHomepwner.InChapter16,youwilladdpersistencetoHomepwner,usingarchivingtosaveandloadtheapplicationdata.InChapter17,youwilllearnaboutsizeclasses,andyouwillusethesetoupdateHomepwner’sinterfacetoscalewellacrossvariousscreensizes.InChapter18andChapter19,youwillcreateadrawingapplicationnamedTouchTrackertolearnabouttouchevents.YouwillseehowtoaddmultitouchcapabilityandhowtouseUIGestureRecognizertorespondtoparticulargestures.Youwillalsogetexperiencewiththefirstresponderandresponderchainconceptsandmorepracticeusingstructuresanddictionaries.Chapter20introduceswebservicesasyoucreatethePhotoramaapplication.ThisapplicationfetchesandparsesJSONdatafromaserverusingURLSessionandJSONSerialization.InChapter21,youwilllearnaboutcollectionviewsasyoubuildaninterfaceforPhotoramausingUICollectionViewandUICollectionViewCell.InChapter22andChapter23,youwilladdpersistencetoPhotoramausingCoreData.YouwillstoreandloadimagesandassociateddatausinganNSManagedObjectContext.Chapter24willwalkyouthroughmakingyourapplicationsaccessibletomorepeoplebyaddingVoiceOverinformation.

Page 29: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 30: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

StyleChoices

Thisbookcontainsalotofcode.Wehaveattemptedtomakethatcodeandthedesignsbehinditexemplary.Wehavedoneourbesttofollowtheidiomsofthecommunity,butattimeswehavewanderedfromwhatyoumightseeinApple’ssamplecodeorcodeyoumightfindinotherbooks.Inparticular,youshouldknowupfrontthatwenearlyalwaysstartaprojectwiththesimplesttemplateproject:thesingleviewapplication.Whenyourappworks,youwillknowitisbecauseofyourefforts–notbecauseofbehaviorbuiltintothetemplate.

Page 31: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 32: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

TypographicalConventions

Tomakethisbookeasiertoread,certainitemsappearincertainfonts.Classes,types,methods,andfunctionsappearinabold,fixed-widthfont.Classesandtypesstartwithcapitalletters,andmethodsandfunctionsstartwithlowercaseletters.Forexample,“IntheloadView()methodoftheRexViewControllerclass,createaconstantoftypeString.”Variables,constants,andfilenamesappearinafixed-widthfontbutarenotbold.Soyouwillsee,“InViewController.swift,addavariablenamedfidoandinitializeitto"Rufus".”Applicationnames,menuchoices,andbuttonnamesappearinagraysansseriffont.(IfyourKindledeviceorappdoesnothaveasansseriffont,theywillappearingrayinthebodyfont.)Forexample,“OpenXcodeandselectNewProject...fromtheFilemenu.SelectSingleViewApplicationandthenclickNext.”Allcodeblocksareinafixed-widthfont.Codethatyouneedtotypeinisbold;codethatyouneedtodeleteisstruckthrough.Forexample,inthefollowingcode,youwoulddeletethelineimportFoundationandtypeinthetwolinesbeginning@IBOutlet.Theotherlinesarealreadyinthecodeandareincludedtoletyouknowwheretoaddthenewlines.importFoundation

importUIKit

classViewController:UIViewController{

@IBOutletvarquestionLabel:UILabel!

@IBOutletvaranswerLabel:UILabel!

}

Page 33: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 34: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

NecessaryHardwareandSoftware

Tobuildtheapplicationsinthisbook,youmusthaveXcode8.1,whichrequiresaMacrunningmacOSElCapitanversion10.11.4orlater.Xcode,Apple’sIntegratedDevelopmentEnvironment,isavailableontheAppStore.XcodeincludestheiOSSDK,theiOSsimulator,andotherdevelopmenttools.YoushouldjointheAppleDeveloperProgram,whichcosts$99/year,because:

Downloadingthelatestdevelopertoolsisfreeformembers.Youcannotputanappinthestoreuntilyouareamember.

Ifyouaregoingtotakethetimetoworkthroughthisentirebook,membershipintheAppleDeveloperProgramisworththecost.Gotodeveloper.apple.com/programs/ios/tojoin.WhataboutiOSdevices?MostoftheapplicationsyouwilldevelopinthefirsthalfofthebookareforiPhone,butyouwillbeabletorunthemonaniPad.OntheiPadscreen,iPhoneapplicationsappearinaniPhone-sizedwindow.NotacompellinguseofiPad,butthatisOKwhenyouarestartingwithiOS.Intheearlychapters,youwillbefocusedonlearningthefundamentalsoftheiOSSDK,andthesearethesameacrossiOSdevices.Laterinthebook,youwillseehowtomakeapplicationsrunnativelyonbothiOSdevicefamilies.Excitedyet?Good.Let’sgetstarted.

Page 35: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 36: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

1ASimpleiOSApplication

Inthischapter,youaregoingtowriteaniOSapplicationnamedQuiz.Thisapplicationwillshowaquestionandthenrevealtheanswerwhentheusertapsabutton.Tappinganotherbuttonwillshowtheuseranewquestion(Figure1.1).Figure1.1Yourfirstapplication:Quiz

WhenyouarewritinganiOSapplication,youmustanswertwobasicquestions:HowdoIgetmyobjectscreatedandconfiguredproperly?(Example:“IwantabuttonherethatsaysNextQuestion.”)HowdoImakemyapprespondtouserinteraction?(Example:“Whentheusertapsthebutton,Iwantthispieceofcodetobeexecuted.”)

Mostofthisbookisdedicatedtoansweringthesequestions.Asyougothroughthisfirstchapter,youwillprobablynotunderstandeverythingthatyouaredoing,andyoumayfeelridiculousjustgoingthroughthemotions.Butgoingthroughthe

Page 37: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

motionsisenoughfornow.Mimicryisapowerfulformoflearning;itishowyoulearnedtospeak,anditishowyouwillstartiOSprogramming.Asyoubecomemorecapable,youwillexperimentandchallengeyourselftodocreativethingsontheplatform.Fornow,goaheadanddowhatweshowyou.Thedetailswillbeexplainedinlaterchapters.

Page 38: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

CreatinganXcodeProject

OpenXcodeand,fromtheFilemenu,selectNew→Project....(IfXcodeopenstoawelcomescreen,selectCreateanewXcodeproject.)Anewworkspacewindowwillappearandasheetwillslidedownfromitstoolbar.Atthetop,findtheiOSsectionandthentheApplicationarea(Figure1.2).Youareofferedseveralapplicationtemplatestochoosefrom.SelectSingleViewApplication.Figure1.2Creatingaproject

ThisbookwascreatedforXcode8.1.ThenamesofthesetemplatesmaychangewithnewXcodereleases.IfyoudonotseeaSingleViewApplicationtemplate,usethesimplest-soundingtemplate.YoucanalsovisittheBigNerdRanchforumforthisbookatforums.bignerdranch.comforhelpworkingwithnewerversionsofXcode.ClickNextand,inthenextsheet,enterQuizfortheProductName(Figure1.3).Theorganizationnameandidentifierarerequiredtocontinue.YoucanuseBigNerdRanchoranyorganizationnameyouwouldlike.Fortheorganizationidentifier,youcanusecom.bignerdranchorcom.yourcompanynamehere.FromtheLanguagepop-upmenu,chooseSwift,andfromtheDevicespop-upmenu,chooseUniversal.MakesurethattheUseCoreDatacheckboxisunchecked.

Page 39: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure1.3Configuringanewproject

ClickNextand,inthefinalsheet,savetheprojectinthedirectorywhereyouplantostoretheexercisesinthisbook.ClickCreatetocreatetheQuizproject.YournewprojectopensintheXcodeworkspacewindow(Figure1.4).

Page 40: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure1.4Xcodeworkspacewindow

Thelefthandsideoftheworkspacewindowisthenavigatorarea.Thisareadisplaysdifferentnavigators–toolsthatshowyoudifferentpartsofyourproject.Youcanopenanavigatorbyselectingoneoftheiconsinthenavigatorselector,whichisthebarjustabovethenavigatorarea.Thenavigatorcurrentlyopenistheprojectnavigator.Theprojectnavigatorshowsyouthefilesthatmakeupaproject(Figure1.5).Youcanselectoneofthesefilestoopenitintheeditorareatotherightofthenavigatorarea.Thefilesintheprojectnavigatorcanbegroupedintofolderstohelpyouorganizeyourproject.Afewgroupshavebeencreatedbythetemplateforyou.Youcanrenamethem,ifyouwant,oraddnewones.Thegroupsarepurelyfortheorganizationoffilesanddonotcorrelatetothefilesysteminanyway.

Page 41: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure1.5Quizapplication’sfilesintheprojectnavigator

Page 42: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 43: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Model-View-Controller

Beforeyoubeginyourapplication,let’sdiscussakeyconceptinapplicationarchitecture:Model-View-Controller,orMVC.MVCisadesignpatternusediniOSdevelopment.InMVC,everyinstancebelongstoeitherthemodellayer,theviewlayer,orthecontrollerlayer.(Layerheresimplyreferstooneormoreobjectsthattogetherfulfillarole.)

Themodellayerholdsdataandknowsnothingabouttheuserinterface,orUI.InQuiz,themodelwillconsistoftwoorderedlistsofstrings:oneforquestionsandanotherforanswers.Usually,instancesinthemodellayerrepresentrealthingsintheworldoftheuser.Forexample,whenyouwriteanappforaninsurancecompany,yourmodelwillalmostcertainlycontainacustomtypecalledInsurancePolicy.Theviewlayercontainsobjectsthatarevisibletotheuser.Examplesofviewobjects,orviews,arebuttons,textfields,andsliders.Viewobjectsmakeupanapplication’sUI.InQuiz,thelabelsshowingthequestionandanswerandthebuttonsbeneaththemareviewobjects.Thecontrollerlayeriswheretheapplicationismanaged.Controllerobjects,orcontrollers,arethemanagersofanapplication.Controllersconfiguretheviewsthattheuserseesandmakesurethattheviewandmodelobjectsstaysynchronized.Ingeneral,controllerstypicallyhandle“Andthen?”questions.Forexample,whentheuserselectsanitemfromalist,thecontrollerdetermineswhattheuserseesnext.

Figure1.6showstheflowofcontrolinanapplicationinresponsetouserinput,suchastheusertappingabutton.Figure1.6MVCpattern

Noticethatmodelsandviewsdonottalktoeachotherdirectly;controllerssitsquarelyinthemiddleofeverything,receivingmessagesanddispatchinginstructions.

Page 44: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 45: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

DesigningQuiz

YouaregoingtowritetheQuizapplicationusingtheMVCpattern.Hereisabreakdownoftheinstancesyouwillbecreatingandworkingwith:

Themodellayerwillconsistoftwoinstancesof[String].TheviewlayerwillconsistoftwoinstancesofUILabelandtwoinstancesofUIButton.ThecontrollerlayerwillconsistofaninstanceofViewController.

TheseinstancesandtheirrelationshipsarelaidoutinthediagramforQuizshowninFigure1.7.Figure1.7ObjectdiagramforQuiz

Figure1.7isthebigpictureofhowthefinishedQuizapplicationwillwork.Forexample,whentheNextQuestionbuttonistapped,itwilltriggeramethodinViewController.Amethodisalotlikeafunction–alistofinstructionstobeexecuted.Thismethodwillretrieveanewquestionfromthearrayofquestionsandaskthetoplabeltodisplaythatquestion.ItisOKifthisdiagramdoesnotmakesenseyet–itwillbytheendofthechapter.Referbacktoitasyoubuildtheapptoseehowitistakingshape.YouaregoingtobuildQuizinsteps,startingwiththevisualinterfacefortheapplication.

Page 46: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 47: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

InterfaceBuilder

YouareusingtheSingleViewApplicationtemplatebecauseitisthesimplesttemplatethatXcodeoffers.Still,thistemplatehasasignificantamountofmagicinthatsomecriticalcomponentshavealreadybeensetupforyou.Fornow,youwilljustusethesecomponents,withoutattemptingtogainadeepunderstandingofhowtheywork.Therestofthebookwillbeconcernedwiththosedetails.Intheprojectnavigator,clickonceontheMain.storyboardfile.Xcodewillopenitsgraphic-styleeditorcalledInterfaceBuilder.InterfaceBuilderdividestheeditorareaintotwosections:thedocumentoutline,onthelefthandside,andthecanvas,ontheright.ThisisshowninFigure1.8.Ifwhatyouseeinyoureditorareadoesnotmatchthefigure,youmayhavetoclickontheShowDocumentOutlinebutton.(Ifyouhaveadditionalareasshowing,donotworryaboutthem.)Youmayalsohavetoclickonthedisclosuretrianglesinthedocumentoutlinetorevealcontent.Figure1.8InterfaceBuildershowingMain.storyboard

Page 48: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

TherectanglethatyouseeintheInterfaceBuildercanvasiscalledasceneandrepresentstheonly“screen”orviewyourapplicationhasatthistime(rememberthatyouusedthesingleviewapplicationtemplatetocreatethisproject).Inthenextsection,youwilllearnhowtocreateaUIforyourapplicationusingInterfaceBuilder.InterfaceBuilderletsyoudragobjectsfromalibraryontothecanvastocreateinstancesandalsoletsyouestablishconnectionsbetweenthoseobjectsandyourcode.Theseconnectionscanresultincodebeingcalledbyauserinteraction.AcrucialfeatureofInterfaceBuilderisthatitisnotagraphicalrepresentationofcodecontainedinotherfiles.InterfaceBuilderisanobjecteditorthatcancreateinstancesofobjectsandmanipulatetheirproperties.Whenyouaredoneeditinganinterface,itdoesnotgeneratecodethatcorrespondstotheworkyouhavedone.A.storyboardfileisanarchiveofobjectinstancestobeloadedintomemorywhennecessary.

Page 49: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 50: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

BuildingtheInterface

Let’sgetstartedonyourinterface.YouhaveselectedMain.storyboardtorevealitssinglesceneinthecanvas(Figure1.9).Figure1.9ThesceneinMain.storyboard

Tostart,makesureyoursceneissizedforiPhone7.Atthebottomofthecanvas,findtheViewasbutton.ItwilllikelysaysomethinglikeViewas:iPhone7(wChR).(ThewChRwillnotmakesenserightnow;wewillexplainitinChapter17.)IfitsaysiPhone7already,thenyouareallset.Ifnot,clickontheViewasbuttonandselectthefourthdevicefromtheleft,whichcorrespondstoiPhone7(Figure1.10).

Page 51: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure1.10ViewingthesceneforiPhone7

Itistimetoaddyourviewobjectstothatblankslate.

Creatingviewobjects

MakesurethattheutilityareawithinXcode’swindowisvisible.Youmayneedtoclickontherightmostbuttonofthe controlinthetop-rightcornerofthewindow.Theutilityareaistotherightoftheeditorareaandhastwosections:theinspectorandthelibrary.Thetopsectionistheinspector,whichdisplayssettingsforafileorobjectthatisselectedintheeditorarea.Thebottomsectionisthelibrary,whichlistsitemsthatyoucanaddtoafileorproject.Atthetopofeachsectionintheutilityareaisaselectorfordifferentinspectorsandlibraries(Figure1.11).

Page 52: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure1.11Xcodeutilityarea

Yourapplicationinterfacerequiresfourviewobjects:twobuttonstoacceptuserinputandtwotextlabelstodisplayinformation.Toaddthem,firstmakesureyoucanseetheobjectlibrary,asshowninFigure1.11,byselectingthe tabfromthelibraryselector.Theobjectlibrarycontainstheobjectsthatyoucanaddtoastoryboardfiletocomposeyourinterface.FindtheLabelobjectbyeitherscrollingdownthroughthelistorbyusingthesearchbaratthebottomofthelibrary.Selectthisobjectinthelibraryanddragitontotheviewobjectonthecanvas.Dragthelabelaroundthecanvasandnoticethedashedbluelinesthatappearwhenthelabelisnearthecenterofthecanvas(Figure1.12).Theseguidelineswillhelpyoulayoutyourinterface.

Page 53: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure1.12Addingalabeltothecanvas

Usingtheguidelines,positionthelabelinthehorizontalcenteroftheviewandnearthetop,asshowninFigure1.12.Eventually,thislabelwilldisplayquestionstotheuser.Dragasecondlabelontotheviewandpositionitinthehorizontalcenter,closertothemiddle.Thislabelwilldisplayanswers.Next,findButtonintheobjectlibraryanddragtwobuttonsontotheview.Positiononebeloweachlabel.YouhavenowaddedfourviewobjectstotheViewController’sUI.Noticethattheyalsoappearinthedocumentoutline.YourinterfaceshouldlooklikeFigure1.13.Figure1.13BuildingtheQuizinterface

Page 54: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Configuringviewobjects

Nowthatyouhavecreatedtheviewobjects,youcanconfiguretheirattributes.Someattributesofaview,likesize,position,andtext,canbechangeddirectlyonthecanvas.Forexample,youcanresizeanobjectbyselectingitinthecanvasorthedocumentoutlineandthendraggingitscornersandedgesinthecanvas.Beginbyrenamingthelabelsandbuttons.Double-clickoneachlabelandreplacethetextwith???.Thendouble-clicktheupperbuttonandchangeitsnametoNextQuestion.RenamethelowerbuttontoShowAnswer.TheresultsareshowninFigure1.14.

Page 55: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure1.14Renamingthelabelsandbuttons

Youmayhavenoticedthatbecauseyouhavechangedthetextinthelabelsandbuttons,andthereforetheirwidths,theyarenolongerneatlycenteredinthescene.Clickoneachofthemanddragtocenterthemagain,asshowninFigure1.15.Figure1.15Centeringthelabelsandbuttons

Runningonthesimulator

Page 56: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

TotestyourUI,youaregoingtorunQuizonXcode’siOSsimulator.ToprepareQuiztorunonthesimulator,findthecurrentschemepop-upmenuontheXcodetoolbar(Figure1.16).Figure1.16iPhone7schemeselected

IfitsayssomethinggenericlikeiPhone7,thentheprojectissettorunonthesimulatorandyouaregoodtogo.IfitsayssomethinglikeChristian'siPhone,thenclickandchooseiPhone7fromthepop-upmenu.TheiPhone7schemewillbeyoursimulatordefaultthroughoutthisbook.Clickthetriangularplaybuttoninthetoolbar.Thiswillbuild(compile)andthenruntheapplication.YouwillbedoingthisoftenenoughthatyoumaywanttolearnandusethekeyboardshortcutCommand-R.Afterthesimulatorlaunchesyouwillseethattheinterfacehasalltheviewsyouadded,neatlycenteredasyouconfiguredtheminInterfaceBuilder.Nowgobacktothecurrentschemepop-upmenuandselectiPhone7Plusasyoursimulatorofchoice.Runtheapplicationagainandyouwillnoticethatwhiletheviewsyouaddedarestillpresent,theyarenotcenteredastheywereoniPhone7.Thisisbecausethelabelsandbuttonscurrentlyhaveafixedpositiononascreen,andtheydonotremaincenteredonthemainview.Tocorrectthisproblem,youwilluseatechnologycalledAutoLayout.

AbriefintroductiontoAutoLayout

Asofnow,yourinterfacelooksniceintheInterfaceBuildercanvas.ButiOSdevicescomeinevermorescreensizes,andapplicationsareexpectedtosupportallscreensizesandorientations–andperhapsmorethanonedevicetype.Youneedtoguaranteethatthelayoutofviewobjectswillbecorrectregardlessofthescreensizeororientationofthedevicerunningtheapplication.ThetoolforthistaskisAutoLayout.AutoLayoutworksbyspecifyingpositionandsizeconstraintsforeachviewobjectinascene.Theseconstraintscanberelativetoneighboringviewsortocontainerviews.Acontainerviewisjustaviewobjectthat,asthenamesuggests,containsanotherview.Forexample,takealookatthedocumentoutlineforMain.storyboard(Figure1.17).

Page 57: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure1.17Documentlayoutwithacontainerview

YoucanseeinthedocumentoutlinethatthelabelsandbuttonsyouaddedareindentedwithrespecttoaViewobject.Thisviewobjectisthecontainerofthelabelsandbuttons,andtheobjectscanbepositionedandsizedrelativetothisview.TobeginspecifyingAutoLayoutconstraints,selectthetoplabelbyclickingoniteitheronthecanvasorinthedocumentoutline.Atthebottomofthecanvas,noticetheAutoLayoutmenus,showninFigure1.18.Figure1.18TheAutoLayoutmenus

Withthetoplabelstillselected,clickonthe icontorevealtheAlignmenushowninFigure1.19.

Page 58: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure1.19Centeringthetoplabelinthecontainer

WithintheAlignmenu,checktheHorizontallyinContainercheckboxtocenterthelabelinthecontainer.ThenclicktheAdd1Constraintbutton.Thisconstraintguaranteesthatonanysizescreen,inanyorientation,thelabelwillbecenteredhorizontally.Nowyouneedtoaddmoreconstraintstocenterthelowerlabelandthebuttonswithrespecttothetoplabelandtolockthespacingbetweenthem.SelectthefourviewsbyCommand-clickingonthemoneafteranotherandthenclickonthe icontoopentheAddNewConstraintsmenushowninFigure1.20.

Page 59: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure1.20Addingconstraintstocenterandfixthespacingbetweenviews

Clickontheredverticaldashedsegmentnearthetopofthemenu.Whenyouclickonthesegment,itwillbecomesolidred(showninFigure1.20),indicatingthatthedistanceofeachviewispinnedtoitsnearesttopneighbor.Also,checktheAlignboxandthenselectHorizontalCentersfromthepop-upmenu.ForUpdateFrames,makesurethatyouhaveItemsofNewConstraintsselected.Finally,clickontheAdd7Constraintsbuttonatthebottomofthemenu.Ifyoumadeanymistakeswhileaddingconstraints,youmayseeredororangeconstraintsandframesonthecanvasinsteadofthecorrectbluelines.Ifthatisthecase,youwillwanttocleartheexistingconstraintsandgothroughthestepsaboveagain.Toclearconstraints,firstselectthebackground(container)view.Thenclickthe icontoopentheResolveAutoLayoutIssuesmenu.SelectClearConstraintsundertheAllViewsinViewControllersection(Figure1.21).Thiswillclearawayanyconstraintsthatyouhaveaddedandgiveyouafreshstartonaddingtheconstraintsbackin.

Page 60: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure1.21Clearingconstraints

AutoLayoutcanbeadifficulttooltomaster,andthatiswhyyouarestartingtouseitinthefirstchapterofthisbook.Bystartingearly,youwillhavemorechancestouseitandgetusedtoitscomplexity.Also,dealingwithproblemsbeforethingsgettoocomplicatedwillhelpyoudebuglayoutissueswithconfidence.Toconfirmthatyourinterfacebehavescorrectly,buildandruntheapplicationontheiPhone7Plussimulator.Afterconfirmingthattheinterfacelookscorrect,buildandruntheapplicationontheiPhone7simulator.Thelabelsandbuttonsshouldbecenteredonboth.

Makingconnections

Aconnectionletsoneobjectknowwhereanotherobjectisinmemorysothatthetwoobjectscancommunicate.TherearetwokindsofconnectionsthatyoucanmakeinInterfaceBuilder:outletsandactions.Anoutletisareferencetoanobject.Anactionisamethodthatgetstriggeredbyabuttonorsomeotherviewthattheusercaninteractwith,likeasliderorapicker.Let’sstartbycreatingoutletsthatreferencetheinstancesofUILabel.TimetoleaveInterfaceBuilderandwritesomecode.

Declaringoutlets

Intheprojectnavigator,findandselectthefilenamedViewController.swift.TheeditorareawillchangefromInterfaceBuildertoXcode’scodeeditor.InViewController.swift,startbydeletinganycodethatthetemplateaddedbetweenclassViewController:UIViewController{andthefinalbrace,sothatthefile

Page 61: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

lookslikethis:importUIKit

classViewController:UIViewController{

}

(Forsimplicity,wewillnotshowthelineimportUIKitagainforthisfile.)Next,addthefollowingcodethatdeclarestwoproperties.(Throughoutthisbook,newcodeforyoutoaddwillbeshowninbold.Codeforyoutodeletewillbestruckthrough.)Donotworryaboutunderstandingthecodeorpropertiesrightnow;justgetitin.classViewController:UIViewController{

@IBOutletvarquestionLabel:UILabel!

@IBOutletvaranswerLabel:UILabel!

}

ThiscodegiveseveryinstanceofViewControlleranoutletnamedquestionLabelandanoutletnamedanswerLabel.TheviewcontrollercanuseeachoutlettoreferenceaparticularUILabelobject(i.e.,oneofthelabelsinyourview).The@IBOutletkeywordtellsXcodethatyouwillconnecttheseoutletstolabelobjectsusingInterfaceBuilder.

Settingoutlets

Intheprojectnavigator,selectMain.storyboardtoreopenInterfaceBuilder.YouwantthequestionLabeloutlettopointtotheinstanceofUILabelatthetopoftheUI.Inthedocumentoutline,findtheViewControllerScenesectionandtheViewControllerobjectwithinit.Inyourcase,theViewControllerstandsinforaninstanceofViewController,whichistheobjectresponsibleformanagingtheinterfacedefinedinMain.storyboard.Control-drag(orright-clickanddrag)fromtheViewControllerinthedocumentoutlinetothetoplabelinthescene.Whenthelabelishighlighted,releasethemouseandkeyboard;ablackpanelwillappear.SelectquestionLabeltosettheoutlet,asshowninFigure1.22.

Page 62: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure1.22SettingquestionLabel

(IfyoudonotseequestionLabelintheconnectionspanel,double-checkyourViewController.swiftfilefortypos.)Now,whenthestoryboardfileisloaded,theViewController’squestionLabeloutletwillautomaticallyreferencetheinstanceofUILabelatthetopofthescreen,whichwillallowtheViewControllertotellthelabelwhatquestiontodisplay.SettheanswerLabeloutletthesameway:Control-dragfromtheViewControllertothebottomUILabelandselectanswerLabel(Figure1.23).

Page 63: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure1.23SettinganswerLabel

Noticethatyoudragfromtheobjectwiththeoutletthatyouwanttosettotheobjectthatyouwantthatoutlettopointto.Youroutletsareallset.Thenextconnectionsyouneedtomakeinvolvethetwobuttons.

Definingactionmethods

WhenaUIButtonistapped,itcallsamethodonanotherobject.Thatobjectiscalledthetarget.Themethodthatistriggerediscalledtheaction.Thisactionisthenameofthemethodthatcontainsthecodetobeexecutedinresponsetothebuttonbeingtapped.Inyourapplication,thetargetforbothbuttonswillbetheinstanceofViewController.Eachbuttonwillhaveitsownaction.Let’sstartbydefiningthetwoactionmethods:showNextQuestion(_:)andshowAnswer(_:).ReopenViewController.swiftandaddthetwoactionmethodsaftertheoutlets.classViewController:UIViewController{

@IBOutletvarquestionLabel:UILabel!

@IBOutletvaranswerLabel:UILabel!

@IBActionfuncshowNextQuestion(_sender:UIButton){

}

@IBActionfuncshowAnswer(_sender:UIButton){

Page 64: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

}

}

Youwillfleshoutthesemethodsafteryoumakethetargetandactionconnections.The@IBActionkeywordtellsXcodethatyouwillbemakingtheseconnectionsinInterfaceBuilder.

Settingtargetsandactions

SwitchbacktoMain.storyboard.Let’sstartwiththeNextQuestionbutton.YouwantitstargettobeViewControlleranditsactiontobeshowNextQuestion(_:).Tosetanobject’starget,youControl-dragfromtheobjecttoitstarget.Whenyoureleasethemouse,thetargetisset,andapop-upmenuappearsthatletsyouselectanaction.SelecttheNextQuestionbuttoninthecanvasandControl-dragtotheViewControllerinthedocumentoutline.WhentheViewControllerishighlighted,releasethemousebuttonandchooseshowNextQuestion:underSentEventsinthepop-upmenu,asshowninFigure1.24.Figure1.24SettingNextQuestiontarget/action

NowfortheShowAnswerbutton.SelectthebuttonandControl-dragfromthebuttontotheViewController.ChooseshowAnswer:fromthepop-upmenu.

Summaryofconnections

Page 65: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

TherearenowfiveconnectionsbetweentheViewControllerandtheviewobjects.YouhavesetthepropertiesanswerLabelandquestionLabeltoreferencethelabelobjects–twoconnections.TheViewControlleristhetargetforbothbuttons–twomore.Theproject’stemplatemadeoneadditionalconnection:TheviewpropertyofViewControllerisconnectedtotheViewobjectthatrepresentsthebackgroundoftheapplication.Thatmakesfive.Youcanchecktheseconnectionsintheconnectionsinspector.SelecttheViewControllerinthedocumentoutline.Then,intheutilitiesarea,clickthe tabtorevealtheconnectionsinspector(Figure1.25).Figure1.25Checkingconnectionsintheconnectionsinspector

Yourstoryboardfileiscomplete.Theviewobjectshavebeencreatedandconfiguredandallthenecessaryconnectionshavebeenmadetothecontrollerobject.Let’smoveontocreatingandconnectingyourmodelobjects.

Page 66: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 67: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

CreatingtheModelLayer

ViewobjectsmakeuptheUI,sodeveloperstypicallycreate,configure,andconnectviewobjectsusingInterfaceBuilder.Thepartsofthemodellayer,ontheotherhand,aretypicallysetupincode.Intheprojectnavigator,selectViewController.swift.Addthefollowingcodethatdeclarestwoarraysofstringsandaninteger.classViewController:UIViewController{

@IBOutletvarquestionLabel:UILabel!

@IBOutletvaranswerLabel:UILabel!

letquestions:[String]=[

"Whatis7+7?",

"WhatisthecapitalofVermont?",

"Whatiscognacmadefrom?"

]

letanswers:[String]=[

"14",

"Montpelier",

"Grapes"

]

varcurrentQuestionIndex:Int=0

...

}

Thearraysareorderedlistscontainingquestionsandanswers.Theintegerwillkeeptrackofwhatquestiontheuserison.Noticethatthearraysaredeclaredusingtheletkeyword,whereastheintegerisdeclaredusingthevarkeyword.Aconstantisdenotedwiththeletkeyword;itsvaluecannotchange.Thequestionsandanswersarraysareconstants.Thequestionsandanswersinthisquizwillnotchangeand,infact,cannotbechangedfromtheirinitialvalues.Avariable,ontheotherhand,isdenotedbythevarkeyword;itsvalueisallowedtochange.YoumadethecurrentQuestionIndexpropertyavariablebecauseitsvaluemustbeabletochangeastheusercyclesthroughthequestionsandanswers.

Implementingactionmethods

Nowthatyouhavequestionsandanswers,youcanfinishimplementingtheactionmethods.InViewController.swift,updateshowNextQuestion(_:)andshowAnswer(_:)....

@IBActionfuncshowNextQuestion(_sender:UIButton){

currentQuestionIndex+=1

ifcurrentQuestionIndex==questions.count{

currentQuestionIndex=0

}

letquestion:String=questions[currentQuestionIndex]

questionLabel.text=question

Page 68: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

answerLabel.text="???"

}

@IBActionfuncshowAnswer(_sender:UIButton){

letanswer:String=answers[currentQuestionIndex]

answerLabel.text=answer

}

...

Loadingthefirstquestion

Justaftertheapplicationislaunched,youwillwanttoloadthefirstquestionfromthearrayanduseittoreplacethe???placeholderinthequestionLabellabel.AgoodwaytodothisisbyoverridingtheviewDidLoad()methodofViewController.(“Override”meansthatyouareprovidingacustomimplementationforamethod.)AddthemethodtoViewController.swift.classViewController:UIViewController{

...

overridefuncviewDidLoad(){

super.viewDidLoad()

questionLabel.text=questions[currentQuestionIndex]

}

}

Allthecodeforyourapplicationisnowcomplete!

Page 69: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 70: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

BuildingtheFinishedApplication

BuildandruntheapplicationontheiPhone7simulator,asyoudidearlier.Ifbuildingturnsupanyerrors,youcanviewthemintheissuenavigatorbyselectingthetabinthenavigatorarea(Figure1.26).Figure1.26Issuenavigatorwithexampleerrorsandwarnings

Clickonanyerrororwarningintheissuenavigatortobetakentothefileandthelineofcodewheretheissueoccurred.Findandfixanyproblems(i.e.,codetypos!)bycomparingyourcodewiththecodeinthischapter.Thentryrunningtheapplicationagain.Repeatthisprocessuntilyourapplicationcompiles.Afteryourapplicationhascompiled,itwilllaunchintheiOSsimulator.PlayaroundwiththeQuizapplication.YoushouldbeabletotaptheNextQuestionbuttonandseeanewquestioninthetoplabel;tappingShowAnswershouldshowtherightanswer.Ifyourapplicationisnotworkingasexpected,double-checkyourconnectionsinMain.storyboard.YouhavebuiltaworkingiOSapp!Takeamomenttobaskintheglory.OK,enoughbasking.Yourappworks,butitneedssomespitandpolish.

Page 71: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 72: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

ApplicationIcons

WhilerunningQuiz,selectHardware→Homefromthesimulator ’smenu.YouwillseethatQuiz’siconisaboring,defaulttile.Let’sgiveQuizabettericon.AnapplicationiconisasimpleimagethatrepresentstheapplicationontheiOSHomescreen.Differentdevicesrequiredifferent-sizedicons,someofwhichareshowninTable1.1.Table1.1Applicationiconsizesbydevice

Device Applicationiconsizes

5.5-inchiPhone 180x180pixels(@3x)

4.7-inchand4.0-inchiPhone 120x120pixels(@2x)

7.9-inchand9.7-inchiPad 152x152pixels(@2x)

12.9-inchiPad 167x167pixels(@2x)

Wehavepreparedaniconimagefile(size120x120)fortheQuizapplication.Youcandownloadthisicon(alongwithresourcesforotherchapters)fromwww.bignerdranch.com/solutions/iOSProgramming6ed.zip.UnzipiOSProgramming6ed.zipandfindtheQuiz-120.pngfileinthe0-Resources/ProjectAppIconsdirectoryoftheunzippedfolder.Youaregoingtoaddthisicontoyourapplicationbundleasaresource.Ingeneral,therearetwokindsoffilesinanapplication:codeandresources.Code(likeViewController.swift)isusedtocreatetheapplicationitself.Resourcesarethingslikeimagesandsoundsthatareusedbytheapplicationatruntime.Intheprojectnavigator,findAssets.xcassets.SelectthisfiletoopenitandthenselectAppIconfromtheresourcelistonthelefthandside(Figure1.27).

Page 73: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure1.27ShowingtheAssetCatalog

ThispanelistheAssetCatalog,whereyoucanmanagealloftheimagesthatyourapplicationwillneed.DragtheQuiz-120.pngfilefromFinderontothe2xslotoftheiPhoneAppsection(Figure1.28).Thiswillcopythefileintoyourproject’sdirectoryonthefilesystemandaddareferencetothatfileintheAssetCatalog.(YoucanControl-clickonafileintheAssetCatalogandselecttheoptiontoShowinFindertoconfirmthis.)Figure1.28AddingtheappicontotheAssetCatalog

Page 74: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Buildandruntheapplicationagain.Switchtothesimulator ’sHomescreeneitherbyclickingHardware→Home,asyoudidbefore,orbyusingthekeyboardshortcutCommand-Shift-H.Youshouldseethenewicon.(Ifyoudonotseetheicon,deletetheapplicationandthenbuildandrunagaintoredeployit.Todothis,theeasiestoptionistoresetthesimulatorbyclickingSimulator→ResetContentandSettings....Thiswillremoveallapplicationsandresetthesimulatortoitsdefaultsettings.Youshouldseetheappiconthenexttimeyouruntheapplication.)

Page 75: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 76: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

LaunchScreen

Anotheritemyoushouldsetfortheprojectisthelaunchimage,whichappearswhileanapplicationisloading.ThelaunchimagehasaspecificroleiniOS:ItconveystotheuserthattheapplicationisindeedlaunchinganddepictstheUIthattheuserwillinteractwithoncetheapplicationloads.Therefore,agoodlaunchimageisacontent-lessscreenshotoftheapplication.Forexample,theClockapplication’slaunchimageshowsthefourtabsalongthebottom,allintheunselectedstate.Oncetheapplicationloads,thecorrecttabisselectedandthecontentbecomesvisible.(Keepinmindthatthelaunchimageisreplacedaftertheapplicationhaslaunched;itdoesnotbecomethebackgroundimageoftheapplication.)AneasywaytoaccomplishthisistoallowXcodetogeneratethepossiblelaunchscreenimagesforyouusingalaunchscreenfile.Opentheprojectsettingsbyclickingonthetop-levelQuizintheprojectnavigator.UnderAppIconsandLaunchImages,chooseMain.storyboardfromtheLaunchScreenFiledropdown(Figure1.29).LaunchimageswillnowbegeneratedfromMain.storyboard.Figure1.29Settingthelaunchscreenfile

Itisdifficulttoseetheresultsofthischange,becausethelaunchimageistypicallyshownforonlyashorttime.However,itisagoodpracticetosetthelaunchimageeventhoughitsroleissobrief.Congratulations!Youhavewrittenyourfirstapplicationandevenaddedsomedetailstomakeitpolished.YouwillreturntoQuizlaterinthebook.ThenextchaptercoverssomebasicsofSwifttoprepareyouformorecoding.

Page 77: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 78: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

2TheSwiftLanguage

SwiftisanewlanguagethatAppleintroducedin2014.ItreplacesObjective-CastherecommendeddevelopmentlanguageforiOSandMac.Inthischapter,youaregoingtofocusonthebasicsofSwift.Youwillnotlearneverything,butyouwilllearnenoughtogetstarted.Then,asyoucontinuethroughthebook,youwilllearnmoreSwiftwhileyoulearniOSdevelopment.SwiftmaintainstheexpressivenessofObjective-Cwhileintroducingasyntaxthatissafer,succinct,andreadable.Itemphasizestypesafetyandaddsadvancedfeaturessuchasoptionals,generics,andsophisticatedstructuresandenumerations.Mostimportantly,Swiftallowstheuseofthesenewfeatureswhilerelyingonthesametested,elegantiOSframeworksthatdevelopershavebuiltuponforyears.IfyouknowObjective-C,thenthechallengeisrecastingwhatyouknow.Itmayseemawkwardatfirst,butwehavecometoloveSwiftatBigNerdRanchandbelieveyouwill,too.IfyoudonotthinkyouwillbecomfortablepickingupSwiftatthesametimeasiOSdevelopment,youmaywanttostartwithSwiftProgramming:TheBigNerdRanchGuideorApple’sSwifttutorials,whichyoucanfindatdeveloper.apple.com/swift.Butifyouhavesomeprogrammingexperienceandarewillingtolearn“onthejob,”youcanstartyourSwifteducationhereandnow.

Page 79: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

TypesinSwift

Swifttypescanbearrangedintothreebasicgroups:structures,classes,andenumerations(Figure2.1).Allthreecanhave:

properties–valuesassociatedwithatypeinitializers–codethatinitializesaninstanceofatypeinstancemethods–functionsspecifictoatypethatcanbecalledonaninstanceofthattypeclassorstaticmethods–functionsspecifictoatypethatcanbecalledonthetypeitself

Figure2.1Swiftbuildingblocks

Swift’sstructures(or“structs”)andenumerations(or“enums”)aresignificantlymorepowerfulthaninmostlanguages.Inadditiontosupportingproperties,initializers,andmethods,theycanalsoconformtoprotocolsandcanbeextended.Swift’simplementationoftypically“primitive”typessuchasnumbersandBooleanvaluesmaysurpriseyou:Theyareallstructures.Infact,alloftheseSwifttypesarestructures:

Numbers: Int,Float,Double

Boolean: Bool

Text: String,Character

Collections:Array<Element>,Dictionary<Key:Hashable,Value>,Set<Element:Hashable>

Thismeansthatstandardtypeshaveproperties,initializers,andmethodsoftheirown.Theycanalsoconformtoprotocolsandbeextended.Finally,akeyfeatureofSwiftisoptionals.Anoptionalallowsyoutostoreeitheravalueofaparticulartypeornovalueatall.YouwilllearnmoreaboutoptionalsandtheirroleinSwiftlaterinthischapter.

Page 80: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 81: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

UsingStandardTypes

Inthissection,youaregoingtoexperimentwithstandardtypesinanXcodeplayground.Aplaygroundletsyouwritecodeandseetheresultswithouttheoverheadofmanuallyrunninganapplicationandcheckingtheoutput.InXcode,selectFile→New→Playground....Youcanacceptthedefaultnameforthisfile;youwillonlybeherebriefly.MakesuretheplatformisiOS(Figure2.2).Figure2.2Configuringaplayground

ClickNextandsavethisfileinaconvenientplace.Whenthefileopens,noticethattheplaygroundisdividedintotwosections(Figure2.3).Thelargerwhiteareatotheleftistheeditorwhereyouwritecode.Thegraycolumnontherightisthesidebar.Theplaygroundcompilesandexecutesyourcodeaftereverylineandshowstheresultsinthesidebar.Figure2.3Aplayground

Page 82: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Intheexamplecode,thevarkeyworddenotesavariable,sothevalueofstrcanbechangedfromitsinitialvalue.Typeinthecodebelowtochangethevalueofstr,andyouwillseetheresultsappearinthesidebartotheright.varstr="Hello,playground""Hello,playground"

str="Hello,Swift""Hello,Swift"

(Noticethatweareshowingsidebarresultstotherightofthecodeforthebenefitofreaderswhoarenotactivelydoingtheexercise.)Theletkeyworddenotesaconstantvalue,whichcannotbechanged.InyourSwiftcode,youshoulduseletunlessyouexpectthevaluewillneedtochange.Addaconstanttothemix:varstr="Hello,playground""Hello,playground"

str="Hello,Swift""Hello,Swift"

letconstStr=str"Hello,Swift"

BecauseconstStrisaconstant,attemptingtochangeitsvaluewillcauseanerror.varstr="Hello,playground""Hello,playground"

str="Hello,Swift""Hello,Swift"

letconstStr=str"Hello,Swift"

constStr="Hello,world"

Anerrorappears,indicatedbytheredsymboltotheleftoftheoffendingline.Clickthesymboltogetmoreinformationabouttheerror.Inthiscase,theerrorreadsCannotassigntovalue:'constStr'isa'let'constant.Anerrorintheplaygroundcodewillpreventyoufromseeinganyfurtherresultsinthesidebar,soyouusuallywanttoaddressitrightaway.RemovethelinethatattemptstochangethevalueofconstStr.varstr="Hello,playground""Hello,playground"

str="Hello,Swift""Hello,Swift"

letconstStr=str"Hello,Swift"

constStr="Hello,world"

Inferringtypes

Atthispoint,youmayhavenoticedthatneithertheconstStrconstantnorthestrvariablehasaspecifiedtype.Thisdoesnotmeantheyareuntyped!Instead,thecompilerinferstheirtypesfromtheinitialvalues.Thisiscalledtypeinference.YoucanfindoutwhattypewasinferredusingXcode’sQuickHelp.Option-clickonconstStrintheplaygroundtoseetheQuickHelpinformationforthisconstant,showninFigure2.4.

Page 83: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure2.4constStrisoftypeString

Option-clickingtorevealQuickHelpwillworkforanysymbol.

Specifyingtypes

Ifyourconstantorvariablehasaninitialvalue,youcanrelyontypeinference.Ifaconstantorvariabledoesnothaveaninitialvalueorifyouwanttoensurethatitisacertaintype,youcanspecifythetypeinthedeclaration.Addmorevariableswithspecifiedtypes:varstr="Hello,playground""Hello,playground"

str="Hello,Swift""Hello,Swift"

letconstStr=str"Hello,Swift"

varnextYear:Int

varbodyTemp:Float

varhasPet:Bool

Notethatthesidebardoesnotreportanyresultsbecausethesevariablesdonotyethavevalues.Let’sgooverthesenewtypesandhowtheyareused.

NumberandBooleantypes

ThemostcommontypeforintegersisInt.Thereareadditionalintegertypesbasedonwordsizeandsignedness,butApplerecommendsusingIntunlessyoureallyhaveareasontousesomethingelse.Forfloating-pointnumbers,Swiftprovidesthreetypeswithdifferentlevelsofprecision:Floatfor32-bitnumbers,Doublefor64-bitnumbers,andFloat80for80-bitnumbers.ABooleanvalueisexpressedinSwiftusingthetypeBool.ABool’svalueiseithertrueorfalse.

Collectiontypes

Page 84: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

TheSwiftstandardlibraryoffersthreecollections:arrays,dictionaries,andsets.Anarrayisanorderedcollectionofelements.ThearraytypeiswrittenasArray<T>,whereTisthetypeofelementthatthearraywillcontain.Arrayscancontainelementsofanytype:astandardtype,astructure,oraclass.Addavariableforanarrayofintegers:varhasPet:Bool

vararrayOfInts:Array<Int>

Arraysarestronglytyped.Onceyoudeclareanarrayascontainingelementsof,say,Int,youcannotaddaStringtoit.Thereisashorthandsyntaxfordeclaringarrays:Youcansimplyusesquarebracketsaroundthetypethatthearraywillcontain.UpdatethedeclarationofarrayOfIntstousetheshorthand:varhasPet:Bool

vararrayOfInts:Array<Int>

vararrayOfInts:[Int]

Adictionaryisanunorderedcollectionofkey-valuepairs.Thevaluescanbeofanytype,includingstructuresandclasses.Thekeyscanbeofanytypeaswell,buttheymustbeunique.Specifically,thekeysmustbehashable,whichallowsthedictionarytoguaranteethatthekeysareuniqueandtoaccessthevalueforagivenkeymoreefficiently.BasicSwifttypessuchasInt,Float,Character,andStringareallhashable.LikeSwiftarrays,Swiftdictionariesarestronglytypedandcanonlycontainkeysandvaluesofthedeclaredtype.Forexample,youmighthaveadictionarythatstorescapitalcitiesbycountry.Thekeysforthisdictionarywouldbethecountrynames,andthevalueswouldbethecitynames.Bothkeysandvalueswouldbestrings,andyouwouldnotbeabletoaddakeyorvalueofanyothertype.Addavariableforsuchadictionary:vararrayOfInts:[Int]

vardictionaryOfCapitalsByCountry:Dictionary<String,String>

Thereisashorthandsyntaxfordeclaringdictionaries,too.UpdatedictionaryOfCapitalsByCountrytousetheshorthand:vararrayOfInts:[Int]

vardictionaryOfCapitalsByCountry:Dictionary<String,String>

vardictionaryOfCapitalsByCountry:[String:String]

Asetissimilartoanarrayinthatitcontainsanumberofelementsofacertaintype.However,setsareunordered,andthemembersmustbeuniqueaswellashashable.Theunorderednessofsetsmakesthemfasterwhenyousimplyneedtodeterminewhethersomethingisamemberofaset.Addavariableforaset:varwinningLotteryNumbers:Set<Int>

Unlikearraysanddictionaries,setsdonothaveashorthandsyntax.

Literalsandsubscripting

Page 85: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Standardtypescanbeassignedliteralvalues,orliterals.Forexample,strisassignedthevalueofastringliteral.Astringliteralisformedwithdoublequotes.ContrasttheliteralvalueassignedtostrwiththenonliteralvalueassignedtoconstStr:varstr="Hello,playground""Hello,playground"

str="Hello,Swift""Hello,Swift"

letconstStr=str"Hello,Swift"

Addtwonumberliteralstoyourplayground:letnumber=4242

letfmStation=91.191.1

Arraysanddictionariescanbeassignedliteralvaluesaswell.Thesyntaxforcreatingliteralarraysanddictionariesresemblestheshorthandsyntaxforspecifyingthesetypes.letcountingUp=["one","two"]["one","two"]

letnameByParkingSpace=[13:"Alice",27:"Bob"][13:"Alice",27:"Bob"]

Swiftalsoprovidessubscriptingasshorthandforaccessingarrays.Toretrieveanelementinanarray,youprovidetheelement’sindexinsquarebracketsafterthearrayname.letcountingUp=["one","two"]["one","two"]

letsecondElement=countingUp[1]"two"

...

Noticethatindex1retrievesthesecondelement;anarray’sindexalwaysstartsat0.Whensubscriptinganarray,besurethatyouareusingavalidindex.Attemptingtoaccessanout-of-boundsindexresultsinatrap.Atrapisaruntimeerrorthatstopstheprogrambeforeitgetsintoanunknownstate.Subscriptingalsoworkswithdictionaries–moreonthatlaterinthischapter.

Initializers

Sofar,youhaveinitializedyourconstantsandvariablesusingliteralvalues.Indoingso,youcreatedinstancesofaspecifictype.Aninstanceisaparticularembodimentofatype.Historically,thistermhasbeenonlyusedwithclasses,butinSwiftitisusedtodescribestructuresandenumerations,too.Forexample,theconstantsecondElementholdsaninstanceofString.Anotherwayofcreatinginstancesisbyusinganinitializeronthetype.Initializersareresponsibleforpreparingthecontentsofanewinstanceofatype.Whenaninitializerisfinished,theinstanceisreadyforaction.Tocreateanewinstanceusinganinitializer,youusethetypenamefollowedbyapairofparenthesesand,ifrequired,arguments.Thissignature–thecombinationoftypeandarguments–correspondstoaspecificinitializer.Somestandardtypeshaveinitializersthatreturnemptyliteralswhennoargumentsaresupplied.Addanemptystring,anemptyarray,andanemptysettoyourplayground.letemptyString=String()""

letemptyArrayOfInts=[Int]()0elements

letemptySetOfFloats=Set<Float>()0elements

Othertypeshavedefaultvalues:

Page 86: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

letdefaultNumber=Int()0

letdefaultBool=Bool()false

Typescanhavemultipleinitializers.Forexample,StringhasaninitializerthatacceptsanIntandcreatesastringbasedonthatvalue.letnumber=4242

letmeaningOfLife=String(number)"42"

Tocreateaset,youcanusetheSetinitializerthatacceptsanarrayliteral:letavailableRooms=Set([205,411,412]){412,205,411}

Floathasseveralinitializers.Theparameter-lessinitializerreturnsaninstanceofFloatwiththedefaultvalue.Thereisalsoaninitializerthatacceptsafloating-pointliteral.letdefaultFloat=Float()0.0

letfloatFromLiteral=Float(3.14)3.14

Ifyouusetypeinferenceforafloating-pointliteral,thetypedefaultstoDouble.Createthefollowingconstantwithafloating-pointliteral:leteasyPi=3.143.14

UsetheFloatinitializerthatacceptsaDoubletocreateaFloatfromthisDouble:leteasyPi=3.143.14

letfloatFromDouble=Float(easyPi)3.14

Youcanachievethesameresultbyspecifyingthetypeinthedeclaration.leteasyPi=3.143.14

letfloatFromDouble=Float(easyPi)3.14

letfloatingPi:Float=3.143.14

Properties

Apropertyisavalueassociatedwithaninstanceofatype.Forexample,StringhasthepropertyisEmpty,whichisaBoolthattellsyouwhetherthestringisempty.Array<T>hasthepropertycount,whichisthenumberofelementsinthearrayasanInt.Accessthesepropertiesinyourplayground:letcountingUp=["one","two"]["one","two"]

letsecondElement=countingUp[1]"two"

countingUp.count2

...

letemptyString=String()

emptyString.isEmptytrue

Instancemethods

Aninstancemethodisafunctionthatisspecifictoaparticulartypeandcanbecalledonaninstanceofthattype.Tryouttheappend(_:)instancemethodfromArray<T>.YouwillfirstneedtochangeyourcountingUparrayfromaconstanttoavariable.letcountingUp=["one","two"]

varcountingUp=["one","two"]["one","two"]

Page 87: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

letsecondElement=countingUp[1]"two"

countingUp.count

countingUp.append("three")["one","two","three"]

Theappend(_:)methodacceptsanelementofthearray’stypeandaddsittotheendofthearray.Wewilldiscussmethods,includingnaming,inChapter3.

Page 88: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 89: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Optionals

Swifttypescanbeoptional,whichisindicatedbyappending?toatypename.varanOptionalFloat:Float?

varanOptionalArrayOfStrings:[String]?

varanOptionalArrayOfOptionalStrings:[String?]?

Anoptionalletsyouexpressthepossibilitythatavariablemaynotstoreavalueatall.Thevalueofanoptionalwilleitherbeaninstanceofthespecifiedtypeornil.Throughoutthisbook,youwillhavemanychancestouseoptionals.Whatfollowsisanexampletogetyoufamiliarwiththesyntaxsothatyoucanfocusontheuseoftheoptionalslater.Imagineagroupofinstrumentreadings:varreading1:Float

varreading2:Float

varreading3:Float

Sometimes,aninstrumentmightmalfunctionandnotreportareading.Youdonotwantthismalfunctionshowingupas,say,0.0.Youwantittobesomethingcompletelydifferentthattellsyoutocheckyourinstrumentortakesomeotheraction.Youcandothisbydeclaringthereadingsasoptionals.Addthesedeclarationstoyourplayground.varreading1:Float?nil

varreading2:Float?nil

varreading3:Float?nil

Asanoptionalfloat,eachreadingcancontaineitheraFloatornil.Ifnotgivenaninitialvalue,thenthevaluedefaultstonil.Youcanassignvaluestoanoptionaljustlikeanyothervariable.Assignfloating-pointliteralstothereadings:reading1=9.89.8

reading2=9.29.2

reading3=9.79.7

However,youcannotusetheseoptionalfloatslikenon-optionalfloats–eveniftheyhavebeenassignedFloatvalues.Beforeyoucanreadthevalueofanoptionalvariable,youmustaddressthepossibilityofitsvaluebeingnil.Thisiscalledunwrappingtheoptional.Youaregoingtotryouttwowaysofunwrappinganoptionalvariable:optionalbindingandforcedunwrapping.Youwillimplementforcedunwrappingfirst.Thisisnotbecauseitisthebetteroption–infact,itisthelesssafeone.Butimplementingforcedunwrappingfirstwillletyouseethedangersandunderstandwhyoptionalbindingistypicallybetter.Toforciblyunwrapanoptional,youappenda!toitsname.First,tryaveragingthereadingsasiftheywerenon-optionalvariables:reading1=9.89.8

reading2=9.29.2

reading3=9.79.7

letavgReading=(reading1+reading2+reading3)/3

Page 90: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Thisresultsinanerrorbecauseoptionalsrequireunwrapping.Forciblyunwrapthereadingstofixtheerror:letavgReading=(reading1+reading2+reading3)/3

letavgReading=(reading1!+reading2!+reading3!)/39.566667

Everythinglooksfine,andyouseethecorrectaverageinthesidebar.Butadangerlurksinyourcode.Whenyouforciblyunwrapanoptional,youtellthecompilerthatyouaresurethattheoptionalwillnotbenilandcanbetreatedasifitwereanormalFloat.Butwhatifyouarewrong?Tofindout,commentouttheassignmentofreading3,whichwillreturnittoitsdefaultvalue,nil.reading1=9.89.8

reading2=9.29.2

reading3=9.7

//reading3=9.7

Younowhaveanerror.Xcodemayhaveopeneditsdebugareaatthebottomoftheplaygroundwithinformationabouttheerror.Ifitdidnot,selectView→DebugArea→ShowDebugArea.Theerrorreads:fatalerror:unexpectedlyfoundnilwhileunwrappinganOptionalvalue

Ifyouforciblyunwrapanoptionalandthatoptionalturnsouttobenil,itwillcauseatrap,stoppingyourapplication.Asaferwaytounwrapanoptionalisoptionalbinding.Optionalbindingworkswithinaconditionalif-letstatement:Youassigntheoptionaltoatemporaryconstantofthecorrespondingnon-optionaltype.Ifyouroptionalhasavalue,thentheassignmentisvalidandyouproceedusingthenon-optionalconstant.Iftheoptionalisnil,thenyoucanhandlethatcasewithanelseclause.Changeyourcodetouseanif-letstatementthattestsforvalidvaluesinallthreereadings.letavgReading=(reading1!+reading2!+reading3!)/3

ifletr1=reading1,

letr2=reading2,

letr3=reading3{

letavgReading=(r1+r2+r3)/3

}else{

leterrorString="Instrumentreportedareadingthatwasnil."

}

reading3iscurrentlynil,soitsassignmenttor3fails,andthesidebarshowstheerrorstring.Toseetheothercaseinaction,restorethelinethatassignsavaluetoreading3.Nowthatallthreereadingshavevalues,allthreeassignmentsarevalid,andthesidebarupdatestoshowtheaverageofthethreereadings.

Subscriptingdictionaries

Recallthatsubscriptinganarraybeyonditsboundscausesatrap.Dictionariesaredifferent.Theresultofsubscriptingadictionaryisanoptional:

Page 91: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

letnameByParkingSpace=[13:"Alice",27:"Bob"][13:"Alice",27:"Bob"]

letspace13Assignee:String?=nameByParkingSpace[13]"Alice"

letspace42Assignee:String?=nameByParkingSpace[42]nil

Ifthekeyisnotinthedictionary,theresultwillbenil.Aswithotheroptionals,itiscommontouseif-letwhensubscriptingadictionary:letspace13Assignee:String?=nameByParkingSpace[13]

ifletspace13Assignee=nameByParkingSpace[13]{

print("Key13isassignedinthedictionary!")

}

Page 92: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 93: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

LoopsandStringInterpolation

Swifthasallthecontrolflowstatementsthatyoumaybefamiliarwithfromotherlanguages:if-else,while,for,for-in,repeat-while,andswitch.Eveniftheyarefamiliar,however,theremaybesomedifferencesfromwhatyouareaccustomedto.ThekeydifferencebetweenthesestatementsinSwiftandinC-likelanguagesisthatwhileenclosingparenthesesarenotnecessaryonthesestatements’expressions,Swiftdoesrequirebracesonclauses.Additionally,theexpressionsforifandwhile-likestatementsmustevaluatetoaBool.SwiftdoesnothavethetraditionalC-styleforloopthatyoumightbeaccustomedto.Instead,youcanaccomplishthesamethingalittlemorecleanlyusingSwift’sRangetypeandthefor-instatement:letrange=0..<countingUp.count

foriinrange{

letstring=countingUp[i]

//Use'string'

}

Themostdirectroutewouldbetoenumeratetheitemsinthearraythemselves:forstringincountingUp{

//Use'string'

}

Whatifyouwantedtheindexofeachiteminthearray?Swift’senumerated()functionreturnsasequenceofintegersandvaluesfromitsargument:for(i,string)incountingUp.enumerated(){

//(0,"one"),(1,"two")

}

Whatarethoseparentheses,youask?Theenumerated()functionreturnsasequenceoftuples.Atupleisanorderedgroupingofvaluessimilartoanarray,excepteachmembermayhaveadistincttype.Inthisexamplethetupleisoftype(Int,String).Wewillnotspendmuchtimeontuplesinthisbook;theyarenotusediniOSAPIsbecauseObjective-Cdoesnotsupportthem.However,theycanbeusefulinyourSwiftcode.Anotherapplicationoftuplesisinenumeratingthecontentsofadictionary:letnameByParkingSpace=[13:"Alice",27:"Bob"]

for(space,name)innameByParkingSpace{

letpermit="Space\(space):\(name)"

}

Didyounoticethatcuriousmarkupinthestringliteral?ThatisSwift’sstringinterpolation.Expressionsenclosedbetween\(and)areevaluatedandinsertedintothestringatruntime.Inthisexampleyouareusinglocalvariables,butanyvalidSwiftexpression,suchasamethodcall,canbeused.Toseethevaluesofthepermitvariableforeachiterationoftheloop,firstclickonthecircularShowResultindicatoratthefarrightendoftheresultssidebarforthelineletpermit="Space\(space):\(name)".Youwillseethecurrentvalueofpermitunderthecode.Control-clickontheresultandselectValueHistory(Figure2.5).Thiscanbeveryusefulfor

Page 94: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

visualizingwhatishappeninginyourplaygroundcode’sloops.Figure2.5UsingtheValueHistorytoseetheresultsofstringinterpolation

Page 95: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 96: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

EnumerationsandtheSwitchStatement

Anenumerationisatypewithadiscretesetofvalues.Defineanenumdescribingpies:enumPieType{

caseapple

casecherry

casepecan

}

letfavoritePie=PieType.apple

Swifthasapowerfulswitchstatementthat,amongotherthings,isgreatformatchingonenumvalues:letname:String

switchfavoritePie{

case.apple:

name="Apple"

case.cherry:

name="Cherry"

case.pecan:

name="Pecan"

}

Thecasesforaswitchstatementmustbeexhaustive:Eachpossiblevalueoftheswitchexpressionmustbeaccountedfor,whetherexplicitlyorviaadefault:case.UnlikeinC,Swiftswitchcasesdonotfallthrough–onlythecodeforthecasethatismatchedisexecuted.(Ifyouneedthefall-throughbehaviorofC,youcanexplicitlyrequestitusingthefallthroughkeyword.)Switchstatementscanmatchonmanytypes,evenranges:letmacOSVersion:Int=...

switchmacOSVersion{

case0...8:

print("Abigcat")

case9:

print("Mavericks")

case10:

print("Yosemite")

case11:

print("ElCapitan")

case12:

print("Sierra")

default:

print("Greetings,peopleofthefuture!What'snewin10.\(macOSVersion)?")

}

Formoreontheswitchstatementanditspatternmatchingcapabilities,seetheControlFlowsectioninApple’sTheSwiftProgrammingLanguageguide.(Moreonthatinjustamoment.)

Enumerationsandrawvalues

Swiftenumscanhaverawvaluesassociatedwiththeircases:

Page 97: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

enumPieType:Int{

caseapple=0

casecherry

casepecan

}

Withthetypespecified,youcanaskaninstanceofPieTypeforitsrawValueandtheninitializetheenumtypewiththatvalue.Thisreturnsanoptional,sincetherawvaluemaynotcorrespondwithanactualcaseoftheenum,soitisagreatcandidateforoptionalbinding.letpieRawValue=PieType.pecan.rawValue

//pieRawValueisanIntwithavalueof2

ifletpieType=PieType(rawValue:pieRawValue){

//Gotavalid'pieType'!

}

TherawvalueforanenumisoftenanInt,butitcanbeanyintegerorfloating-pointnumbertypeaswellastheStringandCharactertypes.Whentherawvalueisanintegertype,thevaluesautomaticallyincrementifnoexplicitvalueisgiven.ForPieType,onlytheapplecaseisgivenanexplicitvalue.ThevaluesforcherryandpecanareautomaticallyassignedarawValueof1and2,respectively.Thereismoretoenumerations.Eachcaseofanenumerationcanhaveassociatedvalues.YouwilllearnmoreaboutassociatedvaluesinChapter20.

Page 98: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 99: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

ExploringApple’sSwiftDocumentation

ToexploreApple’sdocumentationonSwift,startatdeveloper.apple.com/swift.Herearetwoparticularresourcestolookfor.Wesuggestbookmarkingthemandvisitingthemwhenyouwanttoreviewaparticularconceptordigalittledeeper.TheSwiftProgrammingLanguageThisguidedescribesmanyfeaturesofSwift.Itstartswiththebasicsandincludesexamplecodeandlotsofdetail.ItalsocontainsthelanguagereferenceandformalgrammarofSwift.SwiftStandardLibraryReferenceThestandardlibraryreferencelaysoutthedetailsofSwifttypes,protocols,andglobal(orfree)functions.YourhomeworkistobrowsethroughtheTypessectionoftheSwiftStandardLibraryReferenceandthesectionsofTheSwiftProgrammingLanguageguideonTheBasics,StringsandCharacters,andCollectionTypes.Solidifywhatyoulearnedinthischapterandbecomefamiliarwiththeinformationtheseresourcesoffer.Ifyouknowwheretofindthedetailswhenyouneedthem,thenyouwillfeellesspressuretomemorizethem–lettingyoufocusoniOSdevelopmentinstead.

Page 100: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 101: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

3ViewsandtheViewHierarchy

Overthenextfivechapters,youaregoingtobuildanapplicationnamedWorldTrotter.Whenitiscomplete,thisappwillconvertvaluesbetweendegreesFahrenheitanddegreesCelsius.Inthischapter,youwilllearnaboutviewsandtheviewhierarchythroughcreatingWorldTrotter’sUI.Attheendofthischapter,yourappwilllooklikeFigure3.1.Figure3.1WorldTrotter

Let’sstartwithalittlebitofthetheorybehindviewsandtheviewhierarchy.

Page 102: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

ViewBasics

RecallfromChapter1thatviewsareobjectsthatarevisibletotheuser,likebuttons,textfields,andsliders.Viewobjectsmakeupanapplication’sUI.Aview:

isaninstanceofUIVieworoneofitssubclassesknowshowtodrawitselfcanhandleevents,liketouchesexistswithinahierarchyofviewswhoserootistheapplication’swindow

Let’slookattheviewhierarchyingreaterdetail.

Page 103: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 104: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

TheViewHierarchy

EveryapplicationhasasingleinstanceofUIWindowthatservesasthecontainerforalltheviewsintheapplication.UIWindowisasubclassofUIView,sothewindowisitselfaview.Thewindowiscreatedwhentheapplicationlaunches.Oncethewindowiscreated,otherviewscanbeaddedtoit.Whenaviewisaddedtothewindow,itissaidtobeasubviewofthewindow.Viewsthataresubviewsofthewindowcanalsohavesubviews,andtheresultisahierarchyofviewobjectswiththewindowatitsroot(Figure3.2).Figure3.2Anexampleviewhierarchyandtheinterfacethatitcreates

Oncetheviewhierarchyiscreated,itwillbedrawntothescreen.Thisprocesscanbebrokenintotwosteps:

Eachviewinthehierarchy,includingthewindow,drawsitself.Itrendersitselftoitslayer,whichyoucanthinkofasabitmapimage.(ThelayerisaninstanceofCALayer.)Thelayersofalltheviewsarecompositedtogetheronthescreen.

Figure3.3depictsanotherexampleviewhierarchyandthetwodrawingsteps.

Page 105: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure3.3Viewsrenderthemselvesandthenarecompositedtogether

ForWorldTrotter,youaregoingtocreateaninterfacecomposedofdifferentviews.TherewillbefourinstancesofUILabelandoneinstanceofUITextFieldthatwillallowtheusertoenteratemperatureinFahrenheit.Let’sgetstarted.

Page 106: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 107: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

CreatingaNewProject

InXcode,selectFile→New→Project...(orusethekeyboardshortcutCommand-Shift-N).UndertheiOSsectionatthetop,choosetheSingleViewApplicationtemplateunderApplicationandclickNext.EnterWorldTrotterfortheproductname.MakesurethatSwiftisselectedfromtheLanguagedropdownandthatUniversalisselectedfromtheDevicesdropdown.AlsomakesuretheUseCoreDataboxisunchecked(Figure3.4).ClickNextandthenCreateonthefollowingscreen.Figure3.4ConfiguringWorldTrotter

Page 108: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 109: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

ViewsandFrames

Whenyouinitializeaviewprogrammatically,youuseitsinit(frame:)designatedinitializer.Thismethodtakesoneargument,aCGRect,thatwillbecometheview’sframe,apropertyonUIView.varframe:CGRect

Aview’sframespecifiestheview’ssizeanditspositionrelativetoitssuperview.Becauseaview’ssizeisalwaysspecifiedbyitsframe,aviewisalwaysarectangle.ACGRectcontainsthemembersoriginandsize.TheoriginisastructureoftypeCGPointandcontainstwoCGFloatproperties:xandy.ThesizeisastructureoftypeCGSizeandhastwoCGFloatproperties:widthandheight(Figure3.5).Figure3.5CGRect

Whentheapplicationislaunched,theviewfortheinitialviewcontrollerisaddedtotheroot-levelwindow.ThisviewcontrollerisrepresentedbytheViewControllerclassdefinedinViewController.swift.WewilldiscusswhataviewcontrollerisinChapter5,butfornow,itissufficienttoknowthataviewcontrollerhasaviewandthattheviewassociatedwiththemainviewcontrollerfortheapplicationisaddedasasubviewofthewindow.BeforeyoucreatetheviewsforWorldTrotter,youaregoingtoaddsomepracticeviewsprogrammaticallytoexploreviewsandtheirpropertiesandseehowtheinterfacesforapplicationsarecreated.

Page 110: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

OpenViewController.swiftanddeleteanymethodsthatthetemplatecreated.Yourfileshouldlooklikethis:importUIKit

classViewController:UIViewController{

}

(UIKit,whichyoualsosawinChapter1,isaframework.Aframeworkisacollectionofrelatedclassesandresources.TheUIKitframeworkdefinesmanyoftheUIelementsthatyouruserssee,aswellasotheriOS-specificclasses.Youwillbeusingafewdifferentframeworksasyougothroughthisbook.)Rightaftertheviewcontroller ’sviewisloadedintomemory,itsviewDidLoad()methodiscalled.Thismethodgivesyouanopportunitytocustomizetheviewhierarchy,soitisagreatplacetoaddyourpracticeviews.InViewController.swift,overrideviewDidLoad().CreateaCGRectthatwillbetheframeofaUIView.Next,createaninstanceofUIViewandsetitsbackgroundColorpropertytoblue.Finally,addtheUIViewasasubviewoftheviewcontroller ’sviewtomakeitpartoftheviewhierarchy.(Muchofthiswillnotlookfamiliar.Thatisfine.Wewillexplainmoreafteryouenterthecode.)classViewController:UIViewController{

overridefuncviewDidLoad(){

super.viewDidLoad()

letfirstFrame=CGRect(x:160,y:240,width:100,height:150)

letfirstView=UIView(frame:firstFrame)

firstView.backgroundColor=UIColor.blue

view.addSubview(firstView)

}

}

TocreateaCGRect,youuseitsinitializerandpassinthevaluesfororigin.x,origin.y,size.width,andsize.height.TosetthebackgroundColor,youusetheUIColorclasspropertyblue.ThisisacomputedpropertythatinitializesaninstanceofUIColorthatisconfiguredtobeblue.ThereareanumberofUIColorclasspropertiesforcommoncolors,suchasgreen,black,andclear.Buildandruntheapplication(Command-R).YouwillseeabluerectanglethatistheinstanceofUIView.BecausetheoriginoftheUIView’sframeis(160,240),therectangle’stop-leftcorneris160pointstotherightand240pointsdownfromthetop-leftcornerofitssuperview.Theviewstretches100pointstotherightand150pointsdownfromitsorigin,inaccordancewithitsframe’ssize(Figure3.6).

Page 111: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure3.6WorldTrotterwithoneUIView

Notethatthesevaluesareinpoints,notpixels.Ifthevalueswereinpixels,thentheywouldnotbeconsistentacrossdisplaysofdifferentresolutions(i.e.,Retinaversusnon-Retina).Apointisarelativeunitofameasure;itwillbeadifferentnumberofpixelsdependingonhowmanypixelsareinthedisplay.Sizes,positions,lines,andcurvesarealwaysdescribedinpointstoallowfordifferencesindisplayresolution.Figure3.7representstheviewhierarchythatyouhavecreated.

Page 112: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure3.7Currentviewhierarchy

EveryinstanceofUIViewhasasuperviewproperty.Whenyouaddaviewasasubviewofanotherview,theinverserelationshipisautomaticallyestablished.Inthiscase,theUIView’ssuperviewistheUIWindow.Let’sexperimentwiththeviewhierarchy.First,inViewController.swift,createanotherinstanceofUIViewwithadifferentframeandbackgroundcolor.overridefuncviewDidLoad(){

super.viewDidLoad()

letfirstFrame=CGRect(x:160,y:240,width:100,height:150)

letfirstView=UIView(frame:firstFrame)

firstView.backgroundColor=UIColor.blue

view.addSubview(firstView)

letsecondFrame=CGRect(x:20,y:30,width:50,height:50)

letsecondView=UIView(frame:secondFrame)

secondView.backgroundColor=UIColor.green

view.addSubview(secondView)

}

Buildandrunagain.Inadditiontothebluerectangle,youwillseeagreensquarenearthetop-leftcornerofthewindow.Figure3.8showstheupdatedviewhierarchy.

Page 113: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure3.8Updatedviewhierarchywithtwosubviewsassiblings

NowyouaregoingtoadjusttheviewhierarchysothatoneinstanceofUIViewisasubviewoftheotherUIViewinsteadoftheviewcontroller ’sview.InViewController.swift,addsecondViewasasubviewoffirstView....

letsecondView=UIView(frame:secondFrame)

secondView.backgroundColor=UIColor.green

view.addSubview(secondView)

firstView.addSubview(secondView)

Yourviewhierarchyisnowfourlevelsdeep,asshowninFigure3.9.

Page 114: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure3.9OneUIViewasasubviewoftheother

Buildandruntheapplication.NoticethatsecondView’spositiononthescreenhaschanged(Figure3.10).Aview’sframeisrelativetoitssuperview,sothetop-leftcornerofsecondViewisnowinset(20,30)pointsfromthetop-leftcorneroffirstView.

Page 115: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure3.10WorldTrotterwithnewhierarchy

(IfthegreeninstanceofUIViewlookssmallerthanitdidpreviously,thatisjustanopticalillusion.Itssizehasnotchanged.)Nowthatyouhaveseenthebasicsofviewsandtheviewhierarchy,youcanstartworkingontheinterfaceforWorldTrotter.Insteadofbuildinguptheinterfaceprogrammatically,youwilluseInterfaceBuildertovisuallylayouttheinterface,asyoudidinChapter1.InViewController.swift,startbyremovingyourpracticecode.overridefuncviewDidLoad(){

super.viewDidLoad()

letfirstFrame=CGRect(x:160,y:240,width:100,height:150)

letfirstView=UIView(frame:firstFrame)

firstView.backgroundColor=UIColor.blue

view.addSubview(firstView)

letsecondFrame=CGRect(x:20,y:30,width:50,height:50)

Page 116: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

letsecondView=UIView(frame:secondFrame)

secondView.backgroundColor=UIColor.green

firstView.addSubview(secondView)

}

Nowlet’saddsomeviewstotheinterfaceandsettheirframes.OpenMain.storyboard.Atthebottomofthecanvas,makesuretheViewasbuttonisconfiguredtodisplayaniPhone7device.Fromtheobjectlibrary,dragfiveinstancesofUILabelontothecanvas.SettheirtexttomatchFigure3.11.Asshown,spacethemoutverticallyonthetophalfoftheinterfaceandcenterthemhorizontally.Figure3.11Addinglabelstotheinterface

SelectthetoplabelsoyoucanseeitsframeinInterfaceBuilder.Openitssizeinspector–thefifthtabintheutilitiesarea.(ThekeyboardshortcutsfortheutilitiestabsareCommand-Optionplusthetabnumber.Thesizeinspectoristhefifthtab,soitskeyboardshortcutis

Page 117: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Command-Option-5.)UndertheViewsection,findFrameRectangle.(Ifyoudonotseeit,youmightneedtoselectitfromtheShowpop-upmenu.)Thevaluesshownaretheview’sframe,andtheydictatethepositionoftheviewonscreen(Figure3.12).Figure3.12Viewframevalues

BuildandruntheapplicationontheiPhone7simulator.TheinterfaceonthesimulatorwilllookidenticaltotheinterfacethatyoulaidoutinInterfaceBuilder.

Customizingthelabels

Let’smaketheinterfacelookalittlebitbetterbycustomizingtheviewproperties.InMain.storyboard,selectthebackgroundview.Opentheattributesinspectorandgivetheappanewbackgroundcolor:FindandclicktheBackgrounddropdownandclickOther....Selectthesecondtab(theColorSliderstab)andchooseRGBSlidersfromthedropdown.Intheboxnearthebottom,enteraHexColor#ofF5F4F1(Figure3.13).Thiswillgivethebackgroundawarmgraycolor.

Page 118: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure3.13Changingthebackgroundcolor

Youcancustomizeattributescommontoselectedviewssimultaneously.Youwillusethistogivemanyofthelabelsalargerfontsizeaswellasaburntorangetextcolor.SelectthetoptwoandbottomtwolabelsbyCommand-clickingtheminthedocumentoutline.Makesuretheattributesinspectorisopenandupdatethetextcolor:UndertheLabelsection,findColorandopenthepop-upmenu.SelecttheColorSliderstabagainandenteraHexColor#ofE15829.Nowlet’supdatethefont.Selectthe212and100labels.UndertheLabelsectionintheattributesinspector,findFontandclickonthetexticonnexttothecurrentfont.Inthepopoverthatappears,maketheSize70(Figure3.14).Selecttheremainingthreelabels.OpentheirFontpop-upandmaketheSize36.

Page 119: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure3.14Customizingthelabels’font

Nowthatthefontsizeislarger,thetextnolongerfitswithintheboundsofthelabel.Youcouldresizethelabelsmanually,butthereisaneasierway.Selectthetoplabelonthecanvas.FromXcode’sEditormenu,selectSizetoFitContent(Command-=).Thiswillresizethelabeltoexactlyfititstextcontents.Repeattheprocessfortheotherfourlabels.(Youcanselectallfourlabelstoresizethemallatonce.)Nowmovethelabelssothattheyareagainnicelyalignedverticallyandcenteredhorizontally(Figure3.15).

Page 120: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure3.15Updatingthelabelframes

BuildandruntheapplicationontheiPhone7simulator.NowbuildandruntheapplicationontheiPhone7Plussimulator.Noticethatthelabelsarenolongercentered–instead,theyappearshiftedslightlytotheleft.Youhavejustseentwoofthemajorproblemswithabsoluteframes.First,whenthecontentschange(likewhenyouchangedthefontsize),theframesdonotautomaticallyupdate.Second,theviewdoesnotlookequallygoodondifferentsizesofscreens.Ingeneral,youshouldnotuseabsoluteframesforyourviews.Instead,youshoulduseAutoLayouttoflexiblycomputetheframesforyoubasedonconstraintsthatyouspecifyforeachview.Forexample,whatyoureallywantforWorldTrotterisforthelabelstoremainthesamedistancefromthetopofthescreenandtoremainhorizontallycenteredwithintheirsuperview.Theyshouldalsoupdateifthefontortextofthelabelschange.Thisiswhatyouwillaccomplishinthenextsection.

Page 121: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 122: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

TheAutoLayoutSystem

Beforeyoucanfixthelabelstohavethemlayoutflexibly,youneedtolearnalittletheoryabouttheAutoLayoutsystem.AsyousawinChapter1,absolutecoordinatesmakeyourlayoutfragilebecausetheyassumethatyouknowthesizeofthescreenaheadoftime.UsingAutoLayout,youcandescribethelayoutofyourviewsinarelativewaythatenablestheirframestobedeterminedatruntimesothattheframes’definitionscantakeintoaccountthescreensizeofthedevicethattheapplicationisrunningon.

Thealignmentrectangleandlayoutattributes

TheAutoLayoutsystemisbasedonthealignmentrectangle.Thisrectangleisdefinedbyseverallayoutattributes(Figure3.16).Figure3.16Layoutattributesdefininganalignmentrectangleofaview

Width/Height

Thesevaluesdeterminethealignmentrectangle’ssize.Top/BottomLeft/Right

Thesevaluesdeterminethespacingbetweenthegivenedgeofthealignmentrectangleandthealignmentrectangleofanotherviewinthehierarchy.CenterXCenterY

Thesevaluesdeterminethecenterpointofthealignmentrectangle.FirstBaselineLastBaseline

Thesevaluesarethesameasthebottomattributeformost,butnotall,views.Forexample,UITextFielddefinesitsbaselinesasthebottomofthetextitdisplaysratherthanthebottomofthealignmentrectangle.Thiskeeps“descenders”(thepartsofletterslike“g”and“p”thatdescendbelowthebaseline)frombeingobscuredbyaviewrightbelowthetextfield.Formultilinetextlabelsandtextviews,thefirstandlastbaselinerefertothefirstandlastlineoftext.Inallothersituations,thefirstandlastbaselinearethesame.

Page 123: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

LeadingTrailing

Thesevaluesarelanguage-specificattributes.Ifthedeviceissettoalanguagethatreadslefttoright(e.g.,English),thentheleadingattributeisthesameastheleftattributeandthetrailingattributeisthesameastherightattribute.Ifthelanguagereadsrighttoleft(e.g.,Arabic),thentheleadingattributeisontherightandthetrailingattributeisontheleft.InterfaceBuilderautomaticallyprefersleadingandtrailingoverleftandright,and,ingeneral,youshouldaswell.Bydefault,everyviewhasanalignmentrectangle,andeveryviewhierarchyusesAutoLayout.Thealignmentrectangleisverysimilartotheframe.Infact,thesetworectanglesareoftenthesame.Whereastheframeencompassestheentireview,thealignmentrectangleonlyencompassesthecontentthatyouwishtouseforalignmentpurposes.Figure3.17showsanexamplewheretheframeandthealignmentrectanglearedifferent.Figure3.17Framevsalignmentrectangle

Youcannotdefineaview’salignmentrectangledirectly.Youdonothaveenoughinformation(likescreensize)todothat.Instead,youprovideasetofconstraints.Takentogether,theseconstraintsenablethesystemtodeterminethelayoutattributes,andthusthealignmentrectangle,foreachviewintheviewhierarchy.

Constraints

Aconstraintdefinesaspecificrelationshipinaviewhierarchythatcanbeusedtodeterminealayoutattributeforoneormoreviews.Forexample,youmightaddaconstraintlike,“Theverticalspacebetweenthesetwoviewsshouldalwaysbe8points,”or,“Theseviewsmustalwayshavethesamewidth.”Aconstraintcanalsobeusedtogiveaviewafixedsize,like,“Thisview’sheightshouldalwaysbe44points.”Youdonotneedaconstraintforeverylayoutattribute.Somevaluesmaycomedirectlyfromaconstraint;otherswillbecomputedbythevaluesofrelatedlayoutattributes.Forexample,ifaview’sconstraintssetitsleftedgeanditswidth,thentherightedgeisalreadydetermined(leftedge+width=rightedge,always).Asageneralruleofthumb,youneedatleasttwoconstraintsperdimension(horizontalandvertical).If,afteralloftheconstraintshavebeenconsidered,thereisstillanambiguousormissing

Page 124: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

valueforalayoutattribute,thentherewillbeerrorsandwarningsfromAutoLayoutandyourinterfacewillnotlookasyouexpectonalldevices.Debuggingtheseproblemsisimportant,andyouwillgetsomepracticelaterinthischapter.Howdoyoucomeupwithconstraints?Let’sseehow,usingthelabelsthatyouhavelaidoutonthecanvas.First,describewhatyouwanttheviewtolooklikeindependentofscreensize.Forexample,youmightsaythatyouwantthetoplabeltobe:

8pointsfromthetopofthescreencenteredhorizontallyinitssuperviewaswideandastallasitstext

ToturnthisdescriptionintoconstraintsinInterfaceBuilder,itwillhelptounderstandhowtofindaview’snearestneighbor.Thenearestneighboristheclosestsiblingviewinthespecifieddirection(Figure3.18).Figure3.18Nearestneighbor

Ifaviewdoesnothaveanysiblingsinthespecifieddirection,thenthenearestneighborisitssuperview,alsoknownasitscontainer.Nowyoucanspellouttheconstraintsforthelabel:

Page 125: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

1. Thelabel’stopedgeshouldbe8pointsawayfromitsnearestneighbor(whichisitscontainer–theviewoftheViewController).

2. Thelabel’scentershouldbethesameasitssuperview’scenter.3. Thelabel’swidthshouldbeequaltothewidthofitstextrenderedatitsfontsize.4. Thelabel’sheightshouldbeequaltotheheightofitstextrenderedatitsfontsize.

Ifyouconsiderthefirstandfourthconstraints,youcanseethatthereisnoneedtoexplicitlyconstrainthelabel’sbottomedge.Itwillbedeterminedfromtheconstraintsonthelabel’stopedgeandthelabel’sheight.Similarly,thesecondandthirdconstraintstogetherdeterminethelabel’srightandleftedges.Nowthatyouhaveaplanforthetoplabel,youcanaddtheseconstraints.ConstraintscanbeaddedusingInterfaceBuilderorincode.ApplerecommendsthatyouaddconstraintsusingInterfaceBuilderwheneverpossible,andthatiswhatyouwilldohere.However,ifyourviewsarecreatedandconfiguredprogrammatically,thenyoucanaddconstraintsincode.InChapter6,youwillpracticethatapproach.

AddingconstraintsinInterfaceBuilder

Let’sgetstartedconstrainingthattoplabel.Selectthetoplabelonthecanvas.Inthebottom-rightcornerofthecanvas,findtheAutoLayoutconstraintmenus(Figure3.19).Figure3.19AutoLayoutconstraintmenus

Page 126: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Clickthe icon(thefourthfromtheleft)torevealtheAddNewConstraintsmenu.Thismenushowsyouthecurrentsizeandpositionofthelabel.AtthetopoftheAddNewConstraintsmenuarefourvaluesthatdescribethelabel’scurrentspacingfromitsnearestneighboronthecanvas.Forthislabel,youareonlyinterestedinthetopvalue.Toturnthisvalueintoaconstraint,clickthetopredstrutseparatingthevaluefromthesquareinthemiddle.Thestrutwillbecomeasolidredline.Inthemiddleofthemenu,findthelabel’sWidthandHeight.ThevaluesnexttoWidthandHeightindicatethecurrentcanvasvalues.Toconstrainthelabel’swidthandheighttothecurrentcanvasvalues,checktheboxesnexttoWidthandHeight.ThebuttonatthebottomofthemenureadsAdd3Constraints.Clickthisbutton.Atthispoint,youhavenotspecifiedenoughconstraintstofullydeterminethealignmentrectangle.Theredoutlinearoundthelabelindicatesthatitsalignmentrectangleisincompletelydefined,andInterfaceBuilderwillhelpyoudeterminewhattheproblemis.Inthetop-rightcornerofInterfaceBuilder,noticetheyellowwarningsign(Figure3.20).Clickonthisicontorevealtheissue:Horizontalpositionisambiguousfor"212".

Page 127: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure3.20Horizontalambiguity

Youhaveaddedtwoverticalconstraints(atopedgeconstraintandaheightconstraint),butyouhaveonlyaddedonehorizontalconstraint(awidthconstraint).Havingonlyoneconstraintmakesthehorizontalpositionofthelabelambiguous.Youwillfixthisissuebyaddingacenteralignmentconstraintbetweenthelabelanditssuperview.Withthetoplabelstillselected,clickthe icon(thethirdiconfromtheleft)torevealtheAlignmenu.Ifyouhavemultipleviewsselected,thismenuwillallowyoutoalignattributesamongtheviews.Becauseyouhaveonlyselectedonelabel,theonlyoptionsyouaregivenaretoaligntheviewwithinitscontainer.IntheAlignmenu,checkHorizontallyinContainer(donotclickAdd1Constraintyet).Onceyouaddthisconstraint,therewillbeenoughconstraintstofullydeterminethealignmentrectangle.Toensurethattheframeofthelabelmatchestheconstraintsspecified,opentheUpdateFramespop-upmenufromtheAlignmenuandselectItemsofNewConstraints.Thiswillrepositionthelabeltomatchtheconstraintsthathavebeenadded.NowclickonAdd1Constrainttoaddthecenteringconstraintandrepositionthelabel.Thelabel’sconstraintsareallbluenowthatthealignmentrectangleforthelabelisfullyspecified.Additionally,thewarningatthetop-rightcornerofInterfaceBuilderisnowgone.BuildandruntheapplicationontheiPhone7simulatorandtheiPhone7Plussimulator.Thetoplabelwillremaincenteredinbothsimulators.

Intrinsiccontentsize

Althoughthetoplabel’spositionisflexible,itssizeisnot.Thisisbecauseyouhaveaddedexplicitwidthandheightconstraintstothelabel.Ifthetextorfontweretochange,youwouldbeinthesamepositionyouwereinearlier.Thesizeoftheframeisabsolute,sotheframewouldnothugtothecontent.Thisiswheretheintrinsiccontentsizeofaviewcomesintoplay.Youcanthinkoftheintrinsiccontentsizeasthesizethataview“wants”tobe.Forlabels,thissizeisthesizeofthetextrenderedatthegivenfont.Forimages,thisisthesizeoftheimageitself.Aview’sintrinsiccontentsizeactsasimplicitwidthandheightconstraints.Ifyoudonotspecifyconstraintsthatexplicitlydeterminethewidth,theviewwillbeitsintrinsicwidth.Thesamegoesfortheheight.Withthisknowledge,letthetoplabelhaveaflexiblesizebyremovingtheexplicitwidthandheightconstraints.InMain.storyboard,selectthewidthconstraintonthelabel.Youcandothisbyclickingontheconstraintonthecanvas.Alternatively,inthedocumentoutline,youcanclickonthe

Page 128: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

disclosuretrianglenexttothe212label,thendisclosethelistofconstraintsforthelabel(Figure3.21).Figure3.21Selectingthewidthconstraint

Onceyouhaveselectedthewidthconstraint,presstheDeletekey.Dothesamefortheheightconstraint.Noticethattheconstraintsforthelabelarestillblue.Becausethewidthandheightarebeinginferredfromthelabel’sintrinsiccontentsize,therearestillenoughconstraintstodeterminethelabel’salignmentrectangle.

Misplacedviews

Asyouhaveseen,blueconstraintsindicatethatthealignmentrectangleforaviewisfully

Page 129: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

specified.Orangeconstraintsoftenindicateamisplacedview.ThismeansthattheframefortheviewinInterfaceBuilderisdifferentthantheframethatAutoLayouthascomputed.Amisplacedviewisveryeasytofix.Thatisgood,becauseitisalsoaverycommonissuethatyouwillencounterwhenworkingwithAutoLayout.Giveyourtoplabelamisplacedviewsothatyoucanseehowtoresolvethisissue.Resizethetoplabelonthecanvasusingtheresizecontrolsandlookfortheyellowwarninginthetop-rightcornerofthecanvas.Clickonthiswarningicontorevealtheproblem:Framefor"212"willbedifferentatruntime(Figure3.22).Figure3.22Misplacedviewwarning

Asthewarningsays,theframeatruntimewillnotbethesameastheframespecifiedonthecanvas.Ifyoulookclosely,youwillseeanorangedottedlinethatindicateswhattheruntimeframewillbe.Buildandruntheapplication.NoticethatthelabelisstillcentereddespitethenewframethatyougaveitinInterfaceBuilder.Thismightseemgreat–yougettheresultthatyouwant,afterall.ButthedisconnectbetweenwhatyouhavespecifiedinInterfaceBuilderandtheconstraintscomputedbyAutoLayoutwillcauseproblemsdownthelineasyoucontinuetobuildyourviews.Let’sfixthemisplacedview.Backinthestoryboard,selectthetoplabelonthecanvas.Clickthe icon(theleft-mosticon)toupdatetheframeofthelabeltomatchtheframethattheconstraintswillcompute.YouwillgetveryusedtoupdatingtheframesofviewsasyouworkwithAutoLayout.Onewordofcaution:Ifyoutrytoupdatetheframesforaviewthatdoesnothaveenoughconstraints,youwillalmostcertainlygetunexpectedresults.Ifthathappens,undothechangeandinspecttheconstraintstoseewhatismissing.Atthispoint,thetoplabelisingoodshape.Ithasenoughconstraintstodetermineitsalignmentrectangle,andtheviewislayingoutthewayyouwant.BecomingproficientwithAutoLayouttakesalotofexperience,sointhenextsectionyouare

Page 130: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

goingtoremovetheconstraintsfromthetoplabelandthenaddconstraintstoallofthelabels.

Addingmoreconstraints

Let’sfleshouttheconstraintsfortherestoftheviews.Beforeyoudothat,youwillremovetheexistingconstraintsfromthetoplabel.Selectthetoplabelonthecanvas.OpentheResolveAutoLayoutIssuesmenuandselectClearConstraintsfromtheSelectedViewssection(Figure3.23).Figure3.23Clearingconstraints

Youaregoingtoaddtheconstraintstoalloftheviewsintwosteps.Firstyouwillcenterthetoplabelhorizontallywithinthesuperview.Thenyouwilladdconstraintsthatpinthetopofeachlabeltoitsnearestneighborwhilealigningthecentersofallofthelabels.Selectthetoplabel.OpentheAlignmenuandchooseHorizontallyinContainerwithaconstantof0.MakesurethatUpdateFrameshasNoneselected;rememberthatyoudonotwanttoupdatetheframeofaviewthatdoesnothaveenoughconstraints,andthisoneconstraintwillcertainlynotprovideenoughinformationtocomputethealignmentrectangle.GoaheadandAdd1Constraint.Nowselectallfivelabelsonthecanvas.Itcanbeveryconvenienttoaddconstraintstomultipleviewssimultaneously.OpentheAddNewConstraintsmenuandmakethefollowingchoices:1. Selectthetopstrutandmakesureithasaconstantof8.2. FromtheAlignmenu,chooseHorizontalCenters.3. FromtheUpdateFramesmenu,chooseItemsofNewConstraints.

YourmenushouldmatchFigure3.24.Onceitdoes,clickAdd9Constraints.ThiswilladdtheconstraintstotheviewsandupdatetheirframestoreflecttheAutoLayoutchanges.

Page 131: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure3.24AddingmoreconstraintswiththeAddNewConstraintsmenu

BuildandruntheapplicationontheiPhone7simulator.Theviewswillbecenteredwithintheinterface.NowbuildandruntheapplicationontheiPhone7Plussimulator.Unlikeearlierinthechapter,allofthelabelsremaincenteredonthelargerinterface.AutoLayoutisacrucialtechnologyforeveryiOSdeveloper.Ithelpsyoucreateflexiblelayoutsthatworkacrossarangeofdevicesandinterfacesizes.Italsotakesalotofpracticetomaster.YouwillgetalotofexperienceusingAutoLayoutasyouworkthroughthisbook.

Page 132: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 133: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

BronzeChallenge:MoreAutoLayoutPractice

RemovealloftheconstraintsfromtheViewControllerinterfaceandthenaddthembackin.Trytodothiswithoutconsultingthebook.

Page 134: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 135: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

4TextInputandDelegation

WorldTrotterlooksgood,butsofaritdoesnotdoanything.Inthischapter,youaregoingtoaddaninstanceofUITextFieldtoWorldTrotter.ThetextfieldwillallowtheusertotypeinatemperatureinFahrenheitthatwillthenbeconvertedtoCelsiusanddisplayedontheinterface(Figure4.1).Figure4.1WorldTrotterwithaUITextField

Page 136: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

TextEditing

ThefirstthingyouaregoingtodoisaddaUITextFieldtotheinterfaceandsetuptheconstraintsforthattextfield.Thistextfieldwillreplacethetoplabelintheinterfacethatcurrentlyhasthetext“212.”OpenMain.storyboard.SelectthetoplabelandpresstheDeletekeytoremovethissubview.Theconstraintsforalloftheotherlabelswillturnredbecausetheywerealldirectlyorindirectlyanchoredtothattoplabel(Figure4.2).ThatisOK;youwillfixthemshortly.Figure4.2Ambiguousframesforthelabels

OpentheobjectlibraryanddragaTextFieldtothetopofthecanvaswherethelabelyoudeletedwaspreviouslyplaced.Nowsetuptheconstraintsforthistextfield.Withthetextfieldselected,opentheAlignmenuandaligntheviewHorizontallyinContainerwithaconstantof0.MakesurethatUpdateFramesissettoNoneandthenAdd1Constraint.NowopentheAddNewConstraintsmenu.Givethetextfieldatopedgeconstraintof8points,abottomedgeconstraintof8points,andawidthof250(Figure4.3).Addthesethreeconstraints.

Page 137: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure4.3TextfieldAddNewConstraintsmenu

Finally,selectthetextfieldandthelabelrightbelowit.OpentheAlignmenu,selectHorizontalCenterswithaconstantof0,UpdateFramesforAllFramesinContainer,andfinallyAdd1Constraint(Figure4.4).

Page 138: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure4.4Aligningthetextfield

Next,customizesomeofthetextfieldproperties.Opentheattributesinspectorforthetextfieldandmakethefollowingchanges:

Setthetextcolor(fromtheColormenu)toburntorange.SetthefontsizetoSystem70.SettheAlignmenttocentered.Settheplaceholdertexttobevalue.Thisisthetextthatwillbedisplayedwhentheuserhasnotenteredanytext.SettheBorderStyletobenone,whichisthefirstelementofthesegmentedcontrolwiththedottedlines.

TheattributesinspectorforyourtextfieldshouldlooklikeFigure4.5.

Page 139: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure4.5Textfieldattributesinspector

Becausethetextfield’sfontchanged,theviewsonthecanvasnowaremisplaced.Selectthegraybackgroundview,opentheResolveAutoLayoutIssuesmenu,andselectUpdateFramesfromtheAllViewsinViewControllersection.Thetextfieldandlabelswillberepositionedtomatchtheirconstraints(Figure4.6).

Page 140: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure4.6Updatedframes

Buildandruntheapplication.Taponthetextfieldandentersometext.Ifyoudonotseethekeyboard,clickthesimulator ’sHardwaremenuandselectKeyboard→ToggleSoftwareKeyboardorusethekeyboardshortcutCommand-K.Bydefault,thesimulatortreatsyourcomputer ’skeyboardasaBluetoothkeyboardconnectedtothesimulator.Thisisnotusuallywhatyouwant.Instead,youwantthesimulatortomimicaniOSdevicerunningwithoutanyaccessoriesattachedbyusingtheonscreenkeyboard.

Keyboardattributes

Whenatextfieldistapped,thekeyboardautomaticallyslidesupontothescreen.(Youwillseewhythishappenslaterinthischapter.)Thekeyboard’sappearanceisdeterminedbyasetoftheUITextField’spropertiescalledtheUITextInputTraits.Oneofthesepropertiesisthetypeofkeyboardthatisdisplayed.Forthisapplication,youwanttousethedecimalpad.Intheattributesinspectorforthetextfield,findtheattributenamedKeyboardTypeandchooseDecimalPad.Inthesamesection,youcanseesomeoftheothertextinputtraitsthatyoucancustomizeforthekeyboard.ChangebothCorrectionandSpellCheckingtoNo(Figure4.7).

Page 141: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure4.7Keyboardtextinputtraits

Buildandruntheapplication.Tappingonthetextfieldwillnowrevealthedecimalpad.

Respondingtotextfieldchanges

ThenextstepoftheprojectwillbetoupdatetheCelsiuslabelwhentextistypedintothetextfield.Youaregoingtoneedtowritesomecodetodothis.Specifically,thiscodewillgointotheviewcontrollersubclassassociatedwiththisinterface.Currently,thatcorrespondswiththeViewControllerclassdefinedinViewController.swift.However,ViewControllerisnotaverydescriptivenameforaviewcontrollerthatmanagestheconversionbetweenFahrenheitandCelsius.Havingdescriptivetypenamesallowsyoutomoreeasilymaintainyourprojectsastheygrowlarger.Youaregoingtodeletethisfileandreplaceitwithamoredescriptiveclass.Intheprojectnavigator,findViewController.swiftanddeleteit.ThencreateanewfilebyselectingFile→New→File...(orpressCommand-N).WithiOSselectedatthetop,chooseSwiftFileundertheSourcelabelandclickNext.Onthenextpane,namethisfileConversionViewController.SavethefileintheWorldTrottergroupwithintheWorldTrotterprojectandmakesurethattheWorldTrottertargetischecked,asshowninFigure4.8.ClickCreate,andXcodewillopenConversionViewController.swiftintheeditor.

Page 142: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure4.8SavingaSwiftfile

InConversionViewController.swift,importUIKitanddefineanewviewcontrollernamedConversionViewController.importFoundation

importUIKit

classConversionViewController:UIViewController{

}

NowyouneedtoassociatetheinterfaceyoucreatedinMain.storyboardwiththisnewviewcontroller.OpenMain.storyboardandselecttheViewController,eitherinthedocumentoutlineorbyclickingtheyellowcircleabovetheinterface.Opentheidentityinspector,whichisthethirdtabintheutilitiesview(Command-Option-3).Atthetop,findtheCustomClasssectionandchangetheClasstoConversionViewController(Figure4.9).(YouwilllearnwhatallofthisisdoinginChapter5.)Figure4.9Changingthecustomclass

YousawinChapter1thatabuttoncansendeventstoacontrollerwhenthebuttonistapped.Textfieldsareanothercontrol(bothUIButtonandUITextFieldaresubclassesofUIControl)andcansendaneventwhenthetextchanges.

Page 143: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Togetthisallworking,youwillneedtocreateanoutlettotheCelsiustextlabelandcreateanactionforthetextfieldtocallwhenthetextchanges.OpenConversionViewController.swiftanddefinethisoutletandaction.Fornow,thelabelwillbeupdatedwithwhatevertexttheusertypesintothetextfield.classConversionViewController:UIViewController{

@IBOutletvarcelsiusLabel:UILabel!

@IBActionfuncfahrenheitFieldEditingChanged(_textField:UITextField){

celsiusLabel.text=textField.text

}

}

OpenMain.storyboardtomaketheseconnections.TheoutletwillbeconnectedjustasyoudidinChapter1.Control-dragfromtheConversionViewControllertotheCelsiuslabel(theonethatcurrentlysays“100”)andconnectittothecelsiusLabel.Connectingtheactionwillbealittledifferentbecauseyouwanttheactiontobetriggeredwhentheeditingchanges.Selectthetextfieldonthecanvasandopenitsconnectionsinspectorfromtheutilitypane(theright-mosttab,orCommand-Option-6).Theconnectionsinspectorallowsyoutomakeconnectionsandseewhatconnectionshavealreadybeenmade.YouaregoingtohavechangestothetextfieldtriggertheactionyoudefinedinConversionViewController.Intheconnectionsinspector,locatetheSentEventssectionandtheEditingChangedevent.ClickanddragfromthecircletotherightofEditingChangedtotheConversionViewControllerandclickthefahrenheitFieldEditingChanged:actioninthepop-upmenu(Figure4.10).Figure4.10Connectingtheeditingchangedevent

Page 144: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Buildandruntheapplication.Tapthetextfieldandtypesomenumbers.TheCelsiuslabelwillmimicthetextthatistypedin.Nowdeletethetextinthetextfieldandnoticehowthelabelseemstogoaway.Alabelwithnotexthasanintrinsiccontentwidthandheightof0,sothelabelsbelowitmoveup.Let’sfixthisissue.InConversionViewController.swift,updatefahrenheitFieldEditingChanged(_:)todisplay“???”ifthetextfieldisempty.@IBActionfuncfahrenheitFieldEditingChanged(_textField:UITextField){

celsiusLabel.text=textField.text

iflettext=textField.text,!text.isEmpty{

celsiusLabel.text=text

}else{

celsiusLabel.text="???"

}

}

Ifthetextfieldhastextandthattextisnotempty,itwillbesetonthecelsiusLabel.Ifeitherofthoseconditionsarenottrue,thenthecelsiusLabelwillbegiventhestring“???”.Buildandruntheapplication.Addsometext,deleteit,andconfirmthatthecelsiusLabelispopulatedwith“???”whenthetextfieldisempty.

Dismissingthekeyboard

Currently,thereisnowaytodismissthekeyboard.Let’saddthatfunctionality.OnecommonwayofdoingthisisbydetectingwhentheusertapstheReturnkeyandusingthatactiontodismissthekeyboard;youwillusethisapproachinChapter14.BecausethedecimalpaddoesnothaveaReturnkey,youwillallowtheusertotaponthebackgroundviewtotriggerthedismissal.Whenthetextfieldistapped,themethodbecomeFirstResponder()iscalledonit.Thisisthemethodthat,amongotherthings,causesthekeyboardtoappear.Todismissthekeyboard,youcallthemethodresignFirstResponder()onthetextfield.YouwilllearnmoreaboutthesemethodsinChapter14.ForWorldTrotter,youwillneedanoutlettothetextfieldandamethodthatistriggeredwhenthebackgroundviewistapped.ThismethodwillcallresignFirstResponder()onthetextfieldoutlet.Let’stakecareofthecodefirst.OpenConversionViewController.swiftanddeclareanoutletnearthetoptoreferencethetextfield.@IBOutletvarcelsiusLabel:UILabel!

@IBOutletvartextField:UITextField!

Nowimplementanactionmethodthatwilldismissthekeyboardwhencalled.(Inthecodeabove,weincludedexistingcodesothatyoucouldpositionthenewcodecorrectly.Inthecodebelow,wedonotprovidethatcontextbecausethepositionofthenew

Page 145: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

codeisnotimportantsolongasitiswithinthecurlybracesforthetypebeingimplemented–inthiscase,theConversionViewControllerclass.Whenacodeblockincludesallnewcode,wesuggestthatyouputitattheendofthetype’simplementation,justinsidethefinalclosingbrace.InChapter15,youwillseehowtoeasilynavigatewithinanimplementationfilewhenyourfilesgetlongerandmorecomplex.)@IBActionfuncdismissKeyboard(_sender:UITapGestureRecognizer){

textField.resignFirstResponder()

}

Twothingsarestillneeded:ThetextFieldoutletneedstobeconnectedinthestoryboardfile,andyouneedawayoftriggeringthedismissKeyboard(_:)methodyouadded.Totakecareofthefirstitem,openMain.storyboardandselecttheConversionViewController.Control-dragfromtheConversionViewControllertothetextfieldonthecanvasandconnectittothetextFieldoutlet.Nowyouneedawayoftriggeringthemethodyouimplemented.Youwilluseagesturerecognizertoaccomplishthis.AgesturerecognizerisasubclassofUIGestureRecognizerthatdetectsaspecifictouchsequenceandcallsanactiononitstargetwhenthatsequenceisdetected.Therearegesturerecognizersthatdetecttaps,swipes,longpresses,andmore.Inthischapter,youwilluseaUITapGestureRecognizertodetectwhentheusertapsthebackgroundview.YouwilllearnmoreaboutgesturerecognizersinChapter19.InMain.storyboard,findTapGestureRecognizerintheobjectlibrary.DragthisobjectontothebackgroundviewfortheConversionViewController.Youwillseeareferencetothisgesturerecognizerinthescenedock,therowoficonsabovethecanvas.Control-dragfromthegesturerecognizerinthescenedocktotheConversionViewControllerandconnectittothedismissKeyboard:method(Figure4.11).

Page 146: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure4.11Connectingthegesturerecognizeraction

Page 147: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 148: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

ImplementingtheTemperatureConversion

Withthebasicsoftheinterfacewiredup,let’simplementtheconversionfromFahrenheittoCelsius.YouaregoingtostorethecurrentFahrenheitvalueandcomputetheCelsiusvaluewheneverthetextfieldchanges.InConversionViewController.swift,addapropertyfortheFahrenheitvalue.Thiswillbeanoptionalmeasurementfortemperature(aMeasurement<UnitTemperature>?).@IBOutletvarcelsiusLabel:UILabel!

varfahrenheitValue:Measurement<UnitTemperature>?

Thereasonthispropertyisoptionalisbecausetheusermightnothavetypedinanumber,similartotheemptystringissueyoufixedearlier.NowaddacomputedpropertyfortheCelsiusvalue.ThisvaluewillbecomputedbasedontheFahrenheitvalue.varfahrenheitValue:Measurement<UnitTemperature>?

varcelsiusValue:Measurement<UnitTemperature>?{

ifletfahrenheitValue=fahrenheitValue{

returnfahrenheitValue.converted(to:.celsius)

}else{

returnnil

}

}

FirstyouchecktoseewhetherthereisaFahrenheitvalue.Ifthereis,youconvertthisvaluetotheequivalentvalueinCelsius.IfthereisnoFahrenheitvalue,thenyoucannotcomputeaCelsiusvalueandsoyoureturnnil.AnytimetheFahrenheitvaluechanges,theCelsiuslabelneedstobeupdated.Takecareofthatnext.AddamethodtoConversionViewControllerthatupdatesthecelsiusLabel.funcupdateCelsiusLabel(){

ifletcelsiusValue=celsiusValue{

celsiusLabel.text="\(celsiusValue.value)"

}else{

celsiusLabel.text="???"

}

}

YouwantthismethodtobecalledwhenevertheFahrenheitvaluechanges.Todothis,youwilluseapropertyobserver,whichisachunkofcodethatgetscalledwheneveraproperty’svaluechanges.Apropertyobserverisdeclaredusingcurlybracesimmediatelyafterthepropertydeclaration.Insidethebraces,youdeclareyourobserverusingeitherwillSetordidSet,dependingonwhetheryouwanttobenotifiedimmediatelybeforeorimmediatelyafterthepropertyvaluechanges,respectively.AddapropertyobservertofahrenheitValuethatgetscalledafterthepropertyvalue

Page 149: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

changes.varfahrenheitValue:Measurement<UnitTemperature>?{

didSet{

updateCelsiusLabel()

}

}

(Onesmallnote:Propertyobserversarenottriggeredwhenthepropertyvalueischangedfromwithinaninitializer.)Withthatlogicinplace,youcannowupdatetheFahrenheitvaluewhenthetextfieldchanges(which,inturn,willtriggeranupdateoftheCelsiuslabel).InfahrenheitFieldEditingChanged(_:),deleteyourearliernonconvertingimplementationandinsteadupdatetheFahrenheitvalue.@IBActionfuncfahrenheitFieldEditingChanged(_textField:UITextField){

iflettext=textField.text,!text.isEmpty{

celsiusLabel.text=text

}else{

celsiusLabel.text="???"

}

iflettext=textField.text,letvalue=Double(text){

fahrenheitValue=Measurement(value:value,unit:.fahrenheit)

}else{

fahrenheitValue=nil

}

}

Firstyoucheckwhetherthetextfieldhassometext.Ifso,youchecktoseewhetherthattextcanberepresentedbyaDouble.Forexample,“3.14”canberepresentedbyaDouble,butboth“three”and“1.2.3”cannot.Ifbothofthosecheckspass,thentheFahrenheitvalueissettoaMeasurementinitializedwiththatDoublevalue.Ifeitherofthosechecksfails,thentheFahrenheitvalueissettonil.Buildandruntheapplication.TheconversionbetweenFahrenheitandCelsiusworksgreat–solongasyouenteravalidnumber.(Italsoshowsmoredigitsthanyouprobablywantitto,whichyouwilladdressinamoment.)ItwouldbeniceifthecelsiusLabelwasupdatedwhentheapplicationfirstlaunchedinsteadofstillshowingthevalue“100”.OverrideviewDidLoad()tosettheinitialvalue,similartowhatyoudidinChapter1.overridefuncviewDidLoad(){

super.viewDidLoad()

updateCelsiusLabel()

}

Intheremainderofthischapter,youwillupdateWorldTrottertoaddresstwoissues:YouwillformattheCelsiusvaluetoshowaprecisionuptoonefractionaldigit,andyouwillnotallowtheusertotypeinmorethanonedecimalseparator.Thereareacoupleofotherissueswithyourapp,butyouwillfocusonthesetwofornow.

Page 150: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Oneoftheotherissueswillbepresentedasachallengeattheendofthischapter.Let’sstartwithupdatingtheprecisionoftheCelsiusvalue.

Numberformatters

Youuseanumberformattertocustomizethedisplayofanumber.Thereareotherformattersforformattingdates,energy,mass,length,measurements,andmore.CreateaconstantnumberformatterinConversionViewController.swift.letnumberFormatter:NumberFormatter={

letnf=NumberFormatter()

nf.numberStyle=.decimal

nf.minimumFractionDigits=0

nf.maximumFractionDigits=1

returnnf

}()

Hereyouareusingaclosuretoinstantiatethenumberformatter.YouarecreatingaNumberFormatterwiththe.decimalstyleandconfiguringittodisplaynomorethanonefractionaldigit.YouwilllearnmoreaboutthisnewsyntaxfordeclaringpropertiesinChapter16.NowmodifyupdateCelsiusLabel()tousethisformatter.funcupdateCelsiusLabel(){

ifletcelsiusValue=celsiusValue{

celsiusLabel.text="\(celsiusValue.value)"

celsiusLabel.text=

numberFormatter.string(from:NSNumber(value:celsiusValue.value))

}else{

celsiusLabel.text="???"

}

}

Buildandruntheapplication.PlayaroundwithFahrenheitvaluestoseetheformatteratwork.YoushouldneverseemorethanonefractionaldigitontheCelsiuslabel.Inthenextsection,youwillupdatetheapplicationtoacceptamaximumofonedecimalseparatorinthetextfield.Todothis,youwilluseacommoniOSdesignpatterncalleddelegation.

Page 151: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 152: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Delegation

Delegationisanobject-orientedapproachtocallbacks.Acallbackisafunctionthatissuppliedinadvanceofaneventandiscalledeverytimetheeventoccurs.Someobjectsneedtomakeacallbackformorethanoneevent.Forinstance,thetextfieldneedsto“callback”whentheuserenterstextaswellaswhentheuserpressestheReturnkey.However,thereisnobuilt-inwayfortwo(ormore)callbackfunctionstocoordinateandshareinformation.Thisistheproblemaddressedbydelegation–yousupplyasingledelegatetoreceivealloftheevent-relatedcallbacksforaparticularobject.Thisdelegateobjectcanthenstore,manipulate,acton,andrelaytheinformationfromthecallbacksasitseesfit.Whentheusertypesintoatextfield,thattextfieldwillaskitsdelegateifitwantstoacceptthechangesthattheuserhasmade.ForWorldTrotter,youwanttodenythatchangeiftheuserattemptstoenteraseconddecimalseparator.ThedelegateforthetextfieldwillbetheinstanceofConversionViewController.

Conformingtoaprotocol

ThefirststepisenablinginstancesoftheConversionViewControllerclasstoperformtheroleofUITextFielddelegatebydeclaringthatConversionViewControllerconformstotheUITextFieldDelegateprotocol.Foreverydelegaterole,thereisacorrespondingprotocolthatdeclaresthemethodsthatanobjectcancallonitsdelegate.TheUITextFieldDelegateprotocollookslikethis:protocolUITextFieldDelegate:NSObjectProtocol{

optionalfunctextFieldShouldBeginEditing(_textField:UITextField)->Bool

optionalfunctextFieldDidBeginEditing(_textField:UITextField)

optionalfunctextFieldShouldEndEditing(_textField:UITextField)->Bool

optionalfunctextFieldDidEndEditing(_textField:UITextField)

optionalfunctextField(_textField:UITextField,

shouldChangeCharactersInrange:NSRange,

replacementStringstring:String)->Bool

optionalfunctextFieldShouldClear(_textField:UITextField)->Bool

optionalfunctextFieldShouldReturn(_textField:UITextField)->Bool

}

Thisprotocol,likeallprotocols,isdeclaredwithprotocolfollowedbyitsname,UITextFieldDelegate.TheNSObjectProtocolafterthecolonreferstotheNSObjectprotocolandtellsyouthatUITextFieldDelegateinheritsallofthemethodsintheNSObjectprotocol.ThemethodsspecifictoUITextFieldDelegatearedeclarednext.Youcannotcreateinstancesofaprotocol;itissimplyalistofmethodsandproperties.Instead,implementationislefttoeachtypethatconformstotheprotocol.Inaclass’sdeclaration,theprotocolsthattheclassconformstoareinacomma-delimitedlistfollowingthesuperclass(ifthereisone).InConversionViewController.swift,

Page 153: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

declarethatConversionViewControllerconformstotheUITextFieldDelegateprotocol.classConversionViewController:UIViewController,UITextFieldDelegate{

Protocolsusedfordelegationarecalleddelegateprotocols,andthenamingconventionforadelegateprotocolisthenameofthedelegatingclassplusthewordDelegate.Notallprotocolsaredelegateprotocols,however,andyouwillseeanexampleofadifferentkindofprotocolinChapter16.TheprotocolswehavementionedsofararepartoftheiOSSDK,butyoucanalsowriteyourownprotocols.

Usingadelegate

NowthatyouhavedeclaredConversionViewControllerasconformingtotheUITextFieldDelegateprotocol,youcansetthedelegatepropertyofthetextfield.OpenMain.storyboardandControl-dragfromthetextfieldtotheConversionViewController.ChoosedelegatefromthepopovertoconnectthedelegatepropertyofthetextfieldtotheConversionViewController.Next,youaregoingtoimplementtheUITextFieldDelegatemethodthatyouareinterestedin–textField(_:shouldChangeCharactersIn:replacementString:).Becausethetextfieldcallsthismethodonitsdelegate,youmustimplementitinConversionViewController.swift.InConversionViewController.swift,implementtextField(_:shouldChangeCharactersIn:replacementString:)toprintthetextfield’scurrenttextaswellasthereplacementstring.Fornow,justreturntruefromthismethod.functextField(_textField:UITextField,

shouldChangeCharactersInrange:NSRange,

replacementStringstring:String)->Bool{

print("Currenttext:\(textField.text)")

print("Replacementtext:\(string)")

returntrue

}

NoticethatXcodewasabletoautocompletethismethodbecauseConversionViewControllerconformstoUITextFieldDelegate.ItisagoodideatodeclareaprotocolbeforeimplementingmethodsfromtheprotocolsothatXcodecanofferthissupport.Buildandruntheapplication.EnterseveraldigitsinthetextfieldandwatchXcode’sconsole(Figure4.12).Itprintsoutthecurrenttextofthetextfieldaswellasthereplacementstring.

Page 154: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure4.12Printingtotheconsole

Considerthis“currenttext”and“replacementtext”informationinlightofyourgoalofpreventingmultipledecimalseparators.Logically,iftheexistingstringhasadecimalseparatorandthereplacementstringhasadecimalseparator,thechangeshouldberejected.InConversionViewController.swift,updatetextField(_:shouldChangeCharactersIn:replacementString:)tousethislogic.functextField(_textField:UITextField,

shouldChangeCharactersInrange:NSRange,

replacementStringstring:String)->Bool{

print("Currenttext:\(textField.text)")

print("Replacementtext:\(string)")

returntrue

letexistingTextHasDecimalSeparator=textField.text?.range(of:".")

letreplacementTextHasDecimalSeparator=string.range(of:".")

ifexistingTextHasDecimalSeparator!=nil,

replacementTextHasDecimalSeparator!=nil{

returnfalse

}else{

returntrue

}

}

Buildandruntheapplication.Attempttoentermultipledecimalseparators;theapplicationwillrejecttheseconddecimalseparatorthatyouenter.

Moreonprotocols

Page 155: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

IntheUITextFieldDelegateprotocol,therearetwokindsofmethods:methodsthathandleinformationupdatesandmethodsthathandlerequestsforinput.Forexample,thetextfield’sdelegateimplementsthetextFieldDidBeginEditing(_:)methodifitwantstoknowwhentheusertapsonthetextfield.Ontheotherhand,textField(_:shouldChangeCharactersIn:replacementString:)isarequestforinput.Atextfieldcallsthismethodonitsdelegatetoaskwhetherthereplacementstringshouldbeacceptedorrejected.ThemethodreturnsaBool,whichisthedelegate’sanswer.Methodsdeclaredinaprotocolcanberequiredoroptional.Bydefault,protocolmethodsarerequired,meaningthataclassconformingtotheprotocolmusthaveanimplementationofthosemethods.Ifaprotocolhasoptionalmethods,theseareprecededbythedirectiveoptional.LookingbackattheUITextFieldDelegateprotocol,youcanseethatallofitsmethodsareoptional.Thisistypicallytrueofdelegateprotocols.

Page 156: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 157: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

BronzeChallenge:DisallowAlphabeticCharacters

Currently,theusercanenteralphabeticcharacterseitherbyusingaBluetoothkeyboardorbypastingcopiedtextintothetextfield.Fixthisissue.Hint:YouwillwanttousetheNSCharacterSetclass.

Page 158: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 159: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

BIGNERDRANCHCODINGBOOTCAMPS

BigNerdRanchbootcampscoveralotofgroundinjustdays.Withourretreat-styletraining,we’llsubjectyoutothemostintensiveappdevelopmentcourseyoucanimagine,andwhenyoufinish,you’llbepartofanelitecorps:thefew,theproud,thenerds.Ourdistraction-freetraininggivesyoutheopportunitytomasternewskillsinanintensiveenvironment—nomeetings,nophonecalls,justlearning.

BigNerdRanch’strainingwasunlikeanyotherclassI’vehad.Ilearnedskillsthatmakemeexceptionallymorevaluable,givingmealeguponthecompetition.SincemyfirstBigNerdRanchclass,I’vewrittensoftwareusedinTheWhiteHouse,heldpositionsatAT&TandDisney—andultimatelylandedatApple.—JoshPaul,Alumnus

WeofferclassesiniOS,Android,Front-EndWeb,Back-EndWeb,macOSandDesign.UsecodeBNRGUIDE100for$100offabootcampofyourchoice.

www.bignerdranch.com

Page 160: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 161: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

5ViewControllers

AviewcontrollerisaninstanceofasubclassofUIViewController.Aviewcontrollermanagesaviewhierarchy.Itisresponsibleforcreatingviewobjectsthatmakeupthehierarchyandforhandlingeventsassociatedwiththeviewobjectsinitshierarchy.Sofar,WorldTrotterhasasingleviewcontroller,ConversionViewController.Inthischapter,youwillupdateittousemultipleviewcontrollers.Theuserwillbeabletoswitchbetweentwoviewhierarchies–oneforviewingtheConversionViewControllerandanotherfordisplayingamap(Figure5.1).Figure5.1ThetwofacesofWorldTrotter

Page 162: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

TheViewofaViewController

AssubclassesofUIViewController,allviewcontrollersinheritanimportantproperty:varview:UIView!

ThispropertypointstoaUIViewinstancethatistherootoftheviewcontroller ’sviewhierarchy.Whentheviewofaviewcontrollerisaddedasasubviewofthewindow,theviewcontroller ’sentireviewhierarchyisadded,asshowninFigure5.2.Figure5.2ObjectdiagramforWorldTrotter

Aviewcontroller ’sviewisnotcreateduntilitneedstoappearonthescreen.Thisoptimizationiscalledlazyloading,anditcanconservememoryandimproveperformance.Therearetwowaysthataviewcontrollercancreateitsviewhierarchy:

inInterfaceBuilder,byusinganinterfacefilesuchasastoryboardprogrammatically,byoverridingtheUIViewControllermethodloadView()

YousawthefirstapproachinChapter3.First,youcreatedasampleviewhierarchyprogrammatically,thenyouswitchedtoInterfaceBuildertocreatetheinterfaceforConversionViewControllerusingastoryboardfile.YouwillcontinuetouseInterfaceBuilderinthischapterasyoufurtherexploreviewcontrollers.InChapter6,youwillgetexperiencecreatingprogrammaticviewsusingloadView().

Page 163: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 164: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

SettingtheInitialViewController

Althoughastoryboardcanhavemanyviewcontrollers,eachstoryboardfilehasexactlyoneinitialviewcontroller.Theinitialviewcontrolleractsasanentrypointintothestoryboard.Youaregoingtoaddandconfigureanotherviewcontrollertothecanvasandsetittobetheinitialviewcontrollerforthestoryboard.OpenMain.storyboard.Fromtheobjectlibrary,dragaViewControllerontothecanvas(Figure5.3).(Tomakespaceonthecanvas,youcanzoomoutbyControl-clickingonthebackground,usingthezoomcontrolsatthebottomofthecanvas,orusingpinchgesturesonyourtrackpad.)Figure5.3Addingaviewcontrollertothecanvas

YouwantthisviewcontrollertodisplayanMKMapView–aclassdesignedtodisplayamap–insteadoftheexistingwhiteUIView.SelecttheviewoftheViewController–nottheViewControlleritself!–andpressDeletetoremovethisviewfromthecanvas.ThendragaMapKitViewfromtheobjectlibraryontotheviewcontrollertosetitastheviewforthisviewcontroller(Figure5.4).

Page 165: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure5.4Addingamapviewtothecanvas

NowselecttheViewControllerandopenitsattributesinspector.UndertheViewControllersection,checktheboxnexttoIsInitialViewController(Figure5.5).DidyounoticethatthegrayarrowonthecanvasthatwaspointingattheConversionViewControllerisnowpointingtotheViewController?Thearrow,asyouhaveprobablysurmised,indicatestheinitialviewcontroller.Anotherwaytoassigntheinitialviewcontrolleristodragthatarrowfromoneviewcontrollertoanotheronthecanvas.

Page 166: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure5.5Settingtheinitialviewcontroller

Thereisaquirkthatwouldcauseproblemsifyouweretobuildandruntheapprightnow.(Tryit,ifyoulike.)MKMapViewisinaframeworkthatisnotcurrentlybeingloadedintotheapplication.Aframeworkisasharedlibraryofcodethatincludesassociatedresourcessuchasinterfacefilesandimages.YoubrieflylearnedaboutframeworksinChapter3,andyouhavebeenusingacoupleofframeworksalready:UIKitandFoundationarebothframeworks.Sofar,youhavebeenincludingframeworksinyourappbyusingtheimportkeyword,likeso:importUIKit

NowyouneedtoimporttheMapKitframeworksothattheMKMapViewwillload.However,ifyouimporttheMapKitframeworkusingtheimportkeywordwithoutincludinganycodethatusesthatframework,thecompilerwilloptimizeitout–eventhoughyouareusingamapviewinyourstoryboard.Instead,youneedtomanuallylinktheMapKitframeworktotheapp.Withtheprojectnavigatoropen,clickontheWorldTrotterprojectatthetopofthelisttoopentheprojectsettings.FindandopentheGeneraltabinthesettings.ScrolldowntothebottomandfindthesectionlabeledLinkedFrameworksandLibraries.Clickonthe+atthebottomandsearchforMapKit.framework.SelectthisframeworkandclickAdd(Figure5.6).

Page 167: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure5.6AddingtheMapKitframework

Nowyoucanbuildandruntheapplication.Becauseyouhavechangedtheinitialviewcontroller,themapshowsupinsteadoftheviewoftheConversionViewController.Asmentionedabove,therecanonlybeoneinitialviewcontrollerassociatedwithagivenstoryboard.YousawthisearlierwhenyousettheViewControllertobetheinitialviewcontroller.Atthatpoint,theConversionViewControllerwasnolongertheinitialviewcontrollerforthisstoryboard.Let’stakealookathowthisrequirementworkswiththerootlevelUIWindowtoaddtheinitialviewcontroller ’sviewtothewindowhierarchy.UIWindowhasarootViewControllerproperty.Whenaviewcontrollerissetasthewindow’srootViewController,thatviewcontroller ’sviewgetsaddedtothewindow’sviewhierarchy.Whenthispropertyisset,anyexistingsubviewsonthewindowareremovedandviewcontroller ’sviewgetsaddedtothewindowwiththeappropriateAutoLayoutconstraints.Eachapplicationhasonemaininterface,areferencetoastoryboard.Whentheapplicationlaunches,theinitialviewcontrollerforthemaininterfacegetssetastherootViewControllerofthewindow.Themaininterfaceforanapplicationissetintheprojectsettings.StillintheGeneraltaboftheprojectsettings,findtheDeploymentInfosection.HereyouwillseetheMainInterfacesetting(Figure5.7).ThisissettoMain,whichcorrespondstoMain.storyboard.

Page 168: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure5.7Anapplication’smaininterface

Page 169: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 170: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

UITabBarController

Viewcontrollersbecomemoreinterestingwhentheuserhasawaytoswitchbetweenthem.Throughoutthisbook,youwilllearnanumberofwaystopresentviewcontrollers.Inthischapter,youwillcreateaUITabBarControllerthatwillallowtheusertoswapbetweentheConversionViewControllerandtheUIViewControllerdisplayingthemap.UITabBarControllerkeepsanarrayofviewcontrollers.Italsomaintainsatabbaratthebottomofthescreenwithatabforeachviewcontrollerinitsarray.Tappingonatabresultsinthepresentationoftheviewoftheviewcontrollerassociatedwiththattab.OpenMain.storyboardandselecttheViewController.FromtheEditormenu,chooseEmbedIn→TabBarController.ThiswilladdtheViewControllertotheviewcontrollersarrayoftheTabBarController.YoucanseethisrepresentedbytheRelationshiparrowpointingfromtheTabBarControllertotheViewController(Figure5.8).Additionally,InterfaceBuilderknowstomaketheTabBarControllertheinitialviewcontrollerforthestoryboard.Figure5.8Tabbarcontrollerwithoneviewcontroller

Atabbarcontrollerisnotveryusefulwithjustoneviewcontroller.AddtheConversionViewControllertotheTabBarController’sviewcontrollersarray.Control-dragfromtheTabBarControllertotheConversionViewController.FromtheRelationshipSeguesection,chooseviewcontrollers(Figure5.9).

Page 171: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure5.9Addingaviewcontrollertothetabbarcontroller

Buildandruntheapplication.Taponthetwotabsatthebottomtoswitchbetweenthetwoviewcontrollers.Atthemoment,thetabsjustsayItem,whichisnotveryhelpful.Inthenextsection,youwillupdatethetabbaritemstomakethetabsmoredescriptiveandobvious.UITabBarControllerisitselfasubclassofUIViewController.AUITabBarController’sviewisaUIViewwithtwosubviews:thetabbarandtheviewoftheselectedviewcontroller(Figure5.10).Figure5.10UITabBarControllerdiagram

Page 172: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Tabbaritems

Eachtabonthetabbarcandisplayatitleandanimage,andeachviewcontrollermaintainsatabBarItempropertyforthispurpose.WhenaviewcontrolleriscontainedbyaUITabBarController,itstabbaritemappearsinthetabbar.Figure5.11showsanexampleofthisrelationshipiniPhone’sPhoneapplication.

Page 173: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure5.11UITabBarItemexample

First,youneedtoaddafewfilestoyourprojectthatwillbetheimagesforthetabbaritems.Intheprojectnavigator,opentheAssetCatalogbyopeningAssets.xcassets.Anassetisasetoffilesfromwhichasinglefilewillbeselectedatruntimebasedontheuser ’sdeviceconfiguration(moreonthatattheendofthischapter).YouaregoingtoaddaConvertIconassetandaMapIconasset,eachwithimagesatthreedifferentresolutions.Inthe0-Resourcesdirectoryofthefilethatyoudownloadedearlier(www.bignerdranch.com/solutions/iOSProgramming6ed.zip),findConvertIcon.png,[email protected],[email protected],MapIcon.png,[email protected],andMapIcon@3x.png.DragthesefilesintotheimagessetlistontheleftsideoftheAssetCatalog(Figure5.12).

Page 174: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure5.12AddingimagestotheAssetCatalog

Thetabbaritempropertiescanbeseteitherprogrammaticallyorinastoryboard.Becauseyourdataisstatic,thestoryboardwillbethebestplacetosetthetabbaritemproperties.InMain.storyboard,locatetheViewController(itisnowlabeledItem).Noticethatatabbarwiththetabbariteminitwasaddedtotheinterfacebecausetheviewcontrollerwillbepresentedwithinatabbarcontroller.Thisisveryusefulwhenlayingoutyourinterface.Selectthistabbaritemandopenitsattributesinspector.UndertheBarItemsection,changetheTitleto“Map”andchooseMapIconfromtheImagemenu.Youcanalsochangethetextofthetabbaritembydouble-clickingonthetextonthecanvas.Thetabbarwillbeupdatedtoreflectthesevalues(Figure5.13).Figure5.13ViewController’stabbaritem

NowfindtheConversionViewControllerandselectitstabbaritem.SettheTitletobe“Convert”andtheImagetobeConvertIcon.Let’salsochangethefirsttabtobetheConvertViewController.Theorderofthetabsisdeterminedbytheorderoftheviewcontrollerswithinthetabbarcontroller ’sviewControllersarray.YoucanchangetheorderinastoryboardbydraggingthetabsatthebottomoftheTabBarController.FindtheTabBarControlleronthecanvas.DragtheConverttabtobeinthefirstposition.Buildandruntheapplication.Notonlyarethetabbaritemsatthebottommoredescriptive,

Page 175: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

buttheConvertViewControllerisnowthefirstviewcontrollerthatisdisplayed(Figure5.14).Figure5.14Tabbaritemswithlabelsandicons

Page 176: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 177: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

LoadedandAppearingViews

Nowthatyouhavetwoviewcontrollers,thelazyloadingofviewsmentionedearlierbecomesmoreimportant.Whentheapplicationlaunches,thetabbarcontrollerdefaultstoloadingtheviewofthefirstviewcontrollerinitsarray,whichistheConvertViewController.TheMapViewController’sviewisnotneededandwillonlybeneededwhen(orif)theusertapsthetabtoseeit.Youcantestthisbehaviorforyourself.Whenaviewcontrollerfinishesloadingitsview,viewDidLoad()iscalled,andyoucanoverridethismethodtomakeitprintamessagetotheconsole,allowingyoutoseethatitwascalled.Youaregoingtoaddcodetobothviewcontrollers.However,thereisnocodecurrentlyassociatedwiththeviewcontrollerdisplayingthemapbecauseeverythinghasbeenconfiguredusingthestoryboard.Nowthatyouwanttoaddcodetothatviewcontroller,youaregoingtocreateaviewcontrollersubclassandassociateitwiththatinterface.CreateanewSwiftfile(Command-N)andnameitMapViewController.OpenMapViewController.swiftanddefineaUIViewControllersubclassnamedMapViewController.importFoundation

importUIKit

classMapViewController:UIViewController{

}

NowopenMain.storyboardandselectthemap’sviewcontroller.OpenitsidentityinspectorandchangetheClasstoMapViewController.NowthatyouhaveassociatedtheMapViewControllerclasswiththeviewcontrolleronthecanvas,youcanaddcodetobothConversionViewControllerandMapViewControllertoprinttotheconsolewhentheirviewDidLoad()methodiscalled.InConversionViewController.swift,updateviewDidLoad()toprintastatementtotheconsole.overridefuncviewDidLoad(){

super.viewDidLoad()

print("ConversionViewControllerloadeditsview.")

updateCelsiusLabel()

}

InMapViewController.swift,overridethesamemethod.overridefuncviewDidLoad(){

super.viewDidLoad()

print("MapViewControllerloadeditsview.")

}

Page 178: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Buildandruntheapplication.TheconsolereportsthatConversionViewControllerloadeditsviewrightaway.TapMapViewController’stab,andtheconsolewillreportthatitsviewisnowloaded.Atthispoint,bothviewshavebeenloaded,soswitchingbetweenthetabsnowwillnolongertriggerviewDidLoad().(Tryitandsee.)

Accessingsubviews

Often,youwillwanttodosomeextrainitializationorconfigurationofsubviewsdefinedinInterfaceBuilderbeforetheyappeartotheuser.Sowherecanyouaccessasubview?Therearetwomainoptions,dependingonwhatyouneedtodo.ThefirstoptionistheviewDidLoad()methodthatyouoverrodetospotlazyloading.Thismethodiscalledaftertheviewcontroller ’sinterfacefileisloaded,atwhichpointalloftheviewcontroller ’soutletswillreferencetheappropriateobjects.ThesecondoptionisanotherUIViewControllermethod,viewWillAppear(_:).Thismethodiscalledjustbeforeaviewcontroller ’sviewisaddedtothewindow.Whichshouldyouchoose?OverrideviewDidLoad()iftheconfigurationonlyneedstobedoneonceduringtherunoftheapp.OverrideviewWillAppear(_:)ifyouneedtheconfigurationtobedoneeachtimetheviewcontroller ’sviewappearsonscreen.

Page 179: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 180: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

InteractingwithViewControllersandTheirViews

Let’slookatsomemethodsthatarecalledduringthelifecycleofaviewcontrolleranditsview.Someofthesemethodsyouhavealreadyseen,andsomearenew.

init(coder:)istheinitializerforUIViewControllerinstancescreatedfromastoryboard.Whenaviewcontrollerinstanceiscreatedfromastoryboard,itsinit(coder:)getscalledonce.YouwilllearnmoreaboutthismethodinChapter16.init(nibName:bundle:)isthedesignatedinitializerforUIViewController.Whenaviewcontrollerinstanceiscreatedwithouttheuseofastoryboard,itsinit(nibName:bundle:)getscalledonce.Notethatinsomeapps,youmayendupcreatingseveralinstancesofthesameviewcontrollerclass.Thismethodwillgetcalledonceoneachviewcontrollerasitiscreated.loadView()isoverriddentocreateaviewcontroller ’sviewprogrammatically.viewDidLoad()isoverriddentoconfigureviewscreatedbyloadinganinterfacefile.Thismethodgetscalledaftertheviewofaviewcontrolleriscreated.viewWillAppear(_:)isoverriddentoconfigureviewscreatedbyloadinganinterfacefile.ThismethodandviewDidAppear(_:)getcalledeverytimeyourviewcontrollerismovedonscreen.viewWillDisappear(_:)andviewDidDisappear(_:)getcalledeverytimeyourviewcontrollerismovedoffscreen.

Page 181: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 182: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

SilverChallenge:DarkMode

WhenevertheConversionViewControllerisviewed,updateitsbackgroundcolorbasedonthetimeofday.Intheevening,thebackgroundshouldbeadarkcolor.Otherwise,thebackgroundshouldbealightcolor.YouwillneedtooverrideviewWillAppear(_:)toaccomplishthis.(Ifthatisnotenoughexcitementinyourlife,youcanchangethebackgroundcoloreachtimetheviewcontrollerisviewed.)

Page 183: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 184: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

FortheMoreCurious:RetinaDisplay

WiththereleaseofiPhone4,AppleintroducedtheRetinadisplayforiPhoneandiPodtouch.TheRetinadisplayhasmuchhigherresolutioncomparedtoearlierdevices.Let’slookatwhatyoushoulddotomakegraphicslooktheirbestonbothdisplays.Forvectorgraphics,youdonotneedtodoanything;yourcodewillrenderascrisplyasthedeviceallows.However,ifyoudrawusingCoreGraphicsfunctions,thesegraphicswillappeardifferentlyondifferentdevices.InCoreGraphics(alsocalledQuartz),lines,curves,text,etc.aredescribedintermsofpoints.Onanon-Retinadisplay,apointis1x1pixel.OnmostRetinadisplays,apointis2x2pixels(Figure5.15).Theexceptionsarethe5.5-inchiPhones,whichhaveahigher-resolutionRetinadisplaywhereapointis3x3pixels.Figure5.15Renderingtodifferentresolutions

Giventhesedifferences,bitmapimages(likeJPEGorPNGfiles)willbeunattractiveiftheimageisnottailoredtothedevice’sscreentype.Sayyourapplicationincludesasmallimageof25x25pixels.Ifthisimageisdisplayedona2xRetinadisplay,thentheimagemustbestretchedtocoveranareaof50x50pixels.Atthispoint,thesystemdoesatypeofaveragingcalledanti-aliasingtokeeptheimagefromlookingjagged.Theresultisanimagethatisnotjagged–butitisfuzzy(Figure5.16).Figure5.16Fuzzinessfromstretchinganimage

Page 185: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Youcouldusealargerfileinstead,buttheaveragingwouldthencauseproblemsintheotherdirectionwhentheimageisshrunkforanon-Retinadisplay.Theonlysolutionistobundletwoimagefileswithyourapplication:oneatapixelresolutionequaltothenumberofpointsonthescreenfornon-RetinadisplaysandonetwicethatsizeinpixelsforRetinadisplays.Fortunately,youdonothavetowriteanyextracodetohandlewhichimagegetsloadedonwhichdevice.AllyouhavetodoisassociatethedifferentresolutionimagesintheAssetCatalogwithasingleasset.Then,whenyouuseUIImage’sinit(named:)initializertoloadtheimage,thismethodlooksinthebundleandgetstheappropriatefilefortheparticulardevice.

Page 186: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 187: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

6ProgrammaticViews

Inthischapter,youwillupdateWorldTrottertocreatetheviewforMapViewControllerprogrammatically(Figure6.1).Indoingso,youwilllearnmoreaboutviewcontrollersandhowtosetupconstraintsandcontrols(suchasUIButtons)programmatically.Figure6.1WorldTrotterwithprogrammaticviews

Currently,theviewforMapViewControllerisdefinedinthestoryboard.Thefirststep,then,istoremovethisviewfromthestoryboardsoyoucaninsteadcreateitprogrammatically.InMain.storyboard,selectthemapviewassociatedwithMapViewControllerandpressDelete(Figure6.2).

Page 188: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure6.2Deletingtheview

Page 189: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

CreatingaViewProgrammatically

YoulearnedinChapter5thatyoucreateaviewcontroller ’sviewprogrammaticallybyoverridingtheUIViewControllermethodloadView().OpenMapViewController.swiftandoverrideloadView()tocreateaninstanceofMKMapViewandsetitastheviewoftheviewcontroller.Youwillneedareferencetothemapviewlateron,socreateapropertyforitaswell.importUIKit

importMapKit

classMapViewController:UIViewController{

varmapView:MKMapView!

overridefuncloadView(){

//Createamapview

mapView=MKMapView()

//Setitas*the*viewofthisviewcontroller

view=mapView

}

overridefuncviewDidLoad(){

super.viewDidLoad()

print("MapViewControllerloadeditsview.")

}

}

Whenaviewcontrolleriscreated,itsviewpropertyisnil.Ifaviewcontrollerisaskedforitsviewanditsviewisnil,thentheloadView()methodiscalled.Buildandruntheapplication.Althoughtheapplicationlooksthesame,themapviewisbeingcreatedprogrammaticallyinsteadofthroughInterfaceBuilder.

Page 190: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 191: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

ProgrammaticConstraints

InChapter3,youlearnedaboutAutoLayoutconstraintsandhowtoaddthemusingInterfaceBuilder.Inthissection,youwilllearnhowtoaddconstraintstoaninterfaceprogrammatically.ApplerecommendsthatyoucreateandconstrainyourviewsinInterfaceBuilderwheneverpossible.However,ifyourviewsarecreatedincode,thenyouwillneedtoconstrainthemprogrammatically.TheinterfaceforMapViewControlleriscreatedprogrammatically,soitisagreatcandidateforprogrammaticconstraints.Tolearnaboutprogrammaticconstraints,youaregoingtoaddaUISegmentedControltoMapViewController’sinterface.Asegmentedcontrolallowstheusertochoosebetweenadiscretesetofoptions,andyouwilluseonetoallowtheusertoswitchbetweenmaptypes:standard,hybrid,andsatellite.InMapViewController.swift,updateloadView()toaddasegmentedcontroltotheinterface.overridefuncloadView(){

//Createamapview

mapView=MKMapView()

//Setitas*the*viewofthisviewcontroller

view=mapView

letsegmentedControl

=UISegmentedControl(items:["Standard","Hybrid","Satellite"])

segmentedControl.backgroundColor

=UIColor.white.withAlphaComponent(0.5)

segmentedControl.selectedSegmentIndex=0

segmentedControl.translatesAutoresizingMaskIntoConstraints=false

view.addSubview(segmentedControl)

}

(Notethatduetopagesizerestrictionsweareshowingsomeofthesedeclarationssplitacrosstwolines.Youshouldentereachdeclarationonasingleline.)Thelineofcoderegardingtranslatingconstraintshastodowithanoldersystemforscalinginterfaces–autoresizingmasks.BeforeAutoLayoutwasintroduced,iOSapplicationsusedautoresizingmaskstoallowviewstoscalefordifferent-sizedscreensatruntime.Everyviewhasanautoresizingmask.Bydefault,iOScreatesconstraintsthatmatchtheautoresizingmaskandaddsthemtotheview.Thesetranslatedconstraintswilloftenconflictwithexplicitconstraintsinthelayoutandcauseanunsatisfiableconstraintsproblem.ThefixistoturnoffthisdefaulttranslationbysettingthepropertytranslatesAutoresizingMaskIntoConstraintstofalse.(ThereismoreaboutAutoLayoutandautoresizingmasksattheendofthischapter.)

Anchors

Page 192: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

WhenyouworkwithAutoLayoutprogrammatically,youwilluseanchorstocreateyourconstraints.Anchorsarepropertiesontheviewthatcorrespondtoattributesthatyoumightwanttoconstraintoananchoronanotherview.Forexample,youmightconstraintheleadinganchorofoneviewtotheleadinganchorofanotherview.Thiswouldhavetheeffectofthetwoviews’leadingedgesbeingaligned.Let’screatesomeconstraintstodothefollowing.

Thetopanchorofthesegmentedcontrolshouldbeequaltothetopanchorofitssuperview.Theleadinganchorofthesegmentedcontrolshouldbeequaltotheleadinganchorofitssuperview.Thetrailinganchorofthesegmentedcontrolshouldbeequaltothetrailinganchorofitssuperview.

InMapViewController.swift,createtheseconstraintsinloadView().letsegmentedControl

=UISegmentedControl(items:["Standard","Hybrid","Satellite"])

segmentedControl.backgroundColor

=UIColor.white.withAlphaComponent(0.5)

segmentedControl.selectedSegmentIndex=0

segmentedControl.translatesAutoresizingMaskIntoConstraints=false

view.addSubview(segmentedControl)

lettopConstraint

=segmentedControl.topAnchor.constraint(equalTo:view.topAnchor)

letleadingConstraint

=segmentedControl.leadingAnchor.constraint(equalTo:view.leadingAnchor)

lettrailingConstraint

=segmentedControl.trailingAnchor.constraint(equalTo:view.trailingAnchor)

Xcodewillalertyoutoaproblemwitheachlineyouhaveentered.Youwillfixtheminamoment.Anchorshaveamethodconstraint(equalTo:)thatwillcreateaconstraintbetweenthetwoanchors.ThereareafewotherconstraintcreationmethodsonNSLayoutAnchor,includingonethatacceptsaconstantasanargument:funcconstraint(equalToanchor:NSLayoutAnchor<AnchorType>,

constantc:CGFloat)->NSLayoutConstraint

Activatingconstraints

YounowhavethreeNSLayoutConstraintinstances.However,theseconstraintswillhavenoeffectonthelayoutuntilyouexplicitlyactivatethembysettingtheirisActivepropertiestotrue.ThiswillresolveXcode’scomplaint.InMapViewController.swift,activatetheconstraintsattheendofloadView().lettopConstraint=

segmentedControl.topAnchor.constraint(equalTo:view.topAnchor)

Page 193: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

letleadingConstraint=

segmentedControl.leadingAnchor.constraint(equalTo:view.leadingAnchor)

lettrailingConstraint=

segmentedControl.trailingAnchor.constraint(equalTo:view.trailingAnchor)

topConstraint.isActive=true

leadingConstraint.isActive=true

trailingConstraint.isActive=true

Constraintsneedtobeaddedtothemostrecentcommonancestorfortheviewsassociatedwiththeconstraint.Figure6.3showsaviewhierarchyalongwiththecommonancestorfortwoviews.Figure6.3Commonancestor

Ifaconstraintisrelatedtojustoneview(suchaswhenaddingawidthorheightconstrainttoaview),thenthatviewisconsideredthecommonancestor.Bysettingtheactivepropertyonaconstrainttotrue,theconstraintwillworkitswayupthehierarchyfortheitemstofindthecommonancestortoaddtheconstraintto.ItwillthencallthemethodaddConstraint(_:)ontheappropriateview.SettingtheactivepropertyispreferabletocallingaddConstraint(_:)orremoveConstraint(_:)yourself.BuildandruntheapplicationandswitchtotheMapViewController.Thesegmentedcontrolisnowpinnedtothetop,leading,andtrailingedgesofitssuperview(Figure6.4).

Page 194: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure6.4Segmentedcontroladdedtothescreen

Althoughtheconstraintsaredoingtherightthing,theinterfacedoesnotlookgood.Thesegmentedcontrolisunderlappingthestatusbar,anditwouldlookbetterifthesegmentedcontrolwasinsetfromtheleadingandtrailingedgesofthescreen.Let’stacklethestatusbarissuefirst.

Layoutguides

Viewcontrollersexposetwolayoutguidestoassistwithlayoutcontent:thetopLayoutGuideandthebottomLayoutGuide.Thelayoutguidesindicatetheextenttowhichtheviewcontroller ’sviewcontentswillbevisible.UsingtopLayoutGuidewillallowyourcontenttonotunderlapthestatusbarornavigationbaratthetopofthescreen.(YouwilllearnaboutnavigationbarsinChapter14.)UsingthebottomLayoutGuidewillallowyourcontenttonotunderlapthetabbaratthebottomofthescreen.Thelayoutguidesexposethreeanchorsthatyoucanusetoaddconstraints:topAnchor,bottomAnchor,andheightAnchor.Becauseyouwantthesegmentedcontroltobeunderthestatusbar,youwillconstrainthebottomanchorofthetoplayoutguidetothetopanchorofthesegmentedcontrol.InMapViewController.swift,updatethesegmentedcontrol’sconstraintsinloadView().Makethesegmentedcontrolbe8pointsbelowthetoplayoutguide.lettopConstraint=

segmentedControl.topAnchor.constraint(equalTo:view.topAnchor)

lettopConstraint=

segmentedControl.topAnchor.constraint(equalTo:topLayoutGuide.bottomAnchor,

constant:8)

letleadingConstraint=

segmentedControl.leadingAnchor.constraint(equalTo:view.leadingAnchor)

lettrailingConstraint=

segmentedControl.trailingAnchor.constraint(equalTo:view.trailingAnchor)

topConstraint.isActive=true

leadingConstraint.isActive=true

trailingConstraint.isActive=true

Buildandruntheapplication.Thesegmentedcontrolnowappearsbelowthestatusbar.Byusingthelayoutguidesinsteadofahardcodedconstant,theviewswilladaptbasedonthecontexttheyappearin.

Page 195: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Nowlet’supdatethesegmentedcontrolsothatitisinsetfromtheleadingandtrailingedgesofitssuperview.

Margins

Althoughyoucouldinsetthesegmentedcontrolusingaconstantontheconstraint,itismuchbettertousethemarginsoftheviewcontroller ’sview.EveryviewhasalayoutMarginspropertythatdenotesthedefaultspacingtousewhenlayingoutcontent.ThispropertyisaninstanceofUIEdgeInsets,whichyoucanthinkofasatypeofframe.Whenaddingconstraints,youwillusethelayoutMarginsGuide,whichexposesanchorsthataretiedtotheedgesofthelayoutMargins.Theprimaryadvantageofusingthemarginsisthatthemarginscanchangedependingonthedevicetype(iPadoriPhone)aswellasthesizeofthedevice.Usingthemarginswillgiveyoucontentthatlooksgoodonanydevice.Updatethesegmentedcontrol’sleadingandtrailingconstraintsinloadView()tousethemargins.lettopConstraint=

segmentedControl.topAnchor.constraint(equalTo:topLayoutGuide.bottomAnchor,

constant:8)

letleadingConstraint=

segmentedControl.leadingAnchor.constraint(equalTo:view.leadingAnchor)

lettrailingConstraint=

segmentedControl.trailingAnchor.constraint(equalTo:view.trailingAnchor)

letmargins=view.layoutMarginsGuide

letleadingConstraint=

segmentedControl.leadingAnchor.constraint(equalTo:margins.leadingAnchor)

lettrailingConstraint=

segmentedControl.trailingAnchor.constraint(equalTo:margins.trailingAnchor)

topConstraint.isActive=true

leadingConstraint.isActive=true

trailingConstraint.isActive=true

Buildandruntheapplicationagain.Thesegmentedcontrolisnowinsetfromtheview’smargins(Figure6.5).Figure6.5Segmentedcontrolwithupdatedconstraints

Page 196: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Explicitconstraints

Itishelpfultounderstandhowthesemethodsthatyouhaveusedcreateconstraints.NSLayoutConstrainthasthefollowinginitializer:convenienceinit(itemview1:Any,

attributeattr1:NSLayoutAttribute,

relatedByrelation:NSLayoutRelation,

toItemview2:Any?,

attributeattr2:NSLayoutAttribute,

multiplier:CGFloat,

constantc:CGFloat)

Thisinitializercreatesasingleconstraintusingtwolayoutattributesoftwoviewobjects.Themultiplieristhekeytocreatingaconstraintbasedonaratio.Theconstantisafixednumberofpoints,similartowhatyouusedinyourspacingconstraints.ThelayoutattributesaredefinedasconstantsintheNSLayoutConstraintclass:

NSLayoutAttribute.left

NSLayoutAttribute.right

NSLayoutAttribute.leading

NSLayoutAttribute.trailing

NSLayoutAttribute.top

NSLayoutAttribute.bottom

NSLayoutAttribute.width

NSLayoutAttribute.height

NSLayoutAttribute.centerX

NSLayoutAttribute.centerY

NSLayoutAttribute.firstBaseline

NSLayoutAttribute.lastBaseline

Thereareadditionalattributesthathandlethemarginsassociatedwithaview,suchasNSLayoutAttribute.leadingMargin.Let’sconsiderahypotheticalconstraint.Sayyouwantedthewidthoftheimageviewtobe1.5timesitsheight.Youcouldmakethathappenwiththefollowingcode.(Donottypethishypotheticalconstraintinyourcode!Itwillconflictwithothersyoualreadyhave.)letaspectConstraint=NSLayoutConstraint(item:imageView,

attribute:.width,

relatedBy:.equal,

toItem:imageView,

attribute:.height,

multiplier:1.5,

constant:0.0)

Page 197: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Tounderstandhowthisinitializerworks,thinkofthisconstraintastheequationshowninFigure6.6.Figure6.6NSLayoutConstraintequation

Yourelatealayoutattributeofoneviewtothelayoutattributeofanotherviewusingamultiplierandaconstanttodefineasingleconstraint.

Page 198: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 199: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

ProgrammaticControls

Nowlet’supdatethesegmentedcontroltochangethemaptypewhentheusertapsonasegment.AUISegmentedControlisasubclassofUIControl.YouworkedwithanotherUIControlsubclassinChapter1,theUIButtonclass.Controlsareresponsibleforcallingmethodsontheirtargetinresponsetosomeevent.ControleventsareoftypeUIControlEvents.Hereareafewofthecommoncontroleventsthatyouwilluse:UIControlEvents.touchDown

Atouchdownonthecontrol.UIControlEvents.touchUpInside

Atouchdownfollowedbyatouchupwhilestillwithintheboundsofthecontrol.UIControlEvents.valueChanged

Atouchthatcausesthevalueofthecontroltochange.UIControlEvents.editingChanged

AtouchthatcausesaneditingchangeforaUITextField.Youused.touchUpInsidefortheUIButtoninChapter1(itisthedefaulteventwhenyouControl-dragtoconnectactionsinInterfaceBuilder),andyousawthe.editingChangedeventinChapter4.Forthesegmentedcontrol,youwillusethe.valueChangedevent.InMapViewController.swift,updateloadView()toaddatarget-actionpairtothesegmentedcontrolandassociateitwiththe.valueChangedevent.overridefuncloadView(){

//Createamapview

mapView=MKMapView()

//Setitas*the*viewofthisviewcontroller

view=mapView

letsegmentedControl

=UISegmentedControl(items:["Standard","Satellite","Hybrid"])

segmentedControl.backgroundColor

=UIColor.white.withAlphaComponent(0.5)

segmentedControl.selectedSegmentIndex=0

segmentedControl.addTarget(self,

action:#selector(MapViewController.mapTypeChanged(_:)),

for:.valueChanged)

...

Next,implementtheactionmethodinMapViewControllerthattheeventwilltrigger.Thismethodwillcheckwhichsegmentwasselectedandupdatethemapaccordingly.funcmapTypeChanged(_segControl:UISegmentedControl){

switchsegControl.selectedSegmentIndex{

Page 200: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

case0:

mapView.mapType=.standard

case1:

mapView.mapType=.hybrid

case2:

mapView.mapType=.satellite

default:

break

}

}

Buildandruntheapplication.Changetheselectedsegmentandthemapwillupdate.

Page 201: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 202: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

BronzeChallenge:AnotherTab

Createanewviewcontrollerandaddittothetabbarcontroller.ThisviewcontrollershoulddisplayaWKWebView,whichisaclassusedtodisplaywebcontent.Thewebviewshoulddisplaywww.bignerdranch.comforyoutobookyournextvacation.

Page 203: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 204: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

SilverChallenge:User’sLocation

AddabuttontotheMapViewControllerthatdisplaysandzoomsinontheuser ’scurrentlocation.Youwillneedtousedelegationtoaccomplishthis.RefertothedocumentationforMKMapViewDelegate.

Page 205: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 206: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

GoldChallenge:DroppingPins

Mapviewscandisplaypins,whichareinstancesofMKPinAnnotationView.Addthreepinstothemapview:onewhereyouwereborn,onewhereyouarenow,andoneataninterestinglocationyouhavevisitedinthepast.Addabuttontotheinterfacethatallowsthemaptodisplaythelocationofapin.Subsequenttapsshouldsimplycyclethroughthelistofpins.

Page 207: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 208: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

FortheMoreCurious:NSAutoresizingMaskLayoutConstraint

Aswementionedearlier,beforeAutoLayoutiOSapplicationsusedanothersystemformanaginglayout:autoresizingmasks.Eachviewhadanautoresizingmaskthatconstraineditsrelationshipwithitssuperview,butthismaskcouldnotaffectrelationshipsbetweensiblingviews.Bydefault,viewscreateandaddconstraintsbasedontheirautoresizingmasks.However,thesetranslatedconstraintsoftenconflictwiththeexplicitconstraintsinyourlayout,whichresultsinanunsatisfiableconstraintsproblem.Toseethishappen,commentoutthelineinloadView()thatturnsoffthetranslationofautoresizingmasks.//segmentedControl.translatesAutoresizingMaskIntoConstraints=false

view.addSubview(segmentedControl)

Nowthesegmentedcontrolhasaresizingmaskthatwillbetranslatedintoaconstraint.Buildandruntheapplicationandnavigatetothemapinterface.Youwillnotlikewhatyousee.Theconsolewillreporttheproblemanditssolution.Unabletosimultaneouslysatisfyconstraints.

Probablyatleastoneoftheconstraintsinthefollowinglistisoneyoudon't

want.Trythis:(1)lookateachconstraintandtrytofigureoutwhichyoudon't

expect;(2)findthecodethataddedtheunwantedconstraintorconstraintsand

fixit.(Note:Ifyou'reseeingNSAutoresizingMaskLayoutConstraintsthatyoudon't

understand,refertothedocumentationfortheUIViewproperty

translatesAutoresizingMaskIntoConstraints)

(

"<NSAutoresizingMaskLayoutConstraint:0x7fb6b8e0ad00

h=--&v=--&H:[UISegmentedControl:0x7fb6b9897390(212)]>",

"<NSLayoutConstraint:0x7fb6b9975350UISegmentedControl:0x7fb6b9897390.leading

==UILayoutGuide:0x7fb6b9972640'UIViewLayoutMarginsGuide'.leading>",

"<NSLayoutConstraint:0x7fb6b9975460UISegmentedControl:0x7fb6b9897390.trailing

==UILayoutGuide:0x7fb6b9972640'UIViewLayoutMarginsGuide'.trailing>",

"<NSLayoutConstraint:0x7fb6b8e0b370'UIView-Encapsulated-Layout-Width'

H:[MKMapView:0x7fb6b8d237c0(0)]>",

"<NSLayoutConstraint:0x7fb6b9972020'UIView-leftMargin-guide-constraint'

H:|-(0)-[UILayoutGuide:0x7fb6b9972640'UIViewLayoutMarginsGuide'](LTR)

(Names:'|':MKMapView:0x7fb6b8d237c0)>",

"<NSLayoutConstraint:0x7fb6b9974f50'UIView-rightMargin-guide-constraint'

H:[UILayoutGuide:0x7fb6b9972640'UIViewLayoutMarginsGuide']-(0)-|(LTR)

(Names:'|':MKMapView:0x7fb6b8d237c0)>"

)

Willattempttorecoverbybreakingconstraint

<NSLayoutConstraint:0x7fb6b9975460UISegmentedControl:0x7fb6b9897390.trailing

==UILayoutGuide:0x7fb6b9972640'UIViewLayoutMarginsGuide'.trailing>

MakeasymbolicbreakpointatUIViewAlertForUnsatisfiableConstraintstocatch

thisinthedebugger.

ThemethodsintheUIConstraintBasedLayoutDebuggingcategoryonUIViewlisted

in<UIKit/UIView.h>mayalsobehelpful.

Let’sgooverthisoutput.AutoLayoutisreportingthatitisUnabletosimultaneously

Page 209: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

satisfyconstraints.Thishappenswhenaviewhierarchyhasconstraintsthatconflict.Then,theconsolespitsoutsomehandytipsandalistofallconstraintsthatareinvolved,withtheirdescriptions.Let’slookattheformatofoneoftheseconstraintsmoreclosely.<NSLayoutConstraint:0x7fb6b9975350UISegmentedControl:0x7fb6b9897390.leading

==UILayoutGuide:0x7fb6b9972640'UIViewLayoutMarginsGuide'.leading>

Thisdescriptionindicatesthattheconstraintlocatedatmemoryaddress0x7fb6b9975350issettingtheleadingedgeoftheUISegmentedControl(at0x7fb6b9897390)equaltotheleadingedgeofthemarginoftheUILayoutGuide(at0x7fb6b9972640).FiveoftheseconstraintsareinstancesofNSLayoutConstraint.One,however,isaninstanceofNSAutoresizingMaskLayoutConstraint.Thisconstraintistheproductofthetranslationoftheimageview’sautoresizingmask.Finally,AutoLayouttellsyouhowitisgoingtosolvetheproblembylistingtheconflictingconstraintthatitwillignore.Unfortunately,itchoosespoorlyandignoresoneofyourexplicitinstancesofNSLayoutConstraintinsteadoftheNSAutoresizingMaskLayoutConstraint.Thisiswhyyourinterfacelookslikeitdoes.Thenotebeforetheconstraintsarelistedisveryhelpful:TheNSAutoresizingMaskLayoutConstraintneedstoberemoved.Betteryet,youcanpreventthisconstraintfrombeingaddedinthefirstplacebyexplicitlydisablingtranslationinloadView()://segmentedControl.translatesAutoresizingMaskIntoConstraints=false

view.addSubview(segmentedControl)

Page 210: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 211: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

7Localization

TheappealofiOSisglobal–iOSusersliveinmanycountriesandspeakmanylanguages.Youcanensurethatyourapplicationisreadyforaglobalaudiencethroughtheprocessesofinternationalizationandlocalization.Internationalizationismakingsureyournativeculturalinformation(likelanguage,currency,dateformat,numberformat,etc.)isnothardcodedintoyourapplication.Localizationistheprocessofprovidingtheappropriatedatainyourapplicationbasedontheuser ’sLanguageandRegionFormatsettings.YoucanfindthesesettingsintheiOSSettingsapplication(Figure7.1).SelecttheGeneralrowandthentheLanguage&Regionrow.Figure7.1Languageandregionsettings

Here,userscansettheirregion,likeUnitedStatesorUnitedKingdom.(WhydoesAppleuse“region”insteadof“country”?Somecountrieshavemorethanoneregionwithdifferentsettings.ScrollthroughtheoptionsinRegiontoseeforyourself.)Applemakesinternationalizationandlocalizationrelativelysimple.Anapplicationthattakes

Page 212: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

advantageofthelocalizationAPIsdoesnotevenneedtoberecompiledtobedistributedinotherlanguagesorregions.(Bytheway,because“internationalization”and“localization”arelongwords,youwillsometimesseethemabbreviatedasi18nandL10n,respectively.)

Inthischapter,youwillfirstinternationalizetheWorldTrotterapplicationandthenlocalizeitintoSpanish(Figure7.2).Figure7.2LocalizedWorldTrotter

Page 213: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Internationalization

Inthisfirstsection,youwillusetheNumberFormatterandNSNumberclassestointernationalizetheConversionViewController.

Formatters

InChapter4,youusedaninstanceofNumberFormattertosetthetextoftheCelsiuslabelinConversionViewController.NumberFormatterhasalocaleproperty,whichissettothedevice’scurrentlocale.WheneveryouuseaNumberFormattertocreateanumber,itchecksitslocalepropertyandsetstheformataccordingly.SothetextoftheCelsiuslabelhasbeeninternationalizedfromthestart.Localeknowshowdifferentregionsdisplaysymbols,dates,anddecimalsandwhethertheyusethemetricsystem.AninstanceofLocalerepresentsoneregion’ssettingsforthesevariables.WhenyouaccessthecurrentpropertyonLocale,theinstanceofLocalethatrepresentstheuser ’sregionsettingisreturned.OnceyouhavethatinstanceofLocale,youcanaskitquestions,like,“Doesthisregionusethemetricsystem?”or,“Whatisthecurrencysymbolforthisregion?”letcurrentLocale=Locale.current

letisMetric=currentLocale.usesMetricSystem

letcurrencySymbol=currentLocale.currencySymbol

EventhoughtheCelsiuslabelisalreadyinternationalized,thereisstillaproblemwithit.ChangethesystemregiontoSpaintosee.Selecttheactiveschemepop-upandselectEditScheme...(Figure7.3).Figure7.3Editscheme

MakesurethatRunisselectedonthelefthandsideandthenselecttheOptionstabatthetop.IntheApplicationRegionpop-up,selectEuropeandthenSpain(Figure7.4).Finally,Closetheactiveschemewindow.

Page 214: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure7.4Selectingadifferentregion

Buildandruntheapplication.OntheConversionViewController,tapthetextfieldandmakesurethesoftwarekeyboardisvisible.Youmayalreadynoticeonedifference:InSpain,thedecimalseparatorisacommainsteadofaperiod(andthethousandsseparatorisaperiodinsteadofacomma),sothenumberwritten123,456.789intheUnitedStateswouldbewritten123.456,789inSpain.Attempttotypeinmultipledecimalseparators(thecomma)andnoticethattheapplicationhappilyallowsit.Whoops!Yourcodefordisallowingmultipledecimalseparatorschecksforaperiodinsteadofusingalocale-specificdecimalseparator.Let’sfixthat.OpenConversionViewController.swiftandupdatetextfield(_:shouldChangeCharactersIn:replacementString:)tousethelocale-specificdecimalseparator.functextField(_textField:UITextField,

shouldChangeCharactersInrange:NSRange,

replacementStringstring:String)->Bool{

letexistingTextHasDecimalSeparator=textField.text?.range(of:".")

letreplacementTextHasDecimalSeparator=string.range(of:".")

letcurrentLocale=Locale.current

letdecimalSeparator=currentLocale.decimalSeparator??"."

letexistingTextHasDecimalSeparator

=textField.text?.range(of:decimalSeparator)

letreplacementTextHasDecimalSeparator=string.range(of:decimalSeparator)

ifexistingTextHasDecimalSeparator!=nil,

Page 215: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

replacementTextHasDecimalSeparator!=nil{

returnfalse

}else{

returntrue

}

}

Buildandruntheapplication.Theapplicationnolongerallowsyoutotypeinmultipledecimalseparators,anditdoesthisinawaythatisindependentoftheuser ’sregionchoice.Butthereisstillaproblem.Ifyoutypeinanumberwithadecimalseparatorthatisnotaperiod,theconversiontoCelsiusisnothappening–theCelsiuslabeldisplays“???”.Whatisgoingonhere?InfahrenheitFieldEditingChanged(_:),youareusinganinitializerfortheDoubletypethattakesinastringasitsargument.Thisinitializerdoesnotknowhowtohandleastringthatusessomethingotherthanaperiodforitsdecimalseparator.Let’sfixthiscodeusingtheNumberFormatterclass.InConversionViewController.swift,updatefahrenheitFieldEditingChanged(_:)toconvertthetextfield’sstringintoanumberinalocale-independentway.@IBActionfuncfahrenheitFieldEditingChanged(_textField:UITextField){

iflettext=textField.text,letvalue=Double(text){

fahrenheitValue=Measurement(value:value,unit:.fahrenheit)

iflettext=textField.text,letnumber=numberFormatter.number(from:text){

fahrenheitValue=Measurement(value:number.doubleValue,unit:.fahrenheit)

}else{

fahrenheitValue=nil

}

}

Hereyouareusingthenumberformatter ’sinstancemethodnumber(from:)toconvertthestringintoanumber.Becausethenumberformatterisawareofthelocale,itisabletoconvertthestringintoanumber.Ifthestringcontainsavalidnumber,themethodreturnsaninstanceofNSNumber.NSNumberisaclassthatcanrepresentavarietyofnumbertypes,includingInt,Float,Double,andmore.YoucanaskaninstanceofNSNumberforitsvaluerepresentedasoneofthosevalues.YouaredoingthatheretogetthedoubleValueofthenumber.Buildandruntheapplication.Nowthatyouareconvertingthestringinalocale-independentway,thetextfield’svalueisproperlyconvertedtoitsCelsiusvalue(Figure7.5).

Page 216: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure7.5Conversionwithacommaseparator

Baseinternationalization

Wheninternationalizing,youasktheinstanceofLocalequestions.ButtheLocaleonlyhasafewregion-specificvariables.Thisiswherelocalization–creatingapplication-specificsubstitutionsfordifferentregionandlanguagesettings–comesintoplay.Localizationusuallyinvolveseithergeneratingmultiplecopiesofresources(likeimages,sounds,andinterfacefiles)fordifferentregionsandlanguagesorcreatingandaccessingstringstables(whichyouwillseelaterinthechapter)totranslatetextintodifferentlanguages.Beforeyougothroughtheprocessoflocalizingresources,youmustunderstandhowaniOSapplicationhandleslocalizedresources.WhenyoubuildatargetinXcode,anapplicationbundleiscreated.AlloftheresourcesthatyouaddedtothetargetinXcodearecopiedintothisbundlealongwiththeexecutableitself.

Page 217: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

ThisbundleisrepresentedatruntimebyaninstanceofBundleknownasthemainbundle.ManyclassesworkwiththeBundletoloadresources.

Localizingaresourceputsanothercopyoftheresourceintheapplicationbundle.Theseresourcesareorganizedintolanguage-specificdirectories,knownaslprojdirectories.Eachoneofthesedirectoriesisthenameofthelocalizationsuffixedwithlproj.Forexample,theAmericanEnglishlocalizationisen_US,whereenistheEnglishlanguagecodeandUSistheUnitedStatesofAmericaregioncode,sothedirectoryforAmericanEnglishresourcesisen_US.lproj.(Theregioncanbeomittedifyoudonotneedtomakeregionaldistinctionsinyourresourcefiles.)Theselanguageandregioncodesarestandardonallplatforms,notjustiOS.Whenabundleisaskedforthepathofaresourcefile,itfirstlooksattherootlevelofthebundleforafileofthatname.Ifitdoesnotfindone,itlooksatthelocaleandlanguagesettingsofthedevice,findstheappropriatelprojdirectory,andlooksforthefilethere.Thus,justbylocalizingresourcefiles,yourapplicationwillautomaticallyloadthecorrectfile.Oneoptionforlocalizingresourcefilesistocreateseparatestoryboardfilesandmanuallyediteachstringineachfile.However,thisapproachdoesnotscalewellifyouareplanningmultiplelocalizations.Whathappenswhenyouaddanewlabelorbuttontoyourlocalizedstoryboard?Youhavetoaddthisviewtothestoryboardforeverylanguage.Notfun.Tosimplifytheprocessoflocalizinginterfacefiles,Xcodehasafeaturecalledbaseinternationalization.BaseinternationalizationcreatestheBase.lprojdirectory,whichcontainsthemaininterfacefiles.LocalizingindividualinterfacefilescanthenbedonebycreatingjusttheLocalizable.stringsfiles.Itisstillpossibletocreatethefullinterfacefiles,incaselocalizationcannotbedonebychangingstringsalone.However,withthehelpofAutoLayout,stringreplacementissufficientformostlocalizationneeds.Inthenextsection,youwilluseAutoLayouttoprepareyourlayoutforlocalization.

Preparingforlocalization

OpenMain.storyboardandshowtheassistanteditoreitherbyclickingView→AssistantEditor→ShowAssistantEditororwiththekeyboardshortcutOption-Command-Return.Fromthejumpbardropdown,selectPreview(Figure7.6).Thepreviewassistantallowsyoutoeasilyseehowyourinterfacewilllookacrossscreensizesandorientationsaswellasbetweendifferentlocalizedlanguages.

Page 218: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure7.6Openingthepreviewassistant

Inthestoryboard,selecttheConversionViewControllertoseeitspreview(Figure7.7).Figure7.7Previewassistant

Page 219: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Noticethecontrolsinthelowercornersofthepreviewassistant.The+buttonontheleftsideallowsyoutoaddadditionalscreensizestothepreviewcanvas.Thisallowsyoutoeasilyseehowchangestoyourinterfacepropagateacrossscreensizesandorientationssimultaneously.Thebuttonontherightsideallowsyoutoselectalanguagetopreviewthisinterfacein.(IfyourpreviewisforaconfigurationotherthaniPhone7,usethe+buttontoaddthisconfiguration.ThenclickonwhateverpreviewopenedbydefaultandpresstheDeletekeytoremoveit.)Youhavenotlocalizedtheapplicationintoanotherlanguageyet,butXcodesuppliesapseudolanguageforyoutouse.Pseudolanguageshelpyouinternationalizeyourapplicationsbeforereceivingtranslationsforallofyourstringsandassets.Thebuilt-inpseudolanguage,Double-LengthPseudolanguage,mimicslanguagesthataremoreverbosebyrepeatingwhatevertextstringisinthetextelement.So,forexample,“isreally”becomes“isreallyisreally.”SelecttheLanguagepop-upthatsaysEnglishandchooseDouble-LengthPseudolanguage.Thelabelsall

Page 220: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

havetheirtextdoubled(Figure7.8).Figure7.8Doubledtextstrings

Thedouble-lengthpseudolanguagerevealsaproblemimmediately:Thelabelsgooffboththeleftandrightedgesofthescreen,andyouareunabletoreadtheentirestrings.Thefixistoconstrainallofthelabelssothattheirleadingandtrailingedgesstaywithinthemarginsoftheirsuperview.Thenyouwillneedtochangethelinecountforthelabelsto0,whichtellsthelabelsthattheirtextshouldwraptomultiplelinesifneeded.Youaregoingtostartbyfixingonelabel,thenrepeatthestepsfortherestofthelabels.Inthecanvas,selectthedegreesFahrenheitlabel.Youaregoingtoaddconstraintstothislabelinanewway.Control-dragfromthelabeltotheleftsideofthesuperview.Whenyoudo,acontext-sensitivepop-upwillappeargivingyoutheconstraintsthatmakesenseforthisdirection(Figure7.9).SelectLeadingSpacetoContainerMarginfromthelist.

Page 221: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure7.9CreatingconstraintsbyControl-dragging

Thedirectionthatyoudraginfluenceswhichpossibleconstraintsaredisplayed.Ahorizontaldragwillshowhorizontalconstraints,andaverticaldragwillshowverticalconstraints.Adiagonaldragwillshowbothhorizontalandverticalconstraints,whichisusefulforsettingupmanyconstraintssimultaneously.NowControl-dragfromthedegreesFahrenheitlabeltotherightsideofthesuperviewandselectTrailingSpacetoContainerMargin.Ontheirown,theseconstraintsarenotverygood.Theymaintaintheexistingfixeddistancebetweentheleadingandtrailingedgesofthelabel,asyoucanseeinthepreviewassistant(Figure7.10).

Page 222: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure7.10Previewassistantwithnewconstraints

Whatyoureallywantisforthedistancebetweenthelabelandthemarginstobegreaterthanorequalto0.Youcandothiswithinequalityconstraints.SelecttheleadingconstraintbyclickingontheI-bartotheleftofthelabel.OpenitsattributesinspectorandchangetheRelationtoGreaterThanorEqualandtheConstantto0(Figure7.11).

Page 223: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure7.11Inequalityconstraint

Dothesameforthetrailingconstraint.Takealookatthepreviewassistant;theinterfaceislookingbetter,butthelabelisstillbeingtruncated.Selectthelabelandopenitsattributesinspector.ChangetheLinescountto0.Nowtakealookatthepreviewassistant;thelabelisnolongerbeingtruncatedandinsteadthetextflowstoasecondline.Becausetheotherlabelsareeachrelatedtothelabelabovethem,theyhaveautomaticallybeenmoveddown.Repeatthestepsabovefortheotherlabels.Youwillneedto:

Addaleadingandtrailingconstrainttoeachlabel.Settheconstraints’relationtoGreaterThanorEqualandtheconstantto0.(Ashortcutforeditingaconstraintistodouble-clickonit.)Changethelabel’slinecountto0.

Whenyouaredone,thepreviewassistantwiththedouble-lengthpseudolanguagewilllooklikeFigure7.12.

Page 224: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure7.12Previewassistantwithfinalconstraints

Atthispoint,youaredonewiththepreviewassistant.Youcanclosetheassistanteditorwiththexinthetop-rightcorner.

Page 225: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 226: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Localization

WorldTrotterisnowinternationalized–itsinterfaceisabletoadapttovariouslanguagesandregions.Nowitistimetolocalizetheapp–thatis,toupdatethestringsandresourcesintheapplicationforanewlanguage.Inthissection,youaregoingtolocalizetheinterfaceofWorldTrotter:theMain.storyboardfile.YouwillcreateEnglishandSpanishlocalizations,whichwillcreatetwolprojdirectoriesinadditiontothebaseone.Startbylocalizingastoryboardfile.SelectMain.storyboardintheprojectnavigator.Openthefileinspectorbyclickingthe tabintheinspectorselectororbyusingthekeyboardshortcutOption-Command-1.FindthesectioninthisinspectornamedLocalization.ChecktheEnglishboxandmakesurethatthedropdownsaysLocalizableStrings(Figure7.13).Thiswillcreateastringstablethatyouwilluselatertolocalizetheapplication.Figure7.13LocalizingintoEnglish

Next,intheprojectnavigator,selecttheWorldTrotterprojectatthetop.ThenselectWorldTrotterundertheProjectsectioninthesidelist,andmakesuretheInfotabisopen.(Ifyoucannotseethesidelist,youcanopenitusingtheShowprojectsandtargetslistbuttonintheupper-leftcorner(Figure7.14).)Figure7.14Showingtheprojectsettings

Clickthe+buttonunderLocalizationsandselectSpanish(es).Inthedialog,youcanunchecktheLaunchScreen.storyboardfile;keeptheMain.storyboardfilechecked.MakesurethatthereferencelanguageisBaseandthefiletypeisLocalizableStrings.ClickFinish.Thiscreatesanes.lprojfolderandgeneratestheMain.stringsfileinitthatcontainsallthe

Page 227: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

stringsfromthebaseinterfacefile.TheLocalizationsconfigurationshouldlooklikeFigure7.15.Figure7.15Localizations

Lookintheprojectnavigator.ClickthedisclosurebuttonnexttoMain.storyboard(Figure7.16).XcodemovedtheMain.storyboardfiletotheBase.lprojdirectoryandcreatedtheMain.stringsfileinthees.lprojdirectory.Figure7.16Localizedstoryboardintheprojectnavigator

ClickontheSpanishversionofMain.strings.Whenthisfileopens,thetextisnotinSpanish.Youhavetotranslatelocalizedfilesyourself;Xcodeisnotthatsmart.Editthisfileaccordingtothefollowingtext.Thenumbersandordermaybedifferentinyour

Page 228: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

file,butyoucanusethetextandtitlefieldsinthecommentstomatchupthetranslations./*Class="UITabBarItem";title="Map";ObjectID="6xh-o5-yRt";*/

"6xh-o5-yRt.title"="Map""Mapa";

/*Class="UILabel";text="degreesCelsius";ObjectID="7la-u7-mx6";*/

"7la-u7-mx6.text"="degreesCelsius""gradosCelsius";

/*Class="UILabel";text="degreesFahrenheit";ObjectID="Dic-rs-P0S";*/

"Dic-rs-P0S.text"="degreesFahrenheit""gradosFahrenheit";

/*Class="UILabel";text="100";ObjectID="Eso-Wf-EyH";*/

"Eso-Wf-EyH.text"="100";

/*Class="UITextField";placeholder="value";ObjectID="On4-jV-YlY";*/

"On4-jV-YlY.placeholder"="value""valor";

/*Class="UILabel";text="isreally";ObjectID="wtF-xR-gbZ";*/

"wtF-xR-gbZ.text"="isreally""esrealmente";

/*Class="UITabBarItem";title="Convert";ObjectID="zLY-50-CeX";*/

"zLY-50-CeX.title"="Convert""Convertir";

Nowthatyouhavefinishedlocalizingthisstoryboardfile,let’stestitout.First,thereisalittleXcodeglitchtobeawareof:SometimesXcodeignoresaresourcefile’schangeswhenyoubuildanapplication.Toensurethatyourapplicationisbeingbuiltfromscratch,firstdeleteitfromyourdeviceorsimulator.(Pressandholditsiconinthelauncher.Whenitstartstowiggle,tapthedeletebadge.)RelaunchXcode.(Yes,exitandstartitagain.)Then,chooseCleanfromtheProductmenu.Finally,tobeabsolutelysure,pressandholdtheOptionkeywhileopeningtheProductmenuandchooseCleanBuildFolder....Thiswillforcetheapplicationtobeentirelyrecompiled,rebundled,andreinstalled.Opentheactiveschemepop-upandselectEditScheme.MakesureRunisselectedonthelefthandsideandopentheOptionstab.OpentheApplicationLanguagepop-upandselectSpanish.Finally,confirmthatSpainisstillselectedfromtheApplicationRegionpop-up.Closethewindow.Buildandruntheapplication.MakesureyouareviewingtheConversionViewController,andyouwillseetheinterfaceinSpanish.Becauseyousettheconstraintsonthelabelstoaccommodatedifferentlengthsoftext,theyresizethemselvesappropriately(Figure7.17).

Page 229: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure7.17SpanishConversionViewController

NSLocalizedStringandstringstables

Inmanyplacesinyourapplications,youcreateStringinstancesdynamicallyordisplaystringliteralstotheuser.Todisplaytranslatedversionsofthesestrings,youmustcreateastringstable.Astringstableisafilecontainingalistofkey-valuepairsforallofthestringsthatyourapplicationusesandtheirassociatedtranslations.Itisaresourcefilethatyouaddtoyourapplication,butyoudonotneedtodoalotofworktogetdatafromit.Youmightuseastringinyourcodelikethis:letgreeting="Hello!"

Tointernationalizethestringinyourcode,youreplaceliteralstringswiththefunctionNSLocalizedString(_:comment:).letgreeting=NSLocalizedString("Hello!",comment:"Thegreetingfortheuser")

Thisfunctiontakestwoarguments:akeyandacommentthatdescribesthestring’suse.Thekeyisthelookupvalueinastringstable.Atruntime,NSLocalizedString(_:comment:)willlookthroughthestringstablesbundledwithyourapplicationforatablethatmatchestheuser ’slanguagesettings.Then,inthattable,thefunctiongetsthetranslatedstringthatmatchesthekey.NowyouaregoingtointernationalizethestringsthattheMapViewControllerdisplaysinitssegmentedcontrol.InMapViewController.swift,locatetheloadView()methodandupdatetheinitializerforthesegmentedcontroltouselocalizedstrings.

Page 230: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

overridefuncloadView(){

//Createamapview

mapView=MKMapView()

//Setitas*the*viewofthisviewcontroller

view=mapView

letsegmentedControl

=UISegmentedControl(items:["Standard","Satellite","Hybrid"])

letstandardString=NSLocalizedString("Standard",comment:"Standardmapview")

letsatelliteString

=NSLocalizedString("Satellite",comment:"Satellitemapview")

lethybridString=NSLocalizedString("Hybrid",comment:"Hybridmapview")

letsegmentedControl

=UISegmentedControl(items:[standardString,satelliteString,hybridString])

OnceyouhavefilesthathavebeeninternationalizedwiththeNSLocalizedString(_:comment:)function,youcangeneratestringstableswithacommand-lineapplication.OpentheTerminalapp.ThisisaUnixterminal;itisusedtoruncommand-linetools.YouwanttonavigatetothelocationofMapViewController.swift.IfyouhaveneverusedtheTerminalappbefore,hereisahandytrick.InTerminal,typethefollowing:cd

followedbyaspace.(DonotpressReturnyet.)Next,openFinderandlocateMapViewController.swiftandthefolderthatcontainsit.DragtheiconofthatfolderontotheTerminalwindow.Terminalwillfilloutthepathforyou.Itwilllooksomethinglikethis:cd/Users/cbkeur/iOSDevelopment/WorldTrotter/WorldTrotter/

PressReturn.ThecurrentworkingdirectoryofTerminalisnowthisdirectory.UsetheterminalcommandlstoprintoutthecontentsoftheworkingdirectoryandconfirmthatMapViewController.swiftisinthatlist.Togeneratethestringstable,enterthefollowingintoTerminalandpressReturn:genstringsMapViewController.swift

Theresultingfile,Localizable.strings,containsthestringsfromMapViewController.DragthisnewfilefromFinderintotheprojectnavigator(orusetheFile→AddFilesto"WorldTrotter"...menuitem).Whentheapplicationiscompiled,thisresourcewillbecopiedintothemainbundle.OpenLocalizable.strings.Thefileshouldlooksomethinglikethis:/*Hybridmapview*/

"Hybrid"="Hybrid";

/*Satellitemapview*/

"Satellite"="Satellite";

/*Standardmapview*/

"Standard"="Standard";

Page 231: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

NoticethatthecommentaboveyourstringisthesecondargumentyousuppliedtotheNSLocalizedStringfunction.Eventhoughthefunctiondoesnotrequirethecommentargument,includingitwillmakeyourlocalizinglifeeasier.NowthatyouhavecreatedLocalizable.strings,youneedtolocalizeitinXcode.OpenitsfileinspectorandclicktheLocalize...buttonintheutilityarea.MakesureBaseisselectedfromthepop-upandclickLocalize.AddtheSpanishandEnglishlocalizationbycheckingtheboxnexttoeachlanguage.Intheprojectnavigator,clickonthedisclosuretrianglethatnowappearsnexttoLocalizable.strings.OpentheSpanishversion.ThestringonthelefthandsideisthekeythatispassedtotheNSLocalizedString(_:comment:)function,andthestringontherighthandsideiswhatisreturned.ChangethetextontherighthandsidetotheSpanishtranslationsshownbelow.(Totypeanaccentedcharacter,suchas“é,”pressandholdtheappropriatecharacteronyourkeyboardandthenpresstheappropriatenumberfromthepop-up.)/*Hybridmapview*/

"Hybrid"="Hybrid""Híbrido";

/*Satellitemapview*/

"Satellite"="Satellite""Satélite";

/*Standardmapview*/

"Standard"="Standard""Estándar";

Buildandruntheapplicationagain.Nowallthesestrings,includingthetitlesinthesegmentedcontrol,willappearinSpanish(Figure7.18).Iftheydonot,youmightneedtodeletetheapplication,cleanyourproject,andrebuild.(Orcheckyourschemelanguagesetting.)Figure7.18SpanishMapViewController

Internationalizationandlocalizationareveryimportantforyourapptoreachthelargestaudience.Additionally,asyousawearlyinthischapter,yourappmightnotworkforsomeusersifyouhavenotproperlyinternationalizedit.Youwillinternationalize(butnotlocalize)

Page 232: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

yourprojectsintherestofthisbook.Overthepastfivechapters,youhavebuiltaratherimpressiveapplicationthatallowstheusertoconvertbetweenCelsiusandFahrenheitaswellasdisplayamapinafewdifferentways.NotonlydoesthisapplicationscalewellonalliPhonescreensizes,butitisalsolocalizedintoanotherlanguage.Congratulations!

Page 233: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 234: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

BronzeChallenge:AnotherLocalization

Practicemakesperfect.LocalizeWorldTrotterforanotherlanguage.Useatranslationwebsiteifyouneedhelpwiththelanguage.

Page 235: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 236: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

FortheMoreCurious:Bundle’sRoleinInternationalization

TherealworkoftakingadvantageoflocalizationsisdoneforyoubytheclassBundle.Abundlerepresentsalocationonthefilesystemthatgroupsthecompiledcodeandresourcestogether.The“mainbundle”isanothernamefortheapplicationbundle,whichcontainsalloftheresourcesandtheexecutablefortheapplication.YouwilllearnmoreabouttheapplicationbundleinChapter16.Whenanapplicationisbuilt,allofthelprojdirectoriesarecopiedintothemainbundle.Figure7.19showsthemainbundleforWorldTrotter(withsomeadditionalimagesaddedtotheproject).Figure7.19Applicationbundle

Bundleknowshowtosearchthroughlocalizationdirectoriesforeverytypeofresourceusingtheinstancemethodurl(forResource:withExtension:).Whenyouwantapathtoaresourcebundledwithyourapplication,youcallthismethodonthemainbundle.HereisanexampleusingtheresourcefileBoo.png:letpath=Bundle.main.url(forResource:"Boo",withExtension:"png")

Whenattemptingtolocatetheresource,thebundlefirstcheckstoseewhethertheresourceexistsatthetopleveloftheapplicationbundle.Ifso,itreturnsthefullURLtothatfile.Ifnot,thebundlegetsthedevice’slanguageandregionsettingsandlooksintheappropriatelprojdirectoriestoconstructtheURL.Ifitstilldoesnotfindit,itlookswithintheBase.lproj

Page 237: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

directory.Finally,ifnofileisfound,itreturnsnil.

IntheapplicationbundleshowninFigure7.19,iftheuser ’slanguageissettoSpanish,BundlewillfindBoo.pngatthetoplevel,Tom.pngines.lproj,andHat.pnginBase.lproj.Whenyouaddanewlocalizationtoyourproject,Xcodedoesnotautomaticallyremovetheresourcesfromthetop-leveldirectory.Thisiswhyyoumustdeleteandcleananapplicationwhenyoulocalizeafile–otherwise,thepreviousunlocalizedfilewillstillbeintherootleveloftheapplicationbundle.Eventhoughtherearelprojfoldersintheapplicationbundle,thebundlefindsthetop-levelfilefirstandreturnsitsURL.

Page 238: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 239: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

FortheMoreCurious:ImportingandExportingasXLIFF

Theindustry-standardformatforlocalizationdataistheXLIFFdatatype,whichstandsforXMLLocalisationInterchangeFileFormat(andXMLstandsforExtensibleMarkupLanguage).Whenworkingwithtranslators,youwilloftensendthemanXLIFFfilecontainingthedataintheapplicationtolocalize,andtheywillgiveyoubackalocalizedXLIFFfileforyoutoimport.XcodenativelysupportsimportingandexportinglocalizationdatainXLIFF.Theexportingprocesswilltakecareoffindingandexportingthelocalizedstringswithintheproject,whichyoupreviouslydidmanuallyusingthegenstringstool.ToexportthelocalizablestringsinXLIFF,selecttheproject(WorldTrotter)intheprojectnavigator.ThenselecttheEditormenu,andthenExportForLocalization....Onthenextscreen,youcanchoosewhethertoexportexistingtranslations(whichisprobablyagoodideasothetranslatordoesnotdoredundantwork)andwhichlanguagesyouwouldlikeexported(Figure7.20).Figure7.20ExportinglocalizationdataasXLIFF

Toimportlocalizations,selecttheproject(WorldTrotter)intheprojectnavigator.ThenselectEditor→ImportLocalizations....Afterchoosingafile,youwillbeabletoconfirmtheupdatesbeforeyouimport.

Page 240: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 241: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

8ControllingAnimations

Theword“animation”isderivedfromaLatinwordthatmeans“theactofbringingtolife.”Inyourapplications,animationscansmoothlybringinterfaceelementsonscreenorintofocus,theycandrawtheuser ’sattentiontoanactionableitem,andtheycangiveclearindicationsofhowyourappisrespondingtotheuser ’sactions.Inthischapter,youwillreturntoyourQuizappanduseavarietyofanimationtechniquestobringittolife.BeforeupdatingQuiz,though,let’stakealookatwhatcanbeanimatedbylookingatthedocumentation.Toopenthedocumentation,openXcode’sHelpmenuandselectDocumentationandAPIReference.Thiswillopenthedocumentationinanewwindow.Withthedocumentationopen,usethesearchbaratthetoptosearchfor“UIView.”UnderAPIReferenceinthesearchresults,clickUIViewtoopentheclassreference,thenscrolldowntothesectiontitledAnimations.Thedocumentationgivessomeanimationrecommendations(whichwewillfollowinthisbook)andliststhepropertiesonUIViewthatcanbeanimated(Figure8.1).Figure8.1UIViewanimationdocumentation

Page 242: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 243: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

BasicAnimations

ThedocumentationisalwaysagoodstartingpointforlearningaboutanyiOStechnology.Withthatlittlebitofinformationunderyourbelt,let’sgoaheadandaddsomeanimationstoQuiz.Thefirsttypeofanimationyouaregoingtouseisthebasicanimation.Abasicanimationanimatesbetweenastartvalueandanendvalue(Figure8.2).Figure8.2Basicanimation

Thefirstanimationyouaregoingtoaddwillanimatethealphavalue(thedegreeoftransparency)ofthequestionlabelassociatedwithViewController.Whentheuseradvancestothenextquestion,youwilluseananimationtofadeinthelabel.ThereareclassmethodsonUIViewthatwillallowyoutoaccomplishthis.ThesimplestUIViewanimationmethodis:classfuncanimate(withDurationduration:TimeInterval,animations:()->Void)

Thisclassmethodtakestwoarguments:adurationoftypeTimeInterval(whichisanaliasforaDouble)andananimationsvariablethatisaclosure.

Closures

Aclosureisadiscretebundleoffunctionalitythatcanbepassedaroundyourcode.Closuresarealotlikefunctionsandmethods.Infact,functionsandmethodsarejustspecialcasesofclosures.Closureshavealightweightsyntaxthatallowsthemtobeeasilypassedinasargumentstofunctionsandmethods.Aclosurecanevenbethereturntypeofafunctionormethod.Inthissection,youwilluseaclosuretospecifytheanimationsthatyouwanttooccur.Thesignatureofaclosureisacomma-separatedlistofargumentswithinparenthesesfollowedbyareturnarrowandthereturntype:(arguments)->returntype

Noticethatthissyntaxissimilartothesyntaxforfunctions:funcfunctionName(arguments)->returntype

Nowtakealookagainattheclosuresignaturethattheanimationsargumentexpects:classfuncanimate(withDurationduration:TimeInterval,animations:()->Void)

Thisclosuretakesinnoargumentsanddoesnotreturnanything.(Youwillalsoseethisreturntypeexpressedas(),whichmeansthesamethingasVoid.)Theclosuresignatureisprettystraightforwardandfamiliar,buthowdoyoudeclareaclosure

Page 244: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

incode?Closuresyntaxtakesthefollowingform:{(arguments)->returntypein

//code

}

Youwriteaclosureexpressioninsidebraces({}).Theclosure’sargumentsarelistedinsideparenthesesimmediatelyaftertheopeningbrace.Aclosure’sreturntypecomesaftertheparametersandusestheregularsyntax.Thekeywordinisusedtoseparatetheclosure’sargumentsandreturntypefromthestatementsinsideofitsbody.OpenQuiz.xcodeproj.InViewController.swift,addanewmethodtohandletheanimationsanddeclareaclosureconstantthattakesinnoargumentsanddoesnotreturnanything.funcanimateLabelTransitions(){

letanimationClosure={()->Voidin

}

}

Nowyouhaveaconstantthatreferencesachunkoffunctionality.Currently,however,thisclosuredoesnotactuallydoanything.AddfunctionalitytotheclosurethatsetsthealphaofthequestionLabelto1.Then,passthisclosureasanargumenttoanimate(withDuration:animations:).funcanimateLabelTransitions(){

letanimationClosure={()->Voidin

self.questionLabel.alpha=1

}

//Animatethealpha

UIView.animate(withDuration:0.5,animations:animationClosure)

}

ThequestionLabelalreadyhasanalphaof1whenitcomesonscreen,soyouwillnotseeanythinganimateifyoubuildandrun.Toaddressthis,overrideviewWillAppear(_:)toresetthequestionLabel’salphato0eachtimetheViewController’sviewcomesonscreen.overridefuncviewWillAppear(_animated:Bool){

super.viewWillAppear(animated)

//Setthelabel'sinitialalpha

questionLabel.alpha=0

}

Thecodeaboveworksgreat,butyoucanmakeitmoreconcise.Updatethecode.funcanimateLabelTransitions(){

letanimationClosure={()->Voidin

self.questionLabel.alpha=1

}

//Animatethealpha

UIView.animate(withDuration:0.5,animations:animationClosure)

Page 245: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

UIView.animate(withDuration:0.5,animations:{

self.questionLabel.alpha=1

})

}

Youhavemadetwochanges:First,youarepassingintheclosureanonymously(i.e.,passingitdirectlyintothemethodinsteadofassigningittoavariableorconstant).Second,youhaveremovedthetypeinformationbecausetheclosurecaninferthisfromthecontext.NowcalltheanimateLabelTransitions()methodwhenevertheusertapstheNextQuestionbutton.@IBActionfuncshowNextQuestion(_sender:UIButton){

currentQuestionIndex+=1

ifcurrentQuestionIndex==questions.count{

currentQuestionIndex=0

}

letquestion:String=questions[currentQuestionIndex]

questionLabel.text=question

answerLabel.text="???"

animateLabelTransitions()

}

Buildandruntheapplication.WhenyoutapontheNextQuestionbutton,thelabelwillfadeintoview.Animationsprovidealessjarringuserexperiencethanhavingviewsjustpopintoexistence.

Page 246: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 247: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

AnotherLabel

TheanimationworksgreatthefirsttimetheNextQuestionbuttonispressed,butthereisnovisibleanimationonsubsequentbuttonpressesbecausethelabelalreadyhasanalphavalueof1.Inthissection,youaregoingtoaddanotherlabeltotheinterface.WhentheNextQuestionbuttonispressed,theexistinglabelwillfadeoutwhilethenewlabel(withthetextofthenextquestion)willfadein.AtthetopofViewController.swift,replaceyourdeclarationofasinglelabelwithtwolabels.@IBOutletvarquestionLabel:UILabel!

@IBOutletvarcurrentQuestionLabel:UILabel!

@IBOutletvarnextQuestionLabel:UILabel!

@IBOutletvaranswerLabel:UILabel!

XcodeflagsfourplaceswhereyouneedtoreplacequestionLabelwithoneofyournewlabels.UpdateviewDidLoad()tousecurrentQuestionLabel.UpdateviewWillAppear(_:)andshowNextQuestion(_:)tousenextQuestionLabel.funcviewDidLoad(){

super.viewDidLoad()

questionLabel.text=questions[currentQuestionIndex]

currentQuestionLabel.text=questions[currentQuestionIndex]

}

overridefuncviewWillAppear(_animated:Bool){

super.viewWillAppear(animated)

//Setthelabel'sinitialalpha

questionLabel.alpha=0

nextQuestionLabel.alpha=0

}

@IBActionfuncshowNextQuestion(_sender:UIButton){

currentQuestionIndex+=1

ifcurrentQuestionIndex==questions.count{

currentQuestionIndex=0

}

letquestion:String=questions[currentQuestionIndex]

questionLabel.text=question

nextQuestionLabel.text=question

answerLabel.text="???"

animateLabelTransitions()

}

NowupdateanimateLabelTransitions()toanimatethealphaofthetwolabels.YouwillfadeoutthecurrentQuestionLabelandfadeinthenextQuestionLabelsimultaneously.funcanimateLabelTransitions(){

//Animatethealpha

UIView.animate(withDuration:0.5,animations:{

self.questionLabel.alpha=1

Page 248: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

self.currentQuestionLabel.alpha=0

self.nextQuestionLabel.alpha=1

})

}

OpenMain.storyboard.Nowthatthecodehasbeenupdatedforthesetwolabels,youneedtomaketheconnections.Control-clickontheViewControllertoseealistofconnections.NoticethattheexistingquestionLabelisstillpresentwithayellowwarningsignnexttoit(Figure8.3).Clickonthextoremovethisconnection.Figure8.3Missingconnection

ConnectthecurrentQuestionLabeloutlettotheexistingquestionlabelbydraggingfromthecirclenexttocurrentQuestionLabeltothelabelonthecanvas.NowdraganewLabelontotheinterfaceandpositionitnexttotheexistingquestionlabel.ConnectthenextQuestionLabeltothisnewlabel.Youwantthislabeltobeinthesamepositionastheexistingquestionlabel.Asyouhavelikelyguessed,thebestwaytoachievethisisthroughconstraints.Control-dragfromthenextQuestionLabeltothecurrentQuestionLabelandselectTop.ThenControl-dragupwardfromthenextQuestionLabeltoitssuperviewandselectCenterHorizontallyinContainer.Atthispoint,nextQuestionLabelismisplaced.Selectthelabel,opentheResolveAutoLayoutIssuesmenu,andselectUpdateFrames.Thelabelswillnowbeontopofoneanother.Buildandruntheapplication.TaptheNextQuestionbuttonandyouwillseeagracefulfadeforbothofthelabels.Ifyoutapitagain,however,nofadeoccursbecausethenextQuestionLabelalreadyhasanalphaof1.Tofixthis,youwillswapthereferencestothetwolabels.Whentheanimationcompletes,thecurrentQuestionLabelneedstobesettotheonscreenlabel,andthenextQuestionLabelneedstobesettotheoffscreenlabel.Youwilluseacompletion

Page 249: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

handlerontheanimationtoaccomplishthis.

Page 250: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 251: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

AnimationCompletion

Themethodanimate(withDuration:animations:)returnsimmediately.Thatis,itstartstheanimation,butitdoesnotwaitfortheanimationtocomplete.Whatifyouwanttoknowwhenananimationcompletes?Forinstance,youmightwanttochainanimationstogetherorupdateanotherobjectwhentheanimationcompletes.Toknowwhentheanimationfinishes,passaclosureforthecompletionargument.Youwillusethisopportunitytoswapthetwolabelreferences.InViewController.swift,updateanimateLabelTransitions()tousetheUIViewanimationmethodthathasthemostparameters,includingonethattakesinacompletionclosure.funcanimateLabelTransitions(){

//Animatethealpha

UIView.animate(withDuration:0.5,animations:{

self.currentQuestionLabel.alpha=0

self.nextQuestionLabel.alpha=1

})

UIView.animate(withDuration:0.5,

delay:0,

options:[],

animations:{

self.currentQuestionLabel.alpha=0

self.nextQuestionLabel.alpha=1

},

completion:{_in

swap(&self.currentQuestionLabel,

&self.nextQuestionLabel)

})

}

Thedelayindicateshowlongthesystemshouldwaitbeforetriggeringtheanimation.Wewilltalkabouttheoptionslaterinthischapter.Fornow,youarepassinginanemptyarray.Inthecompletionclosure,youneedtotellthesystemthatwhatusedtobethecurrentQuestionLabelisnowthenextQuestionLabelandthatwhatusedtobethenextQuestionLabelisnowthecurrentQuestionLabel.Toaccomplishthis,youusetheswap(_:_:)function,whichacceptstworeferencesandswapsthem.Buildandruntheapplication.Nowyouareabletotransitionbetweenallofthequestions.

Page 252: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 253: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

AnimatingConstraints

Inthissection,youaregoingtoextendyouranimationtohavethenextQuestionLabelpropertyflyinfromtheleftsideofthescreenandthecurrentQuestionLabelflyouttotherightsideofthescreenwhentheuserpressestheNextQuestionbutton.Indoingso,youwilllearnhowtoanimateconstraints.First,youneedareferencetotheconstraintsthatneedtobemodified.Sofar,allofyour@IBOutletshavebeentoviewobjects.Butoutletsarenotlimitedtoviews–infact,anyobjectinyourinterfacefilecanhaveanoutlet,includingconstraints.AtthetopofViewController.swift,declaretwooutletsforthetwolabels’centeringconstraints.@IBOutletvarcurrentQuestionLabel:UILabel!

@IBOutletvarcurrentQuestionLabelCenterXConstraint:NSLayoutConstraint!

@IBOutletvarnextQuestionLabel:UILabel!

@IBOutletvarnextQuestionLabelCenterXConstraint:NSLayoutConstraint!

@IBOutletvaranswerLabel:UILabel!

NowopenMain.storyboard.Youwanttoconnectthesetwooutletstotheirrespectiveconstraints.Theeasiestwaytoaccomplishthisisusingthedocumentoutline.ClickthedisclosuretrianglenexttoConstraintsinthedocumentoutlineandlocateCurrentQuestionLabelCenterXConstraint.Control-dragfromtheViewControllertothatconstraint(Figure8.4)andselectthecorrectoutlet.DothesameforNextQuestionLabelCenterXConstraint.Figure8.4Connectingaconstraintoutlet

Page 254: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Currently,theNextQuestionbuttonandtheanswersubviewshavetheircenterXconstrainedtothecenterXofthecurrentQuestionLabel.Whenyouimplementtheanimationforthislabeltoslideoffscreen,theothersubviewswillgowithit.Thisisnotwhatyouwant.SelecttheconstraintthatcenterstheXvalueoftheNextQuestionbuttontothecurrentQuestionLabelanddeleteit.ThenControl-dragupwardfromtheNextQuestionbuttontoitssuperviewandselectCenterHorizontallyinContainer.Next,youwantthetwoquestionlabelstobeonescreenwidthapart.ThecenterofnextQuestionLabelwillbehalfofthescreenwidthtotheleftoftheview.ThecenterofthecurrentQuestionLabelwillbeatitscurrentposition,centeredinthescreen.Whentheanimationistriggered,bothlabelswillmoveafullscreenwidthtotheright,placingthenextQuestionLabelatthecenterofthescreenandthecurrentQuestionLabelhalfascreenwidthtotherightofthescreen(Figure8.5).

Page 255: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure8.5Slidingthelabels

Toaccomplishthis,whentheviewofViewControllerisloaded,youneedtomovethenextQuestionLabeltoitsoffscreenposition.InViewController.swift,addanewmethodandcallitfromviewDidLoad().funcviewDidLoad(){

super.viewDidLoad()

currentQuestionLabel.text=questions[currentQuestionIndex]

updateOffScreenLabel()

}

funcupdateOffScreenLabel(){

letscreenWidth=view.frame.width

nextQuestionLabelCenterXConstraint.constant=-screenWidth

}

Nowyouwanttoanimatethelabelstogofromlefttoright.Animatingconstraintsisabitdifferentthananimatingotherproperties.Ifyoumodifytheconstantofaconstraintwithinananimationblock,noanimationwilloccur.Why?Afteraconstraintismodified,thesystemneedstorecalculatetheframesforalloftherelatedviewsinthehierarchytoaccommodatethischange.Itwouldbeexpensiveforanyconstraintchangetotriggerthisautomatically.(Imagineifyouupdatedquiteafewconstraints–youwouldnotwantittorecalculatetheframesaftereachchange.)Soyoumustaskthesystemtorecalculatetheframeswhenyouaredone.Todothis,youcallthemethodlayoutIfNeeded()onaview.Thiswillforcetheviewtolayoutitssubviewsbasedonthelatestconstraints.InViewController.swift,updateanimateLabelTransitions()tochangetheconstraintconstantsandthenforcethelayoutoftheviews.funcanimateLabelTransitions(){

//Animatethealpha

//andthecenterXconstraints

letscreenWidth=view.frame.width

self.nextQuestionLabelCenterXConstraint.constant=0

self.currentQuestionLabelCenterXConstraint.constant+=screenWidth

UIView.animate(withDuration:0.5,

Page 256: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

delay:0,

options:[],

animations:{

self.currentQuestionLabel.alpha=0

self.nextQuestionLabel.alpha=1

self.view.layoutIfNeeded()

},

completion:{_in

swap(&self.currentQuestionLabel,

&self.nextQuestionLabel)

})

}

Finally,inthecompletionhandler,youneedtoswapthetwoconstraintoutletsandresetthenextQuestionLabeltobeontheleftsideofthescreen.funcanimateLabelTransitions(){

//Animatethealpha

//andthecenterXconstraints

letscreenWidth=view.frame.width

self.nextQuestionLabelCenterXConstraint.constant=0

self.currentQuestionLabelCenterXConstraint.constant+=screenWidth

UIView.animate(withDuration:0.5,

delay:0,

options:[],

animations:{

self.currentQuestionLabel.alpha=0

self.nextQuestionLabel.alpha=1

self.view.layoutIfNeeded()

},

completion:{_in

swap(&self.currentQuestionLabel,

&self.nextQuestionLabel)

swap(&self.currentQuestionLabelCenterXConstraint,

&self.nextQuestionLabelCenterXConstraint)

self.updateOffScreenLabel()

})

}

Buildandruntheapplication.Theanimationworksalmostperfectly.Thelabelsslideonandoffthescreen,andthealphavalueanimatesappropriatelyaswell.Thereisonesmallproblemtofix,butitcanbeabitdifficulttosee.Toseeitmoreeasily,turnonSlowAnimationsfromtheDebugmenuinthesimulator(Command-T).Thewidthofallofthelabelsgetsanimated(toseethisontheanswerLabel,youneedtoclicktheShowAnswerbutton).Thisisbecausetheintrinsiccontentsizechangeswhenthetextchanges.Thefixistoforcetheviewtolayoutitssubviewsbeforetheanimationbegins.Thiswillupdatetheframesofallthreelabelstoaccommodatethenexttextbeforethealphaandslidinganimationsstart.UpdateanimateLabelTransitions()toforcetheviewtolayoutitssubviewsbeforetheanimationbegins.funcanimateLabelTransitions(){

Page 257: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

//Forceanyoutstandinglayoutchangestooccur

view.layoutIfNeeded()

//Animatethealpha

//andthecenterXconstraints

letscreenWidth=view.frame.width

self.nextQuestionLabelCenterXConstraint.constant=0

self.currentQuestionLabelCenterXConstraint.constant+=screenWidth

UIView.animate(withDuration:0.5,

delay:0,

options:[],

animations:{

self.currentQuestionLabel.alpha=0

self.nextQuestionLabel.alpha=1

self.view.layoutIfNeeded()

},

completion:{_in

swap(&self.currentQuestionLabel,

&self.nextQuestionLabel)

swap(&self.currentQuestionLabelCenterXConstraint,

&self.nextQuestionLabelCenterXConstraint)

self.updateOffScreenLabel()

})

}

Buildandruntheapplicationandcyclethroughsomequestionsandanswers.Theminoranimationissueisnowresolved.

Page 258: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 259: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

TimingFunctions

Theaccelerationoftheanimationiscontrolledbyitstimingfunction.Bydefault,animationsuseanease-in/ease-outtimingfunction.Touseadrivinganalogy,thiswouldmeanthedriveracceleratessmoothlyfromresttoaconstantspeedandthengraduallyslowsdownattheend,comingtorest.Othertimingfunctionsincludelinear(aconstantspeedfrombeginningtoend),ease-in(acceleratingtoaconstantspeedandthenendingabruptly),andease-out(beginningatfullspeedandthenslowingdownattheend).InViewController.swift,updatetheanimationinanimateLabelTransitions()tousealineartimingfunction.UIView.animate(withDuration:0.5,

delay:0,

options:[.curveLinear],

animations:{

self.currentQuestionLabel.alpha=0

self.nextQuestionLabel.alpha=1

self.view.layoutIfNeeded()

},

completion:{_in

swap(&self.currentQuestionLabel,

&self.nextQuestionLabel)

swap(&self.currentQuestionLabelCenterXConstraint,

&self.nextQuestionLabelCenterXConstraint)

self.updateOffScreenLabel()

})

Now,asopposedtousingthedefaultease-in/ease-outanimationcurve,theanimationwillhavealinearanimationcurve.Buildandruntheapplication.Thedifferenceissubtle,butitisnoticeableifyouwatchforit.TheoptionsparametertakesinaUIViewAnimationOptionsargument.Whyisthisargumentinsquarebrackets?Therearemanyoptionsforananimationinadditiontothetimingfunction.Becauseofthis,youneedawayofspecifyingmorethanoneoption–anarray.UIViewAnimationOptionsconformstotheOptionSetprotocol,whichallowsyoutogroupmultiplevaluesusinganarray.Herearesomeofthepossibleanimationoptionsthatyoucanpassintotheoptionsparameter.AnimationcurveoptionsControltheaccelerationoftheanimation.Possiblevaluesare:

UIViewAnimationOptions.curveEaseInOut

UIViewAnimationOptions.curveEaseIn

UIViewAnimationOptions.curveEaseOut

UIViewAnimationOptions.curveLinear

Page 260: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

UIViewAnimationOptions.allowUserInteraction

Bydefault,viewscannotbeinteractedwithwhenanimating.Specifyingthisoptionoverridesthedefault.Thiscanbeusefulforrepeatinganimations,suchasapulsingview.UIViewAnimationOptions.repeat

Repeatstheanimationindefinitely;oftenpairedwiththeUIViewAnimationOptions.autoreverseoption.UIViewAnimationOptions.autoreverse

Runstheanimationforwardandthenbackward,returningtheviewtoitsinitialstate.BesuretocheckouttheConstantssectionoftheUIViewClassReferencetoseeallofthepossibleoptions.

Page 261: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 262: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

BronzeChallenge:SpringAnimations

iOShasapowerfulphysicsenginebuiltin.Aneasywaytoharnessthispowerisbyusingaspringanimation.//UIView

classfuncanimate(withDurationduration:TimeInterval,

delay:TimeInterval,

usingSpringWithDampingdampingRatio:CGFloat,

initialSpringVelocityvelocity:CGFloat,

options:UIViewAnimationOptions,

animations:()->Void,

completion:((Bool)->Void)?)

Usethismethodtohavethetwolabelsanimateonandoffthescreeninaspring-likefashion.RefertotheUIViewdocumentationtounderstandeachofthearguments.

Page 263: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 264: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

SilverChallenge:LayoutGuides

Ifyourotateintolandscape,thenextQuestionLabelbecomesvisible.Insteadofhardcodingthespacingconstraint’sconstant,useaninstanceofUILayoutGuidetospacethetwolabelsapart.ThislayoutguideshouldhaveawidthconstraintequaltotheViewController’sviewtoensurethatthenextQuestionLabelremainsoffscreenwhennotanimating.

Page 265: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 266: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

9Debugging

Asyouwriteanapplication,youwillinevitablymakemistakes.Evenworse,fromtimetotimeyouwillhaveerrorsinyourapplication’sdesign.Xcode’sdebugger(calledLLDB)isthefundamentaltoolthatwillhelpyoufindthesebugsandfixthem.ThischaptergivesyouanoverviewofXcode’sdebuggeranditsbasicfunctions.

Page 267: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

ABuggyProject

YouwilluseasimpleprojecttoguideyouthroughyourexplorationoftheXcodedebugger.OpenXcodeandcreateanewprojectforaniOSsingleviewapplication.NametheprojectBuggyandmakesureLanguageissettoSwift,DevicesissettoiPhone,andUseCoreData,IncludeUnitTests,andIncludeUITestsareallunchecked(Figure9.1).ClickNext.Figure9.1ConfiguringBuggy

Asyouwritethisapplication’scode,keepinmindthatitisabuggyproject.Youmaybeaskedtotypecodeyouknowisincorrect.Donotfixitasyoutypeitin;thoseerrorswillhelpyoulearnaboutdebuggingtechniques.Togetstarted,openMain.storyboardanddragaUIButtonontotheViewControllerScene.Double-clickonthenewbuttonandchangeitstitleto“Tapme!”Withthebuttonstillselected,opentheAutoLayoutAlignmenu.CheckHorizontallyinContainerandclickAdd1Constraint.Next,opentheAddNewConstraintsmenu.Pinthedistancetothetopofthecontainer,checktheWidthandHeightboxes,andclickAdd3Constraints.YourresultsshouldlooksomethinglikeFigure9.2,butdonotworryifyouractualdimensionsandspacingareabitdifferent.

Page 268: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure9.2AutoLayoutconstraintsfortheTapme!button

Nowyouneedtoimplementamethodforthisbuttontotriggerandthenconnectittothebuttoninthestoryboard.OpenViewController.swiftandimplementanactionmethodforthebuttontotrigger.@IBActionfuncbuttonTapped(_sender:UIButton){

}

NowopenMain.storyboardandControl-dragfromthebuttontotheViewControllerandconnectittothebuttonTapped:option.BackinViewController.swift,addaprint()statementtothebuttonTapped(_:)methodtoconfirmthatthemethodiscalledinresponsetoabuttontap.@IBActionfuncbuttonTapped(_sender:UIButton){

print("CalledbuttonTapped(_:)")

}

Buildandruntheapplication.Makesurethebuttoniscorrectlydisplayedonthescreenandthatyoucantapit.AlsoconfirmthattheCalledbuttonTapped(_:)messageprintstotheconsolewhenyoutapthebutton.

Page 269: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 270: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

DebuggingBasics

Thesimplestdebuggingusestheconsole.Interpretingtheinformationprovidedintheconsolewhenanapplicationcrashesorintentionallylogginginformationtotheconsoleallowsyoutoobserveandzeroinonyourcode’sfailures.Let’slookatsomeexamplesofhowtheconsolecansupportyourquestforbug-freecode.

Interpretingconsolemessages

TimetoaddsomemayhemtotheBuggyproject.SupposethatafterconsideringtheUIforawhile,youdecidethataswitchwouldbeabettercontrolthanabutton.OpenViewController.swiftandmakethefollowingchangestothebuttonTapped(_:)method.@IBActionfuncbuttonTapped(_sender:UIButton){

@IBActionfuncswitchToggled(_sender:UISwitch){

print("CalledbuttonTapped(_:)")

}

YourenamedtheactiontoreflectthechangeofcontrolandyouchangedthetypeofsendertoUISwitch.Unfortunately,youforgottoupdatetheinterfaceinMain.storyboard.Buildandruntheapplication,thentaponthebutton.Theapplicationwillcrashandyouwillseeamessageloggedtotheconsolesimilartotheoneonthenextpage.(Wehavetruncatedsomeoftheinformationtofitonthepage.)

Page 271: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

2016-08-2412:52:38.463Buggy[1961:47078]-[Buggy.ViewControllerbuttonTapped:]:

unrecognizedselectorsenttoinstance0x7ff6db708870

2016-08-2412:52:38.470Buggy[1961:47078]***Terminatingappduetouncaught

exception'NSInvalidArgumentException',

reason:'-[Buggy.ViewControllerbuttonTapped:]:unrecognizedselectorsentto

instance0x7ff6db708870'

***Firstthrowcallstack:

(

0CoreFoundation[...]__exceptionPreprocess+171

1libobjc.A.dylib[...]objc_exception_throw+48

2CoreFoundation[...]-[NSObject(NSObject)doesNotRecognizeSelector:]+132

3CoreFoundation[...]___forwarding___+1013

4CoreFoundation[...]_CF_forwarding_prep_0+120

5UIKit[...]-[UIApplicationsendAction:to:from:forEvent:]+83

6UIKit[...]-[UIControlsendAction:to:forEvent:]+67

7UIKit[...]-[UIControl_sendActionsForEvents:withEvent:]+444

8UIKit[...]-[UIControltouchesEnded:withEvent:]+668

9UIKit[...]-[UIWindow_sendTouchesForEvent:]+2747

10UIKit[...]-[UIWindowsendEvent:]+4011

11UIKit[...]-[UIApplicationsendEvent:]+371

12UIKit[...]__dispatchPreprocessedEventFromEventQueue+3248

13UIKit[...]__handleEventQueue+4879

14CoreFoundation[...]__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION

15CoreFoundation[...]__CFRunLoopDoSources0+556

16CoreFoundation[...]__CFRunLoopRun+918

17CoreFoundation[...]CFRunLoopRunSpecific+420

18GraphicsServices[...]GSEventRunModal+161

19UIKit[...]UIApplicationMain+159

20Buggy[...]main+111

21libdyld.dylib[...]start+1

)

libc++abi.dylib:terminatingwithuncaughtexceptionoftypeNSException

Themessageintheconsolelooksprettyscaryandhardtounderstand,butitisnotasbadasitfirstseems.Thereallyusefulinformationisattheverytop.Let’sstartwiththeveryfirstline.2016-08-2412:52:38.463Buggy[1961:47078]-[Buggy.ViewControllerbuttonTapped:]:

unrecognizedselectorsenttoinstance0x7ff6db708870

Thereisatimestamp,thenameoftheapplication,andthestatementunrecognizedselectorsenttoinstance0x7ff6db708870.Tomakesenseofthisinformation,rememberthataniOSapplicationmaybewritteninSwift,butitisstillbuiltontopofCocoaTouch,whichisacollectionofframeworkswritteninObjective-C.Objective-Cisadynamiclanguage,andwhenamessageissenttoaninstance,theObjective-Cruntimefindstheactualmethodtobecalledatthatprecisetimebasedonitsselector,akindofID.Thus,thestatementthatanunrecognizedselector[was]senttoinstance0x7ff6db708870meansthattheapplicationtriedtocallamethodonaninstancethatdidnothaveit.Whichinstancewasit?Youhavetwopiecesofinformationaboutit.First,itisaBuggy.ViewController.(WhynotjustViewController?Swiftnamespacesincludethenameofthemodule,whichinthiscaseistheapplication’sname.)Second,itislocatedatmemoryaddress0x7ff6db708870(youractualaddresswilllikelybedifferent).Theexpression-[Buggy.ViewControllerbuttonTapped:]isarepresentationofObjective-Ccode.AmessageinObjective-Cisalwaysenclosedinsquarebracketsintheform[receiver

Page 272: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

selector].Thereceiveristheclassorinstancetowhichthemessageissent.Thedash(-)beforetheopeningsquarebracketindicatesthatthereceiverisaninstanceofViewController.(Aplussign(+)wouldindicatethatthereceiverwastheclassitself.)

Inshort,thislinefromtheconsoletellsyouthattheselectorbuttonTapped:wassenttoaninstanceofBuggy.ViewControllerbutitwasnotrecognized.Thenextlineofthemessageaddstheinformationthattheappwasterminatedduetoan“uncaughtexception”andspecifiesthetypeoftheexceptionasNSInvalidArgumentException.Thebulkoftheconsolemessageisthestacktrace,alistofallthefunctionsormethodsthatwerecalleduptothepointoftheapplicationcrash.Knowingwhichlogicalpaththeapplicationtookbeforecrashingcanhelpyoureproduceandfixabug.Noneofthecallsinthestacktracehadachancetoreturn,andtheyarelistedwiththemostrecentcallontop.Hereisthestacktraceagain:***Firstthrowcallstack:

(

0CoreFoundation[...]__exceptionPreprocess+171

1libobjc.A.dylib[...]objc_exception_throw+48

2CoreFoundation[...]-[NSObject(NSObject)doesNotRecognizeSelector:]+132

3CoreFoundation[...]___forwarding___+1013

4CoreFoundation[...]_CF_forwarding_prep_0+120

5UIKit[...]-[UIApplicationsendAction:to:from:forEvent:]+83

6UIKit[...]-[UIControlsendAction:to:forEvent:]+67

7UIKit[...]-[UIControl_sendActionsForEvents:withEvent:]+444

8UIKit[...]-[UIControltouchesEnded:withEvent:]+668

9UIKit[...]-[UIWindow_sendTouchesForEvent:]+2747

10UIKit[...]-[UIWindowsendEvent:]+4011

11UIKit[...]-[UIApplicationsendEvent:]+371

12UIKit[...]__dispatchPreprocessedEventFromEventQueue+3248

13UIKit[...]__handleEventQueue+4879

14CoreFoundation[...]__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION

15CoreFoundation[...]__CFRunLoopDoSources0+556

16CoreFoundation[...]__CFRunLoopRun+918

17CoreFoundation[...]CFRunLoopRunSpecific+420

18GraphicsServices[...]GSEventRunModal+161

19UIKit[...]UIApplicationMain+159

20Buggy[...]main+111

21libdyld.dylib[...]start+1

)

Eachrowinthelistincludesacallnumber,themodulename,amemoryaddress(whichwehaveremovedtofittherestonthepage),andasymbolrepresentingthefunctionormethod.Ifyouscanthestacktracefromthebottomup,youcangetasensethattheapplicationstartsinthemainfunctionofBuggyatthelineidentifiedwithcallnumber20,receivesaneventrecognizedasatouchatcallnumber9,andthentriestosendthecorrespondingactiontothebutton’stargetatcallnumber7.Theselectorfortheactionisnotfound(callnumber2:-[NSObject(NSObject)doesNotRecognizeSelector:]),resultinginanexceptionbeingraised(callnumber1:objc_exception_throw).Althoughthisbreakdownoftheconsolemessageisspecifictooneerrortypeoutofmanypossibilities,understandingthebasicstructureofthesemessageswillhelpyoumakesenseof

Page 273: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

theerrormessagesyouwillencounterinthefuture.Asyougainmoreexperience,youwillstartassociatingerrormessageswithtypesofproblemsandyouwillbecomebetteratdebuggingcode.

Fixingthefirstbug

ReviewingViewController.swift,youdiscoverthatyouchangedyouractionmethodfrombuttonTapped(_:)toswitchToggled(_:),whichiswhytheselectorbuttonTapped:isnotbeingrecognized.Tofixthebug,youhavetwochoices.YoucouldupdatetheactionconnectedtothebuttononMain.storyboardtomatchyournewactionmethod.OryoucouldrevertthenamechangeontheswitchToggled(_:)method.Youdecidethatyoudonotwantaswitchafterall,soopenViewController.swiftandchangeyourmethodbacktoitsearlierimplementation.(Rememberwhatwetoldyou:Makethechangesexactlyasshown,evenifyouseeaproblem.)@IBActionfuncswitchToggled(_sender:UISwitch){

@IBActionfuncbuttonTapped(_sender:UISwitch){

print("CalledbuttonTapped(_:)")

}

Buildandruntheapplication.Itworksfine…ordoesit?Actually,thereisaproblem,whichyouwillresolveinthenextsection.

Cavemandebugging

ThecurrentimplementationofViewController’sbuttonTapped(_:)methodjustlogsastatementtotheconsole.Thisisanexampleofatechniquethatisfondlycalledcavemandebugging:strategicallyplacingprint()callsinyourcodetoverifythatfunctionsandmethodsarebeingcalled(andcalledinthepropersequence)andtologvariablevaluestotheconsoletokeepaneyeonimportantdata.Likethecavemenintheinsurancecommercials,cavemandebuggingisnotasoutmodedasthenamemightsuggest,andmoderndeveloperscontinuetorelyonmessagesloggedtotheconsole.Toexplorewhatcavemandebuggingcandoforyou,logthestateofthesendercontrolwhenbuttonTapped(_:)iscalledinViewController.swift.@IBActionfuncbuttonTapped(_sender:UISwitch){

print("CalledbuttonTapped(_:)")

//Logthecontrolstate:

print("Iscontrolon?\(sender.isOn)")

}

Inthe@IBActionmethodsyouhavewrittenthroughoutthisbook,youhavebeenpassinginanargumentcalledsender.Thisargumentisareferencetothecontrolsendingthemessage.A

Page 274: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

controlisasubclassofUIControl;youhaveworkedwithafewUIControlsubclassessofar,includingUIButton,UITextField,andUISegmentedControl.AsyoucanseeinbuttonTapped(_:)’ssignature,thesenderinthiscaseisaninstanceofaUISwitch.TheisOnpropertyisaBooleanindicatingwhethertheswitchinstanceisintheonstateornot.Buildandruntheapplication.Trytappingthebutton.Oops!Youhaveanunrecognizedselectorerroragain.CalledbuttonTapped(_:)

2016-08-3009:30:57.730Buggy[9738:1177400]-[UIButtonisOn]:

unrecognizedselectorsenttoinstance0x7fcc5d104cd0

2016-08-3009:30:57.734Buggy[9738:1177400]***Terminatingappduetouncaught

exception'NSInvalidArgumentException',reason:'-[UIButtonisOn]:unrecognized

selectorsenttoinstance0x7fcc5d104cd0'

TheconsolemessagebeginswiththeCalledbuttonTapped(_:)line,indicatingthattheactionwasindeedcalled.ButthentheapplicationcrashesbecausetheisOnselectorissenttoaninstanceofaUIButton.Youcanprobablyseetheproblem:senderistypedasaUISwitchinbuttonTapped(_:),buttheactionisactuallyattachedtoaUIButtoninstanceinMain.storyboard.Toconfirmthishypothesis,logtheaddressofsenderinViewController.swift,justbeforeyoucalltheisOnproperty.@IBActionfuncbuttonTaped(_sender:UISwitch){

print("CalledbuttonTapped(_:)")

//Logsender:

print("sender:\(sender)")

//Logthecontrolstate:

print("Iscontrolon?\(sender.isOn)")

}

Buildandruntheapplicationonemoretime.Aftertappingthebuttonandcrashingtheapplication,checkthefirstfewlinesoftheconsolelog,whichwilllooksomethinglikethis:CalledbuttonTapped(_:)

sender:<UIButton:0x7fcf8c508bb0;frame=(16084;5530);opaque=NO;

autoresize=RM+BM;layer=<CALayer:0x618000220ea0>>

2016-08-3009:45:00.562Buggy[9946:1187061]-[UIButtonisOn]:unrecognizedselector

senttoinstance0x7fcf8c508bb0

2016-08-3009:45:00.567Buggy[9946:1187061]***Terminatingappduetouncaught

exception'NSInvalidArgumentException',reason:'-[UIButtonisOn]:unrecognized

selectorsenttoinstance0x7fcf8c508bb0'

InthelineafterCalledbuttonTapped(_:),yougetinformationaboutthesender.Asexpected,itisaninstanceofaUIButtonanditexistsinmemoryataddress0x7fcf8c508bb0.FurtherdownthelogyoucanconfirmthatthisisthesameinstancetowhichyouaresendingtheisOnmessage.AbuttoncannotrespondtoaUISwitchproperty,sotheappcrashes.Tofixthisproblem,correctthebuttonTapped(_:)definitioninViewController.swift.Whileyouarethere,deletetheextracallstoprint(),whichyouwillnotneedagain.@IBActionfuncbuttonTaped(_sender:UISwitch){

Page 275: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

@IBActionfuncbuttonTaped(_sender:UIButton){

print("CalledbuttonTapped(_:)")

//Logsender:

print("sender:\(sender)")

//Logthecontrolstate:

print("Iscontrolon?\(sender.isOn)")

}

Swifthasfourliteralexpressionsthatcanassistyouinlogginginformationtotheconsole(Table9.1):Table9.1Literalexpressionsusefulfordebugging

Literal Type Value

#file String Thenameofthefilewheretheexpressionappears.

#line Int Thelinenumbertheexpressionappearson.

#column Int Thecolumnnumbertheexpressionbeginsin.

#function String Thenameofthedeclarationtheexpressionappearsin.

Toillustratetheuseoftheseliteralexpressions,updateyourcalltoprint()inthebuttonTapped(_:)methodinViewController.swift.@IBActionfuncbuttonTapped(_sender:UIButton){

print("CalledbuttonTapped(_:)")

print("Method:\(#function)infile:\(#file)line:\(#line)called.")

}

Buildandruntheapplication.Asyoutapthebutton,youwillseeamessageloggedtotheconsolethatisequivalenttotheonebelow.Method:buttonTappedinfile:/Users/juampa/Desktop/Buggy/Buggy/ViewController.swift

atline:13wascalled.

Whilecavemandebuggingisuseful,beawarethatprint()statementsarenotstrippedfromyourcodeasyoubuildyourprojectforrelease.

Page 276: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 277: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

TheXcodeDebugger:LLDB

Tocontinueyourdebuggingexperiments,youaregoingtoaddanotherbugtoyourapplication.AddthecodebelowtoViewController.swift.NoticethatyouwillbeusinganNSMutableArray,theObjective-CcounterpartofSwift’sArray,tomakethebugalittlehardertofind.@IBActionfuncbuttonTapped(_sender:UIButton){

print("Method:\(#function)infile:\(#file)line:\(#line)called.")

badMethod()

}

funcbadMethod(){

letarray=NSMutableArray()

foriin0..<10{

array.insert(i,at:i)

}

//Goonesteptoofaremptyingthearray(noticetherangechange):

for_in0...10{

array.remove(at:0)

}

}

BuildandruntheapplicationtoconfirmthatataponthebuttonresultsintheapplicationcrashingwithanuncaughtNSRangeExceptionexception.Useyourfreshlyacquiredknowledgetostudyandinterprettheerrormessageasmuchaspossible.IfyouusedaSwiftArraytypetocreatethisbug,Xcodewouldhavebeenabletohighlightthelineofcodethatcausedtheexception.BecauseyouusedanNSMutableArray,thecodethatraisedtheexceptionisdeepwithintheCocoaTouchframework.Frequentlythisisthecasewhendebugging;problemsarenotsoobviousandyouneedtodosomeinvestigativework.

Settingbreakpoints

Assumethatyoudonotknowthedirectcauseofthecrash.Youjustknowithappensafteryoutaptheapplication’sbutton.Areasonablewaytoproceedwouldbetostoptheapplicationafterthebuttonistappedandstepthroughthecodeuntilyougetaclueastotheproblem.OpenViewController.swift.Tostopanapplicationataspecifiedlocationinthecode,yousetabreakpoint.Thesimplestwaytosetabreakpointistoclickontheguttertotheleftoftheeditorpanenexttothelinewhereyouwantexecutiontostop.Tryit:Clicktotheleftoftheline@IBActionfuncbuttonTapped(_sender:UIButton){.Abluemarkerindicatingthenewbreakpointwillappear(Figure9.3).

Page 278: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure9.3Settingabreakpoint

Afterabreakpointisset,youcantoggleitbyclickingonthebluemarkerdirectly.Ifyouclickonthemarkeronce,itwillbecomedisabled,indicatedbyapalershadeofblue(Figure9.4).Figure9.4Disablingabreakpoint

Anotherclickre-enablesthebreakpoint.Youcanalsoenable,disable,delete,oreditabreakpointbyControl-clickingonthemarker.Acontextualmenuwillappear,asshowninFigure9.5.Figure9.5Modifyingabreakpoint

SelectingRevealinBreakpointNavigatoropensthebreakpointnavigatorinXcode’sleftpanewithalistofallthebreakpointsinyourapplication(Figure9.6).Youcanalsoopenthebreakpointnavigatorbyclickingitsiconinthenavigatorselector.

Page 279: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure9.6Thebreakpointnavigator

Steppingthroughcode

MakesureyourbreakpointonthebuttonTapped(_:)methodissetandactiveafteralltheclickingyoudidintheprevioussection.Runtheapplicationandtaponthebutton.Yourapplicationhitsthebreakpointandstopsexecuting,andXcodetakesyoutothelineofcodethatwouldbeexecutednext,whichishighlightedingreen.Italsoopenssomenewinformationareas(Figure9.7).Figure9.7Xcodestoppedatabreakpoint

Page 280: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Youarefamiliarwiththeconsoleandhavealreadyseenthedebugnavigator.Thenewareasherearethevariablesviewandthedebugbar,whichtogetherwiththeconsolemakeupthedebugarea.(Ifyoucannotseethevariablesview,clickonthe icononthebottom-rightcornerofthedebugarea.)Thevariablesviewcanhelpyoudiscoverthevaluesofvariablesandconstantswithinthescopeofthebreakpoint.However,tryingtofindaparticularvaluecanrequireafairamountofdigging.Initially,allyouwillseelistedinthevariablesviewarethesenderandselfargumentspassedtothebuttonTapped(_:)method.Clickonthedisclosuretriangleforsender,andyouwillseethatitcontainsaUIKit.UIControlproperty.Withinitthereisa_targetActionsarraythatcontainsthebutton’sattachedtarget-actionpairs.Openthe_targetActionsarray,openthefirstitem([0]),andthenselectthe_targetproperty.Tapthespacebarwhile_targetisselected,andaQuickLookwindowwillopen,showingapreviewofthevariable(whichisaninstanceofViewController).TheQuickLookisshowninFigure9.8.Figure9.8Inspectingvariablesinthevariablesview

Inthesamesectionasthe_target,youwillseethe_selector.Nexttoit,youwillsee(SEL)"buttonTapped:".The(SEL)indicatesthatthisisaselector,and"buttonTapped:"isthenameoftheselector.

Page 281: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Inthiscontrivedexample,itdoesnothelpyoumuchtodigtofindthe_targetandthe_action;however,onceyoustartworkingwithlarger,morecomplexapplications,itcanbeespeciallyusefultousethevariablesview.Youdoneedtoknowwhatyouarelookingfor,suchasthe_targetandthe_action–butfindingthevaluethatyouareinterestedincanbeveryhelpfulintrackingdownbugs.Nowitistimetostartadvancingthroughthecode.Youcandothisusingthebuttonsonthedebugbar,showninFigure9.9.Figure9.9Thedebugbar

Theimportantbuttonsinthedebugbarare:Continueprogramexecution( )–resumesnormalexecutionoftheprogramStepover( )–executesasinglelineofcodewithoutenteringanyfunctionormethodcallStepinto( )–executesthenextlineofcode,includingenteringafunctionormethodcallStepout( )–continuesexecutionuntilthecurrentfunctionormethodisexited

Clickthe buttonuntilyouhighlightthebadMethod()line(donotexecutethisline).Notethatyoudonotstepintotheprint()method–becauseitisanApple-writtenmethod,youknowtherewillbenoproblemsthere.WithbadMethod()highlighted,clickthe buttontostepintothebadMethod()method,andcontinuesteppingthroughthecodewith untiltheapplicationcrashes.Itwilltakeyouquiteafewclicks,anditwilllooklikeyouaregoingthroughthesamelinesofcodeoverandover–infact,youare,asthecodeloopsovertheranges.Asyoustepthroughthecode,youcanpausetomouseoveriandarray.removetoseetheirvaluesupdate(Figure9.10).

Page 282: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure9.10Examiningthevalueofavariable

Oncetheapplicationcrashes,youhaveconfirmationthatthecrashoccurswithinthebadMethod()method.WiththisknowledgeyoucannowdeleteordisablethebreakpointatthefuncbuttonTapped(_sender:UIButton)line.Todeleteabreakpoint,Control-clickitandselectDeleteBreakpoint.Youcanalsodeleteabreakpointbydraggingthebluemarkeroutofthegutter,asshowninFigure9.11.Figure9.11Draggingamarkertodeletethebreakpoint

Occasionally,youwanttobenotifiedwhenalineofcodeistriggered,butyoudonotneedanyadditionalinformationorfortheapplicationtopausewhenithitsthatline.Toaccomplishthis,youcanaddasoundtoabreakpointandhaveitautomaticallycontinueexecutionafterbeingtriggered.Addanewbreakpointatthearray.insert(i,at:i)lineofthebadMethod()method.ThenControl-clickonthemarkerandselectEditBreakpoint....ClickontheAddActionbuttonandselectSoundfromthepop-upmenu.Finally,checktheboxtoAutomaticallycontinueafterevaluatingactions(Figure9.12).

Page 283: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure9.12Enablingspecialactions

Youhaveconfiguredthebreakpointtomakeanalertsoundinsteadofstoppingexecutioneverytimeitisencountered.Runtheapplicationagainandtapthebutton.Youshouldhearasequenceofsounds,andthentheapplicationwillcrash.Itseemstheapplicationissafelycompletingtheforloop,butyouneedtobesure.FindandControl-clickyourbreakpointmarkeragain,selectingEditBreakpoint...asbefore.Intheeditorpop-up,clickthe+totherightofthesoundactiontoaddanewaction.Fromthepop-up,selectLogMessage.IntheTextfield,enterPassnumber%H(%Histhebreakpointhitcount,areferencetothenumberoftimesthebreakpointhasbeenencountered).Finally,makesuretheLogmessagetoconsoleradiobuttonisselected(Figure9.13).

Page 284: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure9.13Assigningmultipleactionstoabreakpoint

Runtheapplicationagainandtapthebutton.Youwillhearthesequenceofsoundsagain,andtheapplicationwillcrashasbefore.Butthistime,ifyouwatchtheconsole(orscrollupaftertheapplicationcrashes),youwillseethatthebreakpointwasencountered10times.Thisconfirmsthatyourcodeiscompletingtheloopsafely.Deleteyourcurrentbreakpointandaddanewoneonthelinearray.remove(at:0).Editthebreakpointtologthepassnumberandcontinueautomatically,asbefore(Figure9.14).

Page 285: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure9.14Addingaloggingbreakpoint

Runtheapplicationandtapthebutton.Whenitcrashes,scrollupintheconsoleandyouwillseethatthesecondbreakpointwasencountered11times.Thatisonetimetoomany,andyouhaveyoursmokinggun.ItalsoexplainstheNSRangeExceptionloggedontheconsoleastheapplicationcrashes.Carefullyreadthecrashlogontheconsoleagainandmakeasmuchsenseofitaspossible.Beforefixingtheproblem,takethetimetoexploreacouplemoredebuggingstrategies.First,disableordeleteanyremainingbreakpointsintheapplication.Inthesesimpleexamples,youhaveknownjustwheretolooktofindthebuginyourcode,butinreal-worlddevelopmentyouwilloftenhavenoideawhereinyourapplicationabugishiding.Itwouldbeniceifyoucouldtellwhichlineofcodeiscausinganuncaughtexceptionresultinginacrash.Itwouldbenice–andwithanexceptionbreakpoint,youcandojustthat.Openthebreakpointnavigatorandclickonthe+inthelower-leftcornerofthewindow.Fromthecontextualmenu,selectExceptionBreakpoint....Anewexceptionbreakpointiscreatedandapop-upappears.Makesureitcatchesallexceptionsonthrow,asshowninFigure9.15.

Page 286: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure9.15Addinganexceptionbreakpoint

Runtheapplicationandtapthebuttononceagain.TheapplicationautomaticallystopsandXcodetakesyoutothelinethatdirectlycausestheexceptiontoberaised.Note,however,thatthereisnoconsolelog.Thatisbecausetheapplicationhasnotcrashedyet.Toseethecrashandreadthecause,clickonthe buttononthedebugbaruntilyouseethecrash.Thisstrategyistheonetobeginwithasyoutackleanewbug.Infact,manyprogrammersalwayskeepanexceptionbreakpointactivewhiledeveloping.Whydidwemakeyouwaitsolongtouseit?Becauseifyouhadstartedwithanexceptionbreakpoint,youwouldnothaveneededtolearnabouttheotherdebuggingstrategies,andtheyhavetheiruses,too.Feelfreetoremovethisbreakpointifyouwouldlike;youwillnotneeditagain.Youaregoingtotryonefinaltechnique:thesymbolicbreakpoint.Thesearebreakpointsspecifiednotbylinenumber,butbythenameofafunctionormethod,referredtoasasymbol.Symbolicbreakpointsaretriggeredwhenthesymboliscalled–whetherthesymbolisinyourcodeorinaframeworkforwhichyouhavenocode.Addanewsymbolicbreakpointinthebreakpointnavigatorbyclickingthe+buttononthelower-leftcornerand,fromthecontextualmenu,selectingSymbolicBreakpoint....Inthepop-up,specify“badMethod”asthesymbol,asshowninFigure9.16.ThismeansthateverytimebadMethod()iscalled,theapplicationwillstop.

Page 287: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure9.16Addingasymbolicbreakpoint

Runtheapplicationtotestthebreakpoint.TheapplicationshouldstopatbadMethod()afteryoutaptheTapme!button.Inareal-worldapp,itisrarethatyouwoulduseasymbolicbreakpointonamethodthatyoucreated;youwouldlikelyaddanormalbreakpointliketheonesyousawearlierinthischapter.Symbolicbreakpointsaremostusefultostoponamethodthatyoudidnotwrite,suchasamethodinoneofApple’sframeworks.Forexample,youmightwanttoknowwheneverthemethodloadView()istriggeredforanyviewcontrollerwithintheapplication.Finally,fixthebug.funcbadMethod(){

letarray=NSMutableArray()

foriin0..<10{

array.insert(i,at:i)

}

//Goonesteptoofaremptyingthearray(noticetherangechange):

for_in0...10{

for_in0..<10{

array.remove(at:0)

}

}

TheLLDBconsole

AgreatfeatureofXcode’sLLDBdebuggeristhatithasacommand-lineinterface.Theconsoleareaisnotonlyusedtoreadmessages,butalsocanbeusedtotypeLLDBcommands.Thedebuggercommand-lineinterfaceisactivewheneveryouseetheblue(lldb)promptontheconsole.MakesureyoursymbolicbreakpointonbadMethod()isstillactive,runtheapplication,andtapthebuttontobreakatthatpoint.Lookattheconsoleandyouwillseethe(lldb)prompt(Figure9.17).Clickbesidetheprompt,andyoucantypecommands.

Page 288: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure9.17The(lldb)promptontheconsole

OneofthemostusefulLLDBcommandsisprint-object,abbreviatedpo.Thiscommandprintsanicedescriptionofanyinstance.Tryitoutbytypingontheconsole.(lldb)poself

<Buggy.ViewController:0x7fae9852bf20>

TheresponsetothecommandisthatselfisaninstanceofViewController.Nowadvanceonelineofcodewiththecommandstep;thiswillinitializethearrayconstantreference.Printthereference’svaluewithpo.(lldb)step

(lldb)poarray

0elements

Theresponse0elementsisnotveryuseful,asitdoesnotgiveyoualotofinformation.Theprintcommand,abbreviatedp,canbemoreverbose.Tryit.(lldb)parray

(NSMutableArray)$R3=0x00007fae98517c00"0values"{}

Frequently,usingtheconsolewithprintorprint-objecttoexaminevariablesismuchmoreconvenientthanXcode’svariablesviewpane.AnotherusefulLLDBcommandisexpression,abbreviatedexpr.ThiscommandallowsyoutoenterSwiftcodetomodifyvariables.Forexample,addsomedatatothearray,lookatthecontents,andcontinueexecution.(lldb)exprarray.insert(1,at:0)

(lldb)parray

(NSMutableArray)$R5=0x00007fae98517c00"1value"{

[0]=0xb000000000000013Int64(1)

}

(lldb)poarray

▿1element-[0]:1

(lldb)continue

Perhapsmoresurprisingly,youcanalsochangetheUIwithLLDBexpressions.Trychangingthebutton’stintColortored.(lldb)exprself.view.tintColor=UIColor.red

(lldb)continue

Page 289: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

TherearemanyLLDBcommands.Tolearnmore,enterthehelpcommandatthe(lldb)prompt.

Page 290: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 291: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

10UITableViewandUITableViewController

ManyiOSapplicationsshowtheuseralistofitemsandallowtheusertoselect,delete,orreorderitemsonthelist.Whetheranapplicationdisplaysalistofpeopleintheuser ’saddressbookoralistofbest-sellingitemsontheAppStore,itisaUITableViewdoingthework.AUITableViewdisplaysasinglecolumnofdatawithavariablenumberofrows.Figure10.1showssomeexamplesofUITableView.Figure10.1ExamplesofUITableView

Page 292: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

BeginningtheHomepwnerApplication

Inthischapter,youaregoingtostartanapplicationcalledHomepwnerthatkeepsaninventoryofallyourpossessions.Inthecaseofafireorothercatastrophe,youwillhavearecordforyourinsurancecompany.(“Homepwner,”bytheway,isnotatypo.Ifyouneedadefinitionfortheword“pwn,”visitwww.wiktionary.org.)Sofar,youriOSprojectshavebeensmall,butHomepwnerwillgrowintoarealisticallycomplexapplicationoverthecourseofeightchapters.Bytheendofthischapter,HomepwnerwillpresentalistofIteminstancesinaUITableView,asshowninFigure10.2.Figure10.2Homepwner:phase1

Togetstarted,openXcodeandcreateanewiOSSingleViewApplicationproject.ConfigureitasshowninFigure10.3.

Page 293: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure10.3ConfiguringHomepwner

Page 294: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 295: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

UITableViewController

AUITableViewisaviewobject.RecallthatintheMVCdesignpattern,whichiOSdevelopersdotheirbesttofollow,eachclassfallsintoexactlyoneofthefollowingcategories:

model:holdsdataandknowsnothingabouttheUIview:isvisibletotheuserandknowsnothingaboutthemodelobjectscontroller:keepstheUIandthemodelobjectsinsyncandcontrolstheflowoftheapplication

Asaviewobject,aUITableViewdoesnothandleapplicationlogicordata.WhenusingaUITableView,youmustconsiderwhatelseisnecessarytogetthetableworkinginyourapplication:

AUITableViewtypicallyneedsaviewcontrollertohandleitsappearanceonthescreen.AUITableViewneedsadatasource.AUITableViewasksitsdatasourceforthenumberofrowstodisplay,thedatatobeshowninthoserows,andothertidbitsthatmakeaUITableViewausefulUI.Withoutadatasource,atableviewisjustanemptycontainer.ThedataSourceforaUITableViewcanbeanytypeofobjectaslongasitconformstotheUITableViewDataSourceprotocol.AUITableViewtypicallyneedsadelegatethatcaninformotherobjectsofeventsinvolvingtheUITableView.ThedelegatecanbeanyobjectaslongasitconformstotheUITableViewDelegateprotocol.

AninstanceoftheclassUITableViewControllercanfillallthreeroles:viewcontroller,datasource,anddelegate.UITableViewControllerisasubclassofUIViewControllerandthereforehasaview.AUITableViewController’sviewisalwaysaninstanceofUITableView,andtheUITableViewControllerhandlesthepreparationandpresentationoftheUITableView.WhenaUITableViewControllercreatesitsview,thedataSourceanddelegatepropertiesoftheUITableViewareautomaticallysettopointattheUITableViewController(Figure10.4).

Page 296: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure10.4UITableViewController-UITableViewrelationship

SubclassingUITableViewController

YouaregoingtoimplementasubclassofUITableViewControllerforHomepwner.CreateanewSwiftfilenamedItemsViewController.InItemsViewController.swift,defineaUITableViewControllersubclassnamedItemsViewController.importFoundation

importUIKit

classItemsViewController:UITableViewController{

}

NowopenMain.storyboard.Youwanttheinitialviewcontrollertobeatableviewcontroller.SelecttheexistingViewControlleronthecanvasandpressDelete.ThendragaTableViewControllerfromtheobjectlibraryontothecanvas.WiththeTableViewControllerselected,openitsidentityinspectorandchangetheclasstoItemsViewController.Finally,opentheattributesinspectorforItemsViewControllerandchecktheboxforIsInitialViewController.Buildandrunyourapplication.Youshouldseeanemptytableview,asshowninFigure10.5.AsasubclassofUIViewController,aUITableViewControllerinheritstheviewproperty.Whenthispropertyisaccessedforthefirsttime,theloadView()methodiscalled,whichcreatesandloadsaviewobject.AUITableViewController’sviewisalwaysaninstanceofUITableView,soaskingfortheviewofaUITableViewControllergetsyouabright,shiny,andemptytableview.

Page 297: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure10.5EmptyUITableView

YounolongerneedtheViewController.swiftfilethatthetemplatecreatedforyou.SelectthisfileintheprojectnavigatorandpressDelete.

Page 298: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 299: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

CreatingtheItemClass

Yourtableviewneedssomerowstodisplay.Eachrowinthetableviewwilldisplayanitemwithinformationsuchasaname,serialnumber,andvalueindollars.CreateanewSwiftfilenamedItem.InItem.swift,definetheItemclassandgiveitfourproperties.importFoundation

importUIKit

classItem:NSObject{

varname:String

varvalueInDollars:Int

varserialNumber:String?

letdateCreated:Date

}

IteminheritsfromNSObject.NSObjectisthebaseclassthatmostObjective-Cclassesinheritfrom.AlloftheUIKitclassesthatyouhaveworkedwith–UIView,UITextField,andUIViewController,tonameafew–inheriteitherdirectlyorindirectlyfromNSObject.YourownclasseswilloftenneedtoinheritfromNSObjectwhentheyneedtointerfacewiththeruntimesystem.NoticethatserialNumberisanoptionalString,necessarybecauseanitemmaynothaveaserialnumber.Also,noticethatnoneofthepropertieshaveadefaultvalue.Youwillneedtogivethemvaluesinadesignatedinitializer.

Custominitializers

YoulearnedaboutstructinitializersinChapter2.Initializersonstructsarefairlystraightforwardbecausestructsdonotsupportinheritance.Classes,ontheotherhand,havesomerulesforinitializerstosupportinheritance.Classescanhavetwokindsofinitializers:designatedinitializersandconvenienceinitializers.Adesignatedinitializerisaprimaryinitializerfortheclass.Everyclasshasatleastonedesignatedinitializer.Adesignatedinitializerensuresthatallpropertiesintheclasshaveavalue.Onceitensuresthat,adesignatedinitializercallsadesignatedinitializeronitssuperclass(ifithasone).ImplementanewdesignatedinitializerontheItemclassthatsetstheinitialvaluesforalloftheproperties.importUIKit

classItem:NSObject{

varname:String

varvalueInDollars:Int

varserialNumber:String?

letdateCreated:Date

Page 300: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

init(name:String,serialNumber:String?,valueInDollars:Int){

self.name=name

self.valueInDollars=valueInDollars

self.serialNumber=serialNumber

self.dateCreated=Date()

super.init()

}

}

Thisinitializertakesinargumentsforthename,serialNumber,andvalueInDollars.Becausetheargumentnamesandthepropertynamesarethesame,youmustuseselftodistinguishthepropertyfromtheargument.Nowthatyouhaveimplementedyourowncustominitializer,youlosethefreeinitializer–init()–thatclasseshave.Thefreeinitializerisusefulwhenallofyourclass’spropertieshavedefaultvaluesandyoudonotneedtodoadditionalworktocreatethenewinstance.TheItemclassdoesnotsatisfythiscriteria,soyouhavedeclaredacustominitializerfortheclass.Everyclassmusthaveatleastonedesignatedinitializer,butconvenienceinitializersareoptional.Youcanthinkofconvenienceinitializersashelpers.Aconvenienceinitializeralwayscallsanotherinitializeronthesameclass.Convenienceinitializersareindicatedbytheconveniencekeywordbeforetheinitializername.AddaconvenienceinitializertoItemthatcreatesarandomlygenerateditem.convenienceinit(random:Bool=false){

ifrandom{

letadjectives=["Fluffy","Rusty","Shiny"]

letnouns=["Bear","Spork","Mac"]

varidx=arc4random_uniform(UInt32(adjectives.count))

letrandomAdjective=adjectives[Int(idx)]

idx=arc4random_uniform(UInt32(nouns.count))

letrandomNoun=nouns[Int(idx)]

letrandomName="\(randomAdjective)\(randomNoun)"

letrandomValue=Int(arc4random_uniform(100))

letrandomSerialNumber=

UUID().uuidString.components(separatedBy:"-").first!

self.init(name:randomName,

serialNumber:randomSerialNumber,

valueInDollars:randomValue)

}else{

self.init(name:"",serialNumber:nil,valueInDollars:0)

}

}

Ifrandomistrue,theinstanceisconfiguredwitharandomname,serialnumber,andvalue.(Thearc4random_uniformfunctionreturnsarandomvaluebetween0,inclusive,andthevaluepassedinastheargument,exclusive.)Noticethatattheendofbothbranchesoftheconditional,youarecallingthroughtothedesignatedinitializerforItem.Convenienceinitializersmustcallanotherinitializeronthesametype,whereasdesignatedinitializersmust

Page 301: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

calladesignatedinitializeronitssuperclass.TheItemclassisreadyforwork.InthenextsectionyouwilldisplayanarrayofIteminstancesinatableview.

Page 302: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 303: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

UITableView’sDataSource

TheprocessofprovidingrowstoaUITableViewinCocoaTouch(thecollectionofframeworksusedtobuildiOSapps)isdifferentfromthetypicalproceduralprogrammingtask.Inaproceduraldesign,youtellthetableviewwhatitshoulddisplay.InCocoaTouch,thetableviewasksanotherobject–itsdataSource–whatitshoulddisplay.Inthiscase,theItemsViewControlleristhedatasource,soitneedsawaytostoreitemdata.YouaregoingtouseanarraytostoretheIteminstances,butwithatwist.ThearraythatholdstheIteminstanceswillbeabstractedintoanotherobject–anItemStore(Figure10.6).Figure10.6Homepwnerobjectdiagram

Ifanobjectwantstoseealloftheitems,itwillasktheItemStoreforthearraythatcontainsthem.Infuturechapters,thestorewillberesponsibleforperformingoperationsonthearray,likereordering,adding,andremovingitems.Itwillalsoberesponsibleforsavingandloadingtheitemsfromdisk.CreateanewSwiftfilenamedItemStore.InItemStore.swift,definetheItemStoreclassanddeclareapropertytostorethelistofItems.importFoundation

importUIKit

Page 304: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

classItemStore{

varallItems=[Item]()

}

ItemStoreisaSwiftbaseclass–itdoesnotinheritfromanyotherclass.UnliketheItemclassthatyoudefinedearlier,ItemStoredoesnotrequireanyofthebehaviorthatNSObjectaffords.TheItemsViewControllerwillcallamethodonItemStorewhenitwantsanewItemtobecreated.TheItemStorewilloblige,creatingtheobjectandaddingittoanarrayofinstancesofItem.InItemStore.swift,implementcreateItem()tocreateandreturnanewItem.@discardableResultfunccreateItem()->Item{

letnewItem=Item(random:true)

allItems.append(newItem)

returnnewItem

}

The@discardableResultannotationmeansthatacallerofthisfunctionisfreetoignoretheresultofcallingthisfunction.Takealookatthefollowingcodelistingthatillustratesthiseffect.//ThisisOK

letnewItem=itemStore.createItem()

//ThisisalsoOK;theresultisnotassignedtoavariable

itemStore.createItem()

Givingthecontrolleraccesstothestore

InItemsViewController.swift,addapropertyforanItemStore.classItemsViewController:UITableViewController{

varitemStore:ItemStore!

}

Now,whereshouldyousetthispropertyontheItemsViewControllerinstance?Whentheapplicationfirstlaunches,theAppDelegate’sapplication(_:didFinishLaunchingWithOptions:)methodiscalled.TheAppDelegateisdeclaredinAppDelegate.swiftand,asthenameimplies,servesasthedelegatefortheapplicationitself.Itisresponsibleforhandlingthechangesinstatethattheapplicationgoesthrough.YouwilllearnmoreabouttheAppDelegateandthestatesthattheapplicationgoesthroughinChapter16.OpenAppDelegate.swift.AccesstheItemsViewController(whichwillbetherootViewControllerofthewindow)andsetitsitemStorepropertytobeanewinstanceofItemStore.

Page 305: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

funcapplication(_application:UIApplication,didFinishLaunchingWithOptions

launchOptions:[UIApplicationLaunchOptionsKey:Any]?)->Bool{

//Overridepointforcustomizationafterapplicationlaunch.

//CreateanItemStore

letitemStore=ItemStore()

//AccesstheItemsViewControllerandsetitsitemstore

letitemsController=window!.rootViewControlleras!ItemsViewController

itemsController.itemStore=itemStore

returntrue

}

Finally,inItemStore.swift,implementthedesignatedinitializertoaddfiverandomitems.init(){

for_in0..<5{

createItem()

}

}

Asaquickaside,ifcreateItem()wasnotannotatedwith@discardableResult,thenthecalltothatfunctionwouldhaveneededtolooklike://Callthefunction,butignoretheresult

let_=createItem()

AtthispointyoumaybewonderingwhyitemStorewassetexternallyontheItemsViewController.Whydidn’ttheItemsViewControllerinstanceitselfjustcreateaninstanceofthestore?Thereasonforthisapproachisbasedonafairlycomplextopiccalledthedependencyinversionprinciple.Theessentialgoalofthisprincipleistodecoupleobjectsinanapplicationbyinvertingcertaindependenciesbetweenthem.Thisresultsinmorerobustandmaintainablecode.Thedependencyinversionprinciplestatesthat:1. High-levelobjectsshouldnotdependonlow-levelobjects.Bothshoulddependon

abstractions.2. Abstractionsshouldnotdependondetails.Detailsshoulddependonabstractions.

TheabstractionrequiredbythedependencyinversionprincipleinHomepwneristheconceptofa“store.”Astoreisalower-levelobjectthatretrievesandsavesIteminstancesthroughdetailsthatareonlyknowntothatclass.ItemsViewControllerisahigher-levelobjectthatonlyknowsthatitwillbeprovidedwithautilityobject(thestore)fromwhichitcanobtainalistofIteminstancesandtowhichitcanpassneworupdatedIteminstancestobestoredpersistently.ThisresultsinadecouplingbecauseItemsViewControllerisnotdependentonItemStore.Infact,aslongasthestoreabstractionisrespected,ItemStorecouldbereplacedbyanotherobjectthatfetchesIteminstancesdifferently(suchasbyusingawebservice)withoutanychangestoItemsViewController.Acommonpatternusedwhenimplementingthedependencyinversionprincipleisdependencyinjection.Initssimplestform,higher-levelobjectsdonotassumewhichlower-levelobjectstheyneedtouse.Instead,thosearepassedtothemthroughaninitializerorproperty.Inyour

Page 306: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

implementationofItemsViewController,youusedinjectionthroughapropertytogiveitastore.

Implementingdatasourcemethods

Nowthattherearesomeitemsinthestore,youneedtoteachItemsViewControllerhowtoturnthoseitemsintorowsthatitsUITableViewcandisplay.WhenaUITableViewwantstoknowwhattodisplay,itcallsmethodsfromthesetofmethodsdeclaredintheUITableViewDataSourceprotocol.OpenthedocumentationandsearchfortheUITableViewDataSourceprotocolreference.ScrolldowntothesectiontitledConfiguringaTableView(Figure10.7).Figure10.7UITableViewDataSourceprotocoldocumentation

IntheConfiguringaTableViewsection,noticethattwoofthemethodsaremarkedRequired.ForItemsViewControllertoconformtoUITableViewDataSource,itmustimplement

Page 307: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

tableView(_:numberOfRowsInSection:)andtableView(_:cellForRowAt:).Thesemethodstellthetableviewhowmanyrowsitshoulddisplayandwhatcontenttodisplayineachrow.WheneveraUITableViewneedstodisplayitself,itcallsaseriesofmethods(therequiredmethodsplusanyoptionalonesthathavebeenimplemented)onitsdataSource.TherequiredmethodtableView(_:numberOfRowsInSection:)returnsanintegervalueforthenumberofrowsthattheUITableViewshoulddisplay.InthetableviewforHomepwner,thereshouldbearowforeachentryinthestore.InItemsViewController.swift,implementtableView(_:numberOfRowsInSection:).overridefunctableView(_tableView:UITableView,

numberOfRowsInSectionsection:Int)->Int{

returnitemStore.allItems.count

}

Wonderingaboutthesectionthatthismethodrefersto?Tableviewscanbebrokenupintosections,witheachsectionhavingitsownsetofrows.Forexample,intheaddressbook,allnamesbeginningwith“C”aregroupedtogetherinasection.Bydefault,atableviewhasonesection,andinthischapteryouwillworkwithonlyone.Onceyouunderstandhowatableviewworks,itisnothardtousemultiplesections.Infact,usingsectionsisthefirstchallengeattheendofthischapter.ThesecondrequiredmethodintheUITableViewDataSourceprotocolistableView(_:cellForRowAt:).Toimplementthismethod,youneedtolearnaboutanotherclass–UITableViewCell.

Page 308: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 309: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

UITableViewCells

Eachrowofatableviewisaview.TheseviewsareinstancesofUITableViewCell.Inthissection,youwillcreatetheinstancesofUITableViewCelltofillthetableview.Acellitselfhasonesubview–itscontentView(Figure10.8).ThecontentViewisthesuperviewforthecontentofthecell.Thecellmayalsohaveanaccessoryview.Figure10.8UITableViewCelllayout

Theaccessoryviewshowsanaction-orientedicon,suchasacheckmark,adisclosureicon,oraninformationbutton.Theseiconsareaccessedthroughpredefinedconstantsfortheappearanceoftheaccessoryview.ThedefaultisUITableViewCellAccessoryType.none,andthatiswhatyouaregoingtouseinthischapter.YouwillseetheaccessoryviewagaininChapter23.(Curiousnow?SeethedocumentationforUITableViewCellformoredetails.)TherealmeatofaUITableViewCellisthecontentView,whichhasthreesubviewsofitsown(Figure10.9).TwoofthosesubviewsareUILabelinstancesthatarepropertiesofUITableViewCellnamedtextLabelanddetailTextLabel.ThethirdsubviewisaUIImageViewcalledimageView.Inthischapter,youwillusetextLabelanddetailTextLabel.

Page 310: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure10.9UITableViewCellhierarchy

EachcellalsohasaUITableViewCellStylethatdetermineswhichsubviewsareusedandtheirpositionwithinthecontentView.ExamplesofthesestylesandtheirconstantsareshowninFigure10.10.Figure10.10UITableViewCellStyle:stylesandconstants

CreatingandretrievingUITableViewCells

Fornow,eachcellwilldisplaythenameofanItemasitstextLabelandthevalueInDollarsoftheItemasitsdetailTextLabel.Tomakethishappen,youneed

Page 311: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

toimplementthesecondrequiredmethodfromtheUITableViewDataSourceprotocol,tableView(_:cellForRowAt:).Thismethodwillcreateacell,setitstextLabeltothenameoftheItem,setitsdetailTextLabeltothevalueInDollarsoftheItem,andreturnittotheUITableView(Figure10.11).Figure10.11UITableViewCellretrieval

HowdoyoudecidewhichcellanItemcorrespondsto?OneoftheparameterssenttotableView(_:cellForRowAt:)isanIndexPath,whichhastwoproperties:sectionandrow.Whenthismethodiscalledonadatasource,thetableviewisasking,“CanIhaveacelltodisplayinsectionX,rowY?”Becausethereisonlyonesectioninthisexercise,yourimplementationwillonlybeconcernedwiththeindexpath’srow.InItemsViewController.swift,implementtableView(_:cellForRowAt:)sothatthenthrowdisplaysthenthentryintheallItemsarray.overridefunctableView(_tableView:UITableView,

cellForRowAtindexPath:IndexPath)->UITableViewCell{

//CreateaninstanceofUITableViewCell,withdefaultappearance

letcell=UITableViewCell(style:.value1,reuseIdentifier:"UITableViewCell")

//Setthetextonthecellwiththedescriptionoftheitem

//thatisatthenthindexofitems,wheren=rowthiscell

//willappearinonthetableview

letitem=itemStore.allItems[indexPath.row]

cell.textLabel?.text=item.name

cell.detailTextLabel?.text="$\(item.valueInDollars)"

returncell

}

BuildandruntheapplicationnowandyouwillseeaUITableViewpopulatedwithalistof

Page 312: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

randomitems.

ReusingUITableViewCells

iOSdeviceshavealimitedamountofmemory.IfyouweredisplayingalistwiththousandsofentriesinaUITableView,youwouldhavethousandsofinstancesofUITableViewCell.Mostofthesecellswouldtakeupmemoryneedlessly.Afterall,iftheusercannotseeacellonscreen,thenthereisnoreasonforthatcelltohaveaclaimonmemory.Toconservememoryandimproveperformance,youcanreusetableviewcells.Whentheuserscrollsthetable,somecellsmoveoffscreen.Offscreencellsareputintoapoolofcellsavailableforreuse.Then,insteadofcreatingabrandnewcellforeveryrequest,thedatasourcefirstchecksthepool.Ifthereisanunusedcell,thedatasourceconfiguresitwithnewdataandreturnsittothetableview(Figure10.12).Figure10.12ReusableinstancesofUITableViewCell

Thereisoneproblemtobeawareof:SometimesaUITableViewhasdifferenttypesofcells.Occasionally,yousubclassUITableViewCelltocreateaspeciallookorbehavior.However,differentsubclassesfloatingaroundthepoolofreusablecellscreatethepossibilityofgettingbackacellofthewrongtype.Youmustbesureofthetypeofthecellreturnedsothatyoucanbesureofwhatpropertiesandmethodsithas.Notethatyoudonotcareaboutgettinganyspecificcelloutofthepoolbecauseyouaregoingtochangethecellcontentanyway.Whatyouneedisacellofaspecifictype.Thegoodnewsis

Page 313: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

thateverycellhasareuseIdentifierpropertyoftypeString.Whenadatasourceasksthetableviewforareusablecell,itpassesastringandsays,“Ineedacellwiththisreuseidentifier.”Byconvention,thereuseidentifieristypicallythenameofthecellclass.Toreusecells,youneedtoregistereitheraprototypecelloraclasswiththetableviewforaspecificreuseidentifier.YouaregoingtoregisterthedefaultUITableViewCellclass.Youtellthetableview,“Hey,anytimeIaskforacellwiththisreuseidentifier,givemebackacellthatisthisspecificclass.”Thetableviewwilleithergiveyouacellfromthereusepoolorinstantiateanewcelliftherearenocellsofthattypeinthereusepool.OpenMain.storyboard.NoticeinthetableviewthatthereisasectionforPrototypeCells(Figure10.13).Figure10.13Prototypecells

Inthisarea,youcanconfigurethedifferentkindsofcellsthatyouneedfortheassociatedtableview.Ifyouarecreatingcustomcells,thisiswhereyouwillsetuptheinterfaceforthecells.ItemsViewControlleronlyneedsonekindofcell,andusingoneofthebuilt-instyleswillworkgreatfornow,soyouwillonlyneedtoconfiguresomeattributesonthecellthatisalreadyonthecanvas.Selecttheprototypecellandopenitsattributesinspector.ChangetheStyletoRightDetail(whichcorrespondstoUITableViewCellStyle.value1)andgiveitanIdentifierofUITableViewCell(Figure10.14).

Page 314: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure10.14Tableviewcellattributes

Next,inItemsViewController.swift,updatetableView(_:cellForRowAt:)toreusecells.overridefunctableView(_tableView:UITableView,

cellForRowAtindexPath:IndexPath)->UITableViewCell{

//CreateaninstanceofUITableViewCell,withdefaultappearance

letcell=UITableViewCell(style:.value1,reuseIdentifier:"UITableViewCell")

//Getaneworrecycledcell

letcell=tableView.dequeueReusableCell(withIdentifier:"UITableViewCell",

for:indexPath)

...

}

ThemethoddequeueReusableCell(withIdentifier:for:)willcheckthepool,orqueue,ofcellstoseewhetheracellwiththecorrectreuseidentifieralreadyexists.Ifso,itwill“dequeue”thatcell.Ifthereisnotanexistingcell,anewcellwillbecreatedandreturned.Buildandruntheapplication.Thebehavioroftheapplicationshouldremainthesame.Reusingcellsmeansthatyouonlyhavetocreateahandfulofcells,whichputsfewerdemandsonmemory.Yourapplication’susers(andtheirdevices)willthankyou.

Page 315: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 316: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

ContentInsets

Asyouhavebeenrunningtheapplicationthroughoutthischapter,youmighthavenoticedthatthefirsttableviewcellunderlapsthestatusbar(Figure10.15).Theinterfacesfortheapplicationsyoucreatefilluptheentirewindowofthedevice.Thestatusbar,ifvisible,isplacedontopoftheinterface,soyourinterfacesmustaccountfortheplacementofthestatusbar.Figure10.15Tableviewcellunderlappingstatusbar

Tohavethetableviewcellsnotunderlapthestatusbar,youwilladdsomepaddingtothetopofthetableview.AUITableViewisasubclassofUIScrollView,fromwhichitinheritsthecontentInsetproperty.Youcanthinkofthecontentinsetaspaddingforallfoursidesofthescrollview.InItemsViewController.swift,overrideviewDidLoad()toupdatethetableviewcontentinset.overridefuncviewDidLoad(){

super.viewDidLoad()

//Gettheheightofthestatusbar

letstatusBarHeight=UIApplication.shared.statusBarFrame.height

letinsets=UIEdgeInsets(top:statusBarHeight,left:0,bottom:0,right:0)

tableView.contentInset=insets

tableView.scrollIndicatorInsets=insets

}

Thetopofthetableviewisgivenacontentinsetequaltotheheightofthestatusbar.Thiswillmakethecontentappearbelowthestatusbarwhenthetableviewisscrolledtothetop.Thescrollindicatorswillalsounderlapthestatusbar,soyougivethemthesameinsetstohavethemappearjustbelowthestatusbar.NoticethatyouaccessthetableViewpropertyontheItemsViewControllertogetatthetableview.ThispropertyisinheritedfromUITableViewControllerandreturnsthecontroller ’stableview.WhileyoucangetthesameobjectbyaccessingtheviewofaUITableViewController,usingtableViewtellsthecompilerthatthereturnedobject

Page 317: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

willbeaninstanceofUITableView.Thus,callingamethodoraccessingapropertythatisspecifictoUITableViewwillnotgenerateanerror.

Buildandruntheapplication.Thetableviewcellcontentnolongerunderlapsthestatusbarwhenthetableviewisscrolledtothetop(Figure10.16).Figure10.16Tableviewwithadjustedcontentinset

Page 318: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 319: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

BronzeChallenge:Sections

HavetheUITableViewdisplaytwosections–oneforitemsworthmorethan$50andonefortherest.Beforeyoustartthischallenge,copythefoldercontainingtheprojectandallofitssourcefilesinFinder.Thentacklethechallengeinthecopiedproject;youwillneedtheoriginaltobuildoninthefollowingchapters.

Page 320: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 321: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

SilverChallenge:ConstantRows

MakeitsothelastrowoftheUITableViewalwayshasthetext“Nomoreitems!”Makesurethisrowappearsregardlessofthenumberofitemsinthestore(including0items).

Page 322: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 323: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

GoldChallenge:CustomizingtheTable

Makeeachrow’sheight60points,exceptforthelastrowfromthesilverchallenge,whichshouldremain44points.Then,changethefontsizeofeveryrowexceptthelastto20points.Finally,makethebackgroundoftheUITableViewdisplayanimage.(Tomakethispixel-perfect,youwillneedanimageofthecorrectsizedependingonyourdevice.RefertothechartinChapter1.)

Page 324: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 325: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

11EditingUITableView

Inthelastchapter,youcreatedanapplicationthatdisplaysalistofIteminstancesinaUITableView.Thenextstepisallowingtheusertointeractwiththetable–toadd,delete,andmoverows.Figure11.1showswhatHomepwnerwilllooklikebytheendofthischapter.Figure11.1Homepwnerineditingmode

Page 326: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

EditingMode

UITableViewhasaneditingproperty,andwhenthispropertyissettotrue,theUITableViewenterseditingmode.Oncethetableviewisineditingmode,therowsofthetablecanbemanipulatedbytheuser.Dependingonhowthetableviewisconfigured,theusercanchangetheorderoftherows,addrows,orremoverows.(Editingmodedoesnotallowtheusertoeditthecontentofarow.)Butfirst,theuserneedsawaytoputtheUITableViewineditingmode.Fornow,youaregoingtoincludeabuttonintheheaderviewofthetable.Aheaderviewappearsatthetopofatableandisusefulforaddingsection-wideortable-widetitlesandcontrols.ItcanbeanyUIViewinstance.Notethatthetableviewusestheword“header”intwodifferentways:Therecanbeatableheaderandsectionheaders.Likewise,therecanbeatablefooterandsectionfooters(Figure11.2).Figure11.2Headersandfooters

Page 327: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Youarecreatingatableheaderview.ItwillhavetwosubviewsthatareinstancesofUIButton:onetotoggleeditingmodeandtheothertoaddanewItemtothetable.Youcouldcreatethisviewprogrammatically,butinthiscaseyouwillcreatetheviewanditssubviewsinthestoryboardfile.First,let’ssetupthenecessarycode.ReopenHomepwner.xcodeproj.InItemsViewController.swift,stubouttwomethodsintheimplementation.classItemsViewController:UITableViewController{

varitemStore:ItemStore!

@IBActionfuncaddNewItem(_sender:UIButton){

}

@IBActionfunctoggleEditingMode(_sender:UIButton){

}

Page 328: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

NowopenMain.storyboard.Fromtheobjectlibrary,dragaViewtotheverytopofthetableview,abovetheprototypecell.Thiswilladdtheviewasaheaderviewforthetableview.Resizetheheightofthisviewtobeabout60points.(Youcanusethesizeinspectorifyouwanttomakeitexact.)NowdragtwoButtonsfromtheobjectlibrarytotheheaderview.ChangetheirtextandpositionthemasshowninFigure11.3.Youdonotneedtobeexact–youwilladdconstraintssoontopositionthebuttons.Figure11.3Addingbuttonstotheheaderview

SelectbothofthebuttonsandopentheAutoLayoutAlignmenu.SelectVerticallyinContainerwithaconstantof0.MakesureUpdateFramesissettoNone,andthenclickAdd2Constraints(Figure11.4).Figure11.4Alignmenuconstraints

OpentheAddNewConstraintsmenuandconfigureitasshowninFigure11.5.Makesurethevaluesfortheleadingandtrailingconstraintssaveafteryouhavetypedthem;sometimesthe

Page 329: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

valuesdonotsave,soitcanbeabittricky.Whenyouhavedonethat,clickAdd4Constraints.Figure11.5Addingnewconstraints

Finally,connecttheactionsforthetwobuttonsasshowninFigure11.6.

Page 330: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure11.6Connectingthetwoactions

Buildandruntheapplicationtoseetheinterface.Nowlet’simplementthetoggleEditingMode(_:)method.YoucouldtoggletheeditingpropertyofUITableViewdirectly.However,UIViewControlleralsohasaneditingproperty.AUITableViewControllerinstanceautomaticallysetstheeditingpropertyofitstableviewtomatchitsowneditingproperty.Bysettingtheeditingpropertyontheviewcontrolleritself,itcanensurethatotheraspectsoftheinterfacealsoenterandleaveeditingmode.YouwillseeanexampleofthisinChapter14withUIViewController’seditButtonItem.TosettheisEditingpropertyforaviewcontroller,youcallthemethodsetEditing(_:animated:).InItemsViewController.swift,implementtoggleEditingMode(_:).@IBActionfunctoggleEditingMode(_sender:UIButton){

//Ifyouarecurrentlyineditingmode...

ifisEditing{

//Changetextofbuttontoinformuserofstate

sender.setTitle("Edit",for:.normal)

//Turnoffeditingmode

setEditing(false,animated:true)

}else{

//Changetextofbuttontoinformuserofstate

sender.setTitle("Done",for:.normal)

//Entereditingmode

setEditing(true,animated:true)

}

}

Buildandrunyourapplication.TaptheEditbuttonandtheUITableViewwillentereditingmode(Figure11.7).

Page 331: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure11.7UITableViewineditingmode

Page 332: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 333: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

AddingRows

Therearetwocommoninterfacesforaddingrowstoatableviewatruntime.Abuttonabovethecellsofthetableview:usuallyforaddingarecordforwhichthereisadetailview.Forexample,intheContactsapp,youtapabuttonwhenyoumeetanewpersonandwanttotakedownhisorherinformation.Acellwithagreenplussign:usuallyforaddinganewfieldtoarecord,suchaswhenyouwanttoaddabirthdaytoaperson’srecordintheContactsapp.Ineditingmode,youtapthegreenplussignnextto“addbirthday.”

Inthisexercise,youwillusethefirstoptionandcreateaNewbuttonintheheaderview.Whenthisbuttonistapped,anewrowwillbeaddedtotheUITableView.InItemsViewController.swift,implementaddNewItem(_:).@IBActionfuncaddNewItem(_sender:UIButton){

//Makeanewindexpathforthe0thsection,lastrow

letlastRow=tableView.numberOfRows(inSection:0)

letindexPath=IndexPath(row:lastRow,section:0)

//Insertthisnewrowintothetable

tableView.insertRows(at:[indexPath],with:.automatic)

}

Buildandruntheapplication.TaptheAddbuttonand…theapplicationcrashes.Theconsoletellsyouthatthetableviewhasaninternalinconsistencyexception.Rememberthat,ultimately,itisthedataSourceoftheUITableViewthatdeterminesthenumberofrowsthetableviewshoulddisplay.Afterinsertinganewrow,thetableviewhassixrows(theoriginalfiveplusthenewone).WhentheUITableViewasksitsdataSourceforthenumberofrows,theItemsViewControllerconsultsthestoreandreturnsthatthereshouldbefiverows.TheUITableViewcannotresolvethisinconsistencyandthrowsanexception.YoumustmakesurethattheUITableViewanditsdataSourceagreeonthenumberofrowsbyaddinganewItemtotheItemStorebeforeinsertingthenewrow.InItemsViewController.swift,updateaddNewItem(_:).@IBActionfuncaddNewItem(_sender:UIButton){

//Makeanewindexpathforthe0thsection,lastrow

letlastRow=tableView.numberOfRows(inSection:0)

letindexPath=IndexPath(row:lastRow,section:0)

//Insertthisnewrowintothetable

tableView.insertRows(at:[indexPath],with:.automatic)

//Createanewitemandaddittothestore

letnewItem=itemStore.createItem()

//Figureoutwherethatitemisinthearray

ifletindex=itemStore.allItems.index(of:newItem){

letindexPath=IndexPath(row:index,section:0)

Page 334: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

//Insertthisnewrowintothetable

tableView.insertRows(at:[indexPath],with:.automatic)

}

}

Buildandruntheapplication.TaptheAddbutton,andthenewrowwillslideintothebottompositionofthetable.Rememberthattheroleofaviewobjectistopresentmodelobjectstotheuser;updatingviewswithoutupdatingthemodelobjectsisnotveryuseful.Nowthatyouhavetheabilitytoaddrowsanditems,younolongerneedthecodethatputsfiverandomitemsintothestore.OpenItemStore.swiftandremovetheinitializercode.init(){

for_in0..<5{

createItem()

}

}

Buildandruntheapplication.Therewillnolongerbeanyrowswhenyoufirstlaunchtheapplication,butyoucanaddsomebytappingtheAddbutton.

Page 335: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 336: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

DeletingRows

Ineditingmode,theredcircleswiththeminussign(showninFigure11.7)aredeletioncontrols,andtappingoneshoulddeletethatrow.However,atthispoint,youcannotactuallydeletetherow.(Tryitandsee.)Beforethetableviewwilldeletearow,itcallsamethodonitsdatasourceabouttheproposeddeletionandwaitsforconfirmation.Whendeletingacell,youmustdotwothings:removetherowfromtheUITableViewandremovetheItemassociatedwithitfromtheItemStore.Topullthisoff,theItemStoremustknowhowtoremoveobjectsfromitself.InItemStore.swift,implementanewmethodtoremoveaspecificitem.funcremoveItem(_item:Item){

ifletindex=allItems.index(of:item){

allItems.remove(at:index)

}

}

NowyouwillimplementtableView(_:commit:forRow:),amethodfromtheUITableViewDataSourceprotocol.(ThismethodiscalledontheItemsViewController.KeepinmindthatwhiletheItemStoreiswherethedataiskept,theItemsViewControlleristhetableview’sdataSource.)WhentableView(_:commit:forRowAt:)iscalledonthedatasource,twoextraargumentsarepassedalongwithit.ThefirstistheUITableViewCellEditingStyle,which,inthiscase,is.delete.TheotherargumentistheIndexPathoftherowinthetable.InItemsViewController.swift,implementthismethodtohavetheItemStoreremovetherightobjectandconfirmtherowdeletionbycallingthemethoddeleteRows(at:with:)onthetableview.overridefunctableView(_tableView:UITableView,

commiteditingStyle:UITableViewCellEditingStyle,

forRowAtindexPath:IndexPath){

//Ifthetableviewisaskingtocommitadeletecommand...

ifeditingStyle==.delete{

letitem=itemStore.allItems[indexPath.row]

//Removetheitemfromthestore

itemStore.removeItem(item)

//Alsoremovethatrowfromthetableviewwithananimation

tableView.deleteRows(at:[indexPath],with:.automatic)

}

}

Buildandrunyourapplication,createsomerows,andthendeletearow.Itwilldisappear.Noticethatswipe-to-deleteworksalso.

Page 337: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 338: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

MovingRows

TochangetheorderofrowsinaUITableView,youwilluseanothermethodfromtheUITableViewDataSourceprotocol–tableView(_:moveRowAt:to:).Todeletearow,youhadtocallthemethoddeleteRows(at:with:)ontheUITableViewtoconfirmthedeletion.Movingarow,however,doesnotrequireconfirmation:ThetableviewmovestherowonitsownauthorityandreportsthemovetoitsdatasourcebycallingthemethodtableView(_:moveRowAt:to:).Youimplementthismethodtoupdateyourdatasourcetomatchtheneworder.Butbeforeyoucanimplementthismethod,youneedtogivetheItemStoreamethodtochangetheorderofitemsinitsallItemsarray.InItemStore.swift,implementthisnewmethod.funcmoveItem(fromfromIndex:Int,totoIndex:Int){

iffromIndex==toIndex{

return

}

//Getreferencetoobjectbeingmovedsoyoucanreinsertit

letmovedItem=allItems[fromIndex]

//Removeitemfromarray

allItems.remove(at:fromIndex)

//Insertiteminarrayatnewlocation

allItems.insert(movedItem,at:toIndex)

}

InItemsViewController.swift,implementtableView(_:moveRowAt:to:)toupdatethestore.overridefunctableView(_tableView:UITableView,

moveRowAtsourceIndexPath:IndexPath,

todestinationIndexPath:IndexPath){

//Updatethemodel

itemStore.moveItem(from:sourceIndexPath.row,to:destinationIndexPath.row)

}

Buildandrunyourapplication.Addafewitems,thentapEditandcheckoutthenewreorderingcontrols(thethreehorizontallines)onthesideofeachrow.Touchandholdareorderingcontrolandmovetherowtoanewposition(Figure11.8).

Page 339: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure11.8Movingarow

NotethatsimplyimplementingtableView(_:moveRowAt:to:)causedthereorderingcontrolstoappear.TheUITableViewcanaskitsdatasourceatruntimewhetheritimplementstableView(_:moveRowAt:to:).Ifitdoes,thenthetableviewaddsthereorderingcontrolswheneverthetableviewenterseditingmode.

Page 340: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 341: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

DisplayingUserAlerts

Inthissection,youaregoingtolearnaboutuseralertsandthedifferentwaysofconfiguringanddisplayingthem.Useralertscanprovideyourapplicationwithabetteruserexperience,soyouwillusethemfairlyoften.Alertsareoftenusedtowarnusersthatanimportantactionisabouttohappenandperhapsgivethemtheopportunitytocancelthataction.Whenyouwanttodisplayanalert,youcreateaninstanceofUIAlertControllerwithapreferredstyle.ThetwoavailablestylesareUIAlertControllerStyle.actionSheetandUIAlertControllerStyle.alert(Figure11.9).Figure11.9UIAlertControllerstyles

The.actionSheetstyleisusedtopresenttheuserwithalistofactionsfromwhichtochoose.The.alerttypeisusedtodisplaycriticalinformationtorequiretheusertodecidehowtoproceed.Thedistinctionmayseemsubtle,butiftheusercanbackoutofadecisionoriftheactionisnotcritical,thenan.actionSheetisprobablythebestchoice.

Page 342: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

YouaregoingtouseaUIAlertControllertoconfirmthedeletionofitems.Youwillusethe.actionSheetstylebecausethepurposeofthealertistoconfirmorcancelapossiblydestructiveaction.OpenItemsViewController.swiftandmodifytableView(_:commit:forRowAt:)toasktheusertoconfirmorcancelthedeletionofanitem.overridefunctableView(_tableView:UITableView,

commiteditingStyle:UITableViewCellEditingStyle,

forRowAtindexPath:IndexPath){

//Ifthetableviewisaskingtocommitadeletecommand...

ifeditingStyle==.delete{

letitem=itemStore.allItems[indexPath.row]

lettitle="Delete\(item.name)?"

letmessage="Areyousureyouwanttodeletethisitem?"

letac=UIAlertController(title:title,

message:message,

preferredStyle:.actionSheet)

//Removetheitemfromthestore

itemStore.removeItem(item)

//Alsoremovethatrowfromthetableviewwithananimation

tableView.deleteRows(at:[indexPath],with:.automatic)

}

}

Afterdeterminingthattheuserwantstodeleteanitem,youcreateaninstanceofUIAlertControllerwithanappropriatetitleandmessagedescribingwhatactionisabouttotakeplace.Also,youspecifythe.actionSheetstyleforthealert.TheactionsthattheusercanchoosefromwhenshownanalertareinstancesofUIAlertAction,andyoucanaddmultipleonesregardlessofthealert’sstyle.ActionsareaddedtotheUIAlertControllerusingtheaddAction(_:)method.AddthenecessaryactionstotheactionsheetintableView(_:commit:forRowAt:)....

letac=UIAlertController(title:title,

message:message,

preferredStyle:.actionSheet)

letcancelAction=UIAlertAction(title:"Cancel",style:.cancel,handler:nil)

ac.addAction(cancelAction)

letdeleteAction=UIAlertAction(title:"Delete",style:.destructive,

handler:{(action)->Voidin

//Removetheitemfromthestore

self.itemStore.removeItem(item)

//Alsoremovethatrowfromthetableviewwithananimation

self.tableView.deleteRows(at:[indexPath],with:.automatic)

})

ac.addAction(deleteAction)

...

Page 343: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Thefirstactionhasatitleof“Cancel”andiscreatedusingthe.cancelstyle.The.cancelstyleresultsintextinastandardbluefont.ThisactionwillallowtheusertobackoutofdeletinganItem.Thehandlerparameterallowsaclosuretobeexecutedwhenthatactionoccurs.Becausenootheractionisneeded,nilispassedastheargument.Thesecondactionhasatitleof“Delete”andiscreatedusingthe.destructivestyle.Becausedestructiveactionsshouldbeclearlymarkedandnoticed,the.destructivestyleresultsinbrightredtext.Iftheuserselectsthisaction,thentheitemandthetableviewcellneedtoberemoved.Thisisalldonewithinthehandlerclosurethatispassedtotheaction’sinitializer.Nowthattheactionshavebeenadded,thealertcontrollercanbedisplayedtotheuser.BecauseUIAlertControllerisasubclassofUIViewController,youcanpresentittotheusermodally.Amodalviewcontrollertakesovertheentirescreenuntilithasfinisheditswork.Topresentaviewcontrollermodally,youcallpresent(_:animated:completion:)ontheviewcontrollerwhoseviewisonthescreen.Theviewcontrollertobepresentedispassedtoit,andthisviewcontroller ’sviewtakesoverthescreen....

letdeleteAction=UIAlertAction(title:"Delete",style:.destructive,

handler:{(action)->Voidin

//Removetheitemfromthestore

self.itemStore.removeItem(item)

//Alsoremovethatrowfromthetableviewwithananimation

self.tableView.deleteRows(at:[indexPath],with:.automatic)

})

ac.addAction(deleteAction)

//Presentthealertcontroller

present(ac,animated:true,completion:nil)

...

Buildandruntheapplicationanddeleteanitem.Anactionsheetwillbepresentedforyoutoconfirmthedeletion(Figure11.10).

Page 344: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure11.10Deletinganitem

Page 345: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 346: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

DesignPatterns

Adesignpatternsolvesacommonsoftwareengineeringproblem.Designpatternsarenotactualsnippetsofcode,butinsteadareabstractideasorapproachesthatyoucanuseinyourapplications.Gooddesignpatternsarevaluableandpowerfultoolsforanydeveloper.Theconsistentuseofdesignpatternsthroughoutthedevelopmentprocessreducesthementaloverheadinsolvingaproblemsoyoucancreatecomplexapplicationsmoreeasilyandrapidly.Herearesomeofthedesignpatternsthatyouhavealreadyused:

Delegation:Oneobjectdelegatescertainresponsibilitiestoanotherobject.YouuseddelegationwiththeUITextFieldtobeinformedwhenthecontentsofthetextfieldchange.Datasource:Adatasourceissimilartoadelegate,butinsteadofreactingtoanotherobject,adatasourceisresponsibleforprovidingdatatoanotherobjectwhenrequested.Youusedthedatasourcepatternwithtableviews:Eachtableviewhasadatasourcethatisresponsiblefor,ataminimum,tellingthetableviewhowmanyrowstodisplayandwhichcellitshoulddisplayateachindexpath.Model-View-Controller:Eachobjectinyourapplicationsfulfillsoneofthreeroles.Modelobjectsarethedata.ViewsdisplaytheUI.Controllersprovidethegluethattiesthemodelsandviewstogether.Target-actionpairs:Oneobjectcallsamethodonanotherobjectwhenaspecificeventoccurs.Thetargetistheobjectthathasamethodcalledonit,andtheactionisthemethodbeingcalled.Forexample,youusedtarget-actionpairswithbuttons:Whenatoucheventoccurs,amethodwillbecalledonanotherobject(oftenaviewcontroller).

Appleisveryconsistentinitsuseofthesedesignpatterns,andsoitisimportanttounderstandandrecognizethem.Keepaneyeoutforthesepatternsasyoucontinuethroughthisbook!Recognizingthemwillhelpyoulearnnewclassesandframeworksmuchmoreeasily.

Page 347: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 348: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

BronzeChallenge:RenamingtheDeleteButton

Whendeletingarow,aconfirmationbuttonappearslabeledDelete.ChangethelabelofthisbuttontoRemove.

Page 349: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 350: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

SilverChallenge:PreventingReordering

Makeitsothetableviewalwaysshowsafinalrowthatsays“Nomoreitems!”(Thispartofthechallengeisthesameasachallengefromthelastchapter.Ifyouhavealreadydoneit,youcancopyyourcodefrombefore.)Now,makeitsothatthefinalrowcannotbemoved.

Page 351: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 352: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

GoldChallenge:ReallyPreventingReordering

Aftercompletingthesilverchallenge,youmaynoticethateventhoughyoucannotmovetheNomoreitems!rowitself,youcanstilldragotherrowsunderneathit.Makeitsothat–nomatterwhat–theNomoreitems!rowcanneverbeknockedoutofthelastposition.Finally,makeitundeletable.

Page 353: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 354: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

12SubclassingUITableViewCell

AUITableViewdisplaysalistofUITableViewCellobjects.Formanyapplications,thebasiccellwithitstextLabel,detailTextLabel,andimageViewissufficient.However,whenyouneedacellwithmoredetailoradifferentlayout,yousubclassUITableViewCell.Inthischapter,youwillcreateasubclassofUITableViewCellnamedItemCellthatwilldisplayIteminstancesmoreeffectively.EachofthesecellswillshowanItem’sname,itsvalueindollars,anditsserialnumber(Figure12.1).Figure12.1Homepwnerwithsubclassedtableviewcells

YoucustomizetheappearanceofUITableViewCellsubclassesbyaddingsubviewstoitscontentView.AddingsubviewstothecontentViewinsteadofdirectlytothecellitselfisimportantbecausethecellwillresizeitscontentViewatcertaintimes.Forexample,whenatableviewenterseditingmode,thecontentViewresizesitselftomakeroomfortheeditingcontrols(Figure12.2).IfyouaddedsubviewsdirectlytotheUITableViewCell,theeditingcontrolswouldobscurethesubviews.Thecellcannotadjustitssizewhenenteringeditmode(itmustremainthewidthofthetableview),butthecontentViewcananddoes.

Page 355: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure12.2Tableviewcelllayoutinstandardandeditingmode

Page 356: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

CreatingItemCell

CreateanewSwiftfilenamedItemCell.InItemCell.swift,defineItemCellasaUITableViewCellsubclass.importFoundation

importUIKit

classItemCell:UITableViewCell{

}

TheeasiestwaytoconfigureaUITableViewCellsubclassisthroughastoryboard.InChapter10,yousawthatstoryboardsfortableviewcontrollershaveaPrototypeCellssection.ThisiswhereyouwilllayoutthecontentfortheItemCell.OpenMain.storyboardandselecttheUITableViewCellinthedocumentoutline.Openitsattributesinspector,changetheStyletoCustom,andchangetheIdentifiertoItemCell.Nowopenitsidentityinspector(the tab).IntheClassfield,enterItemCell(Figure12.3).Figure12.3Changingthecellclass

Changetheheightoftheprototypecelltobeabout65pointstall.YoucanchangeiteitheronthecanvasorbyselectingthetableviewcellandchangingtheRowHeightfromitssizeinspector.AnItemCellwilldisplaythreetextelements,sodragthreeUILabelobjectsontothecell.ConfigurethemasshowninFigure12.4.Makethetextofthebottomlabelaslightlysmallerfontinalightshadeofgray.Makesurethatthelabelsdonotoverlapatall.Figure12.4ItemCell’slayout

Addconstraintstothesethreelabelsasfollows.1. Selectthetop-leftlabelandopentheAutoLayoutAddNewConstraintsmenu.Selectthetop

andleftstrutandthenclickAdd2Constraints.2. Youwantthebottom-leftlabeltoalwaysbealignedwiththetop-leftlabel.Control-drag

fromthebottom-leftlabeltothetop-leftlabelandselectLeading.3. Withthebottom-leftlabelstillselected,opentheAddNewConstraintsmenu,selectthe

bottomstrut,andthenclickAdd1Constraint.

Page 357: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

4. SelecttherightlabelandControl-dragfromthislabeltoitssuperviewonitsrightside.SelectbothTrailingSpacetoContainerMarginandCenterVerticallyinContainer.

5. Selectthebottom-leftlabelandopenitssizeinspector.FindtheVerticalContentHuggingPriorityandloweritto250.LowertheVerticalContentCompressionResistancePriorityto749.YouwilllearnwhattheseAutoLayoutpropertiesdoinChapter13.

6. Yourframesmightbemisplaced,soselectthethreelabelsandclicktheUpdateFramesbutton.

Page 358: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 359: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

ExposingthePropertiesofItemCell

ForItemsViewControllertoconfigurethecontentofanItemCellintableView(_:cellForRowAt:),thecellmusthavepropertiesthatexposethethreelabels.ThesepropertieswillbesetthroughoutletconnectionsinMain.storyboard.Thenextstep,then,istocreateandconnectoutletsonItemCellforeachofitssubviews.OpenItemCell.swiftandaddthreepropertiesfortheoutlets.importUIKit

classItemCell:UITableViewCell{

@IBOutletvarnameLabel:UILabel!

@IBOutletvarserialNumberLabel:UILabel!

@IBOutletvarvalueLabel:UILabel!

}

YouaregoingtoconnecttheoutletsforthethreeviewstotheItemCell.Whenconnectingoutletsearlierinthebook,youControl-draggedfromviewcontrollerinthestoryboardtotheappropriateview.ButtheoutletsforItemCellarenotoutletsonacontroller.Theyareoutletsonaview:thecustomUITableViewCellsubclass.Therefore,toconnecttheoutletsforItemCell,youwillconnectthemtotheItemCell.OpenMain.storyboard.Control-clickontheItemCellinthedocumentoutlineandmakethethreeoutletconnectionsshowninFigure12.5.

Page 360: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure12.5Connectingtheoutlets

Page 361: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 362: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

UsingItemCell

Let’sgetyourcustomcellsonscreen.InItemsViewController’stableView(_:cellForRowAt:)method,youwilldequeueaninstanceofItemCellforeveryrowinthetable.NowthatyouareusingacustomUITableViewCellsubclass,thetableviewneedstoknowhowtalleachrowis.Thereareafewwaystoaccomplishthis,butthesimplestwayistosettherowHeightpropertyofthetableviewtoaconstantvalue.Youwillseeanotherwaylaterinthischapter.OpenItemsViewController.swiftandupdateviewDidLoad()tosettheheightofthetableviewcells.overridefuncviewDidLoad(){

super.viewDidLoad()

//Gettheheightofthestatusbar

letstatusBarHeight=UIApplication.shared.statusBarFrame.height

letinsets=UIEdgeInsets(top:statusBarHeight,left:0,bottom:0,right:0)

tableView.contentInset=insets

tableView.scrollIndicatorInsets=insets

tableView.rowHeight=65

}

NowthatyouhaveregisteredtheItemCellwiththetableview(usingtheprototypecellsinthestoryboard),youcanaskthetableviewtodequeueacellwiththeidentifier“ItemCell.”InItemsViewController.swift,modifytableView(_:cellForRowAt:).overridefunctableView(_tableView:UITableView,

cellForRowAtindexPath:NSIndexPath)->UITableViewCell{

//Getaneworrecycledcell

letcell=tableView.dequeueReusableCell(withIdentifier:"UITableViewCell",

for:indexPath)

letcell=tableView.dequeueReusableCell(withIdentifier:"ItemCell",

for:indexPath)as!ItemCell

//Setthetextonthecellwiththedescriptionoftheitem

//thatisatthenthindexofitems,wheren=rowthiscell

//willappearinonthetableview

letitem=itemStore.allItems[indexPath.row]

cell.textLabel?.text=item.name

cell.detailTextLabel?.text="$\(item.valueInDollars)"

//ConfigurethecellwiththeItem

cell.nameLabel.text=item.name

cell.serialNumberLabel.text=item.serialNumber

cell.valueLabel.text="$\(item.valueInDollars)"

returncell

}

Page 363: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

First,thereuseidentifierisupdatedtoreflectyournewsubclass.Thecodeattheendofthismethodisfairlyobvious–foreachlabelonthecell,setitstexttosomepropertyfromtheappropriateItem.Buildandruntheapplication.ThenewcellsnowloadwiththeirlabelspopulatedwiththevaluesfromeachItem.

Page 364: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 365: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

DynamicCellHeights

Currently,thecellshaveafixedheightof65points.Itismuchbettertoallowthecontentofthecelltodriveitsheight.Thatway,ifthecontenteverchanges,thetableviewcell’sheightcanchangeautomatically.Youcanachievethisgoal,asyouhaveprobablyguessed,withAutoLayout.TheUITableViewCellneedstohaveverticalconstraintsthatwillexactlydeterminetheheightofthecell.Currently,ItemCelldoesnothavesufficientconstraintsforthis.Youneedtoaddaconstraintbetweenthetwoleftlabelsthatfixestheverticalspacingbetweenthem.OpenMain.storyboard.Control-dragfromthenameLabeltotheserialNumberLabelandselectVerticalSpacing.NowopenItemsViewController.swiftandupdateviewDidLoad()totellthetableviewthatitshouldcomputethecellheightsbasedontheconstraints.overridefuncviewDidLoad(){

super.viewDidLoad()

//Gettheheightofthestatusbar

letstatusBarHeight=UIApplication.shared.statusBarFrame.height

letinsets=UIEdgeInsets(top:statusBarHeight,left:0,bottom:0,right:0)

tableView.contentInset=insets

tableView.scrollIndicatorInsets=insets

tableView.rowHeight=65

tableView.rowHeight=UITableViewAutomaticDimension

tableView.estimatedRowHeight=65

}

UITableViewAutomaticDimensionisthedefaultvalueforrowHeight,sowhileitisnotnecessarytoadd,itisusefulforunderstandingwhatisgoingon.SettingtheestimatedRowHeightpropertyonthetableviewcanimproveperformance.Insteadofaskingeachcellforitsheightwhenthetableviewloads,settingthispropertyallowssomeofthatperformancecosttobedeferreduntiltheuserstartsscrolling.Buildandruntheapplication.Theapplicationwilllookthesameasitdidbefore.Inthenextsection,youwilllearnaboutatechnologycalledDynamicTypethatwilltakeadvantageoftheautomaticallyresizingtableviewcells.

Page 366: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 367: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

DynamicType

Creatinganinterfacethatappealstoeveryonecanbedaunting.Somepeopleprefermorecompactinterfacessotheycanseemoreinformationatonce.Othersmightwanttobeabletoeasilyseeinformationataglance,orperhapstheyhavepooreyesight.Inshort:Peoplehavedifferentneeds.Gooddevelopersstrivetomakeappsthatmeetthoseneeds.DynamicTypeisatechnologythathelpsrealizethisgoalbyprovidingspecificallydesignedtextstylesthatareoptimizedforlegibility.UserscanselectoneofsevenpreferredtextsizesfromwithinApple’sSettingsapplication(plusafewadditionallargersizesfromwithintheAccessibilitysection),andappsthatsupportDynamicTypewillhavetheirfontsscaledappropriately.Inthissection,youwillupdateItemCelltosupportDynamicType.Figure12.6showstheapplicationrenderedatthesmallestandlargestuser-selectableDynamicTypesizes.Figure12.6ItemCellwithDynamicTypesupported

TheDynamicTypesystemiscenteredaroundtextstyles.Whenafontisrequestedforagiventextstyle,thesystemwillconsidertheuser ’spreferredtextsizeinassociationwiththetextstyletoreturnanappropriatelyconfiguredfont.Figure12.7showsthedifferenttextstyles.

Page 368: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure12.7Textstyles

OpenMain.storyboard.Let’supdatethelabelstousethetextstylesinsteadoffixedfonts.SelectthenameLabelandvalueLabelandopentheattributesinspector.ClickonthetexticontotherightofFont.ForFont,chooseTextStyles-Body(Figure12.8).RepeatthesamestepsfortheserialNumberLabel,choosingtheCaption1textstyle.

Page 369: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure12.8Changingthetextstyle

Nowlet’schangethepreferredfontsize.YoudothisthroughtheSettingsapplication.Buildandruntheapplication.Fromthesimulator ’sHardwaremenu,selectHome.Next,onthesimulator ’sHomescreen,opentheSettingsapplication.ChooseGeneral,thenAccessibility,andthenLargerText.(Onanactualdevice,thismenucanalsobeaccessedinSettingsviaDisplay&Brightness→TextSize.)Dragthesliderallthewaytothelefttosetthefontsizetothesmallestvalue(Figure12.9).

Page 370: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure12.9Textsizesettings

Buildandruntheapplication.(Ifyouswitchbacktotheapplication,eitherusingthetaskswitcherorthroughtheHomescreen,youwillnotseethechanges.Youwillfixthatinthenextsection.)Addsomeitemstothetableviewandyouwillseethenewsmallerfontsizesinaction.

Respondingtouserchanges

Whentheuserchangesthepreferredtextsizeandreturnstotheapplication,thetableviewwillgetreloaded.Unfortunately,thelabelswillnotknowaboutthenewpreferredtextsize.Tofixthis,youneedtohavethelabelsautomaticallyadjusttocontentsizechanges.OpenItemCell.swiftandoverrideawakeFromNib()tohavethelabelsautomaticallyadjust.

Page 371: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

overridefuncawakeFromNib(){

super.awakeFromNib()

nameLabel.adjustsFontForContentSizeCategory=true

serialNumberLabel.adjustsFontForContentSizeCategory=true

valueLabel.adjustsFontForContentSizeCategory=true

}

ThemethodawakeFromNib()getscalledonanobjectafteritisloadedfromanarchive,whichinthiscaseisthestoryboardfile.Bythetimethismethodiscalled,alloftheoutletshavevaluesandcanbeused.Buildandruntheapplicationandaddafewrows.GointoSettingsandchangethepreferredreadingsizetothelargestsize.Unlikebefore,youcannowswitchbacktoHomepwner,eitherbyopeningthetaskswitcherorthroughtheHomescreen,andthetableviewwillupdatetoreflectthenewpreferredtextsize.

Page 372: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 373: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

BronzeChallenge:CellColors

UpdatetheItemCelltodisplaythevalueInDollarsingreenifthevalueislessthan50andredifthevalueisgreaterthanorequalto50.

Page 374: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 375: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

13StackViews

YouhavebeenusingAutoLayoutthroughoutthisbooktocreateflexibleinterfacesthatscaleacrossdevicetypesandsizes.AutoLayoutisaverypowerfultechnology,butwiththatpowercomescomplexity.Layingoutaninterfacewelloftenneedsalotofconstraints,anditcanbedifficulttocreatedynamicinterfacesduetotheneedtoconstantlyaddandremoveconstraints.Often,aninterface(orasubsectionoftheinterface)canbelaidoutinalinearfashion.Thinkabouttheotherapplicationsyouwrote:TheQuizapplicationfromChapter1consistedoffoursubviewsthatwerelaidoutvertically.ThesameistruefortheWorldTrotterapplication;theConversionViewControllerhadaverticalinterfaceconsistingofatextfieldandafewlabels.Interfacesthathavealinearlayoutaregreatcandidatesforusingastackview.AstackviewisaninstanceofUIStackViewthatallowsyoutocreateaverticalorhorizontallayoutthatiseasytolayoutandmanagesmostoftheconstraintsthatyouwouldtypicallyhavetomanageyourself.Perhapsbestofall,youareabletoneststackviewswithinotherstackviews,whichallowsyoutocreatetrulyamazinginterfacesinafractionofthetime.Inthischapter,youaregoingtocontinueworkingonHomepwnertocreateaninterfacefordisplayingthedetailsofaspecificItem.Theinterfacethatyoucreatewillconsistofmultiplenestedstackviews,bothverticalandhorizontal(Figure13.1).Figure13.1Homepwnerwithstackviews

Page 376: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 377: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

UsingUIStackView

YouaregoingtocreateaninterfaceforeditingthedetailsofanItem.Youwillgetthebasicinterfaceworkinginthischapter,andthenyouwillfinishimplementingthedetailsinChapter14.Atthetoplevel,youwillhaveaverticalstackviewwithfourelementsdisplayingtheitem’sname,serialnumber,value,anddatecreated(Figure13.2).Figure13.2Verticalstackviewlayout

OpenyourHomepwnerprojectandthenopenMain.storyboard.DraganewViewControllerfromtheobjectlibraryontothecanvas.DragaVerticalStackViewfromtheobjectlibraryontotheviewfortheViewController.Addconstraintstothestackviewtopinittotheleadingandtrailingmargins,andpinthetopandbottomedgestobe8pointsfromthetopandbottomlayoutguides.NowdragfourinstancesofUILabelfromtheobjectlibraryontothestackview.Fromtoptobottom,givetheselabelsthetext“Name,”“Serial,”“Value,”and“DateCreated”(Figure13.3).

Page 378: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure13.3Labelsaddedtothestackview

Youcanseeaproblemrightaway:Thelabelsallhavearedborder(indicatinganAutoLayoutproblem)andthereisawarningthatsomeviewsareverticallyambiguous.Therearetwowaysyoucanfixthisissue:byusingAutoLayout,orbyusingapropertyonthestackview.Let’sworkthroughtheAutoLayoutsolutionfirstbecauseithighlightsanimportantaspectofAutoLayout.

Implicitconstraints

YoulearnedinChapter3thateveryviewhasanintrinsiccontentsize.Youalsolearnedthatifyoudonotspecifyconstraintsthatexplicitlydeterminethewidthorheight,theviewwillderiveitswidthorheightfromitsintrinsiccontentsize.Howdoesthiswork?Itdoesthisusingimplicitconstraintsderivedfromaview’scontenthuggingprioritiesanditscontentcompressionresistancepriorities.Aviewhasoneoftheseprioritiesforeachaxis:

horizontalcontenthuggingpriority

Page 379: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

verticalcontenthuggingpriorityhorizontalcontentcompressionresistancepriorityverticalcontentcompressionresistancepriority

Contenthuggingpriorities

Thecontenthuggingpriorityislikearubberbandthatisplacedaroundaview.Therubberbandmakestheviewnotwanttobebiggerthanitsintrinsiccontentsizeinthatdimension.Eachpriorityisassociatedwithavaluefrom0to1000.Avalueof1000meansthataviewcannotgetbiggerthanitsintrinsiccontentsizeonthatdimension.Let’slookatanexamplewithjustthehorizontaldimension.Sayyouhavetwolabelsnexttooneanotherwithconstraintsbothbetweenthetwoviewsandbetweeneachviewanditssuperview,asshowninFigure13.4.Figure13.4Twolabelssidebyside

Thisworksgreatuntilthesuperviewbecomeswider.Atthatpoint,whichlabelshouldbecomewider?Thefirstlabel,thesecondlabel,orboth?AsFigure13.5shows,theinterfaceiscurrentlyambiguous.Figure13.5Ambiguouslayout

Thisiswherethecontenthuggingprioritybecomesrelevant.Theviewwiththehighercontenthuggingpriorityistheonethatdoesnotstretch.Youcanthinkaboutthepriorityvalueasthe“strength”oftherubberband.Thehigherthepriorityvalue,thestrongertherubberband,andthemoreitwantstohugtoitsintrinsiccontentsize.

Page 380: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Contentcompressionresistancepriorities

Thecontentcompressionresistanceprioritiesdeterminehowmuchaviewresistsgettingsmallerthanitsintrinsiccontentsize.ConsiderthesametwolabelsfromFigure13.4.Whatwouldhappenifthesuperview’swidthdecreased?Oneofthelabelswouldneedtotruncateitstext(Figure13.6).Butwhichone?Figure13.6Compressedambiguouslayout

Theviewwiththegreatercontentcompressionresistancepriorityistheonethatwillresistcompressionand,therefore,nottruncateitstext.Withthisknowledge,youcannowfixtheproblemwiththestackview.SelecttheDateCreatedlabelandopenitssizeinspector.FindtheVerticalContentHuggingPriorityandloweritto249.Nowtheotherthreelabelshaveahighercontenthuggingpriority,sotheywillallhugtotheirintrinsiccontentheight.TheDateCreatedlabelwillstretchtofillintheremainingspace.

Stackviewdistribution

Let’stakealookatanotherwayofsolvingtheproblem.Stackviewshaveanumberofpropertiesthatdeterminehowtheircontentislaidout.Selectthestackview,eitheronthecanvasorusingthedocumentoutline.OpenitsattributesinspectorandfindthesectionatthetoplabeledStackView.OneofthepropertiesthatdetermineshowthecontentislaidoutistheDistributionproperty.CurrentlyitissettoFill,whichletstheviewslayouttheircontentbasedontheirintrinsiccontentsize.ChangethevaluetoFillEqually.Thiswillresizethelabelssothattheyallhavethesameheight,ignoringtheintrinsiccontentsize(Figure13.7).Besuretoreadthedocumentationfortheotherdistributionvaluesthatastackviewcanhave.

Page 381: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure13.7Stackviewsettofillequally

ChangetheDistributionofthestackviewbacktoFill;thisisthevalueyouwillwantgoingforwardinthischapter.

Nestedstackviews

Oneofthemostpowerfulfeaturesofstackviewsisthattheycanbenestedwithinoneanother.Youwillusethistonesthorizontalstackviewswithinthelargerverticalstackview.ThetopthreelabelswillhaveatextfieldnexttothemthatdisplaysthecorrespondingvaluefortheItemandwillalsoallowtheusertoeditthatvalue.SelecttheNamelabelonthecanvas.ClickthesecondiconfromtheleftintheAutoLayoutconstraintsmenu: .Thiswillembedtheselectedviewinastackview.

Page 382: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Selectthenewstackviewandopenitsattributesinspector.Thestackviewiscurrentlyaverticalstackview,butyouwantittobeahorizontalstackview.ChangetheAxistoHorizontal.NowdragaTextFieldfromtheobjectlibrarytotherightoftheNamelabel.Becauselabels,bydefault,haveagreatercontenthuggingprioritythantextfields,thelabelhugstoitsintrinsiccontentwidthandthetextfieldstretches.Thelabelandthetextfieldcurrentlyhavethesamecontentcompressionresistancepriorities,whichwouldresultinanambiguouslayoutifthetextfield’stextwastoolong.OpenthesizeinspectorforthetextfieldandsetitsHorizontalContentCompressionResistancePriorityto749.Thiswillensurethatthetextfield’stextwillbetruncatedifnecessary,ratherthanthelabel.

Stackviewspacing

Thelabelandtextfieldlookalittlesquishedbecausethereisnospacingbetweenthem.Stackviewsallowyoutocustomizethespacingbetweenitems.Selectthehorizontalstackviewandopenitsattributesinspector.ChangetheSpacingtobe8points.Noticethatthetextfieldshrinkstoaccommodatethespacing,becauseitislessresistanttocompressionthanthelabel.RepeatthesestepsfortheSerialandValuelabels:1. Selectthelabelandclickthe icon.2. Changethestackviewtobeahorizontalstackview.3. Dragatextfieldontothehorizontalstackviewandchangeitshorizontalcontent

compressionresistanceprioritytobe749.4. Updatethestackviewtohaveaspacingof8points.

Thereareacoupleofothertweaksyouwillwanttomaketotheinterface:Theverticalstackviewneedssomespacing.TheDateCreatedlabelshouldhaveacentertextalignment.AndtheName,Serial,andValuelabelsshouldbethesamewidth.Selecttheverticalstackview,openitsattributesinspector,andupdatetheSpacingtobe8points.ThenselecttheDateCreatedlabel,openitsattributesinspector,andchangetheAlignmenttobecentered.Thatsolvesthefirsttwoissues.Althoughstackviewssubstantiallyreducethenumberofconstraintsthatyouneedtoaddtoyourinterface,someconstraintsarestillimportant.Withtheinterfaceasis,thetextfieldsdonotalignontheirleadingedgeduetothedifferenceinthewidthsofthelabels.(ThedifferenceisnotverynoticeableinEnglish,butitbecomesmorepronouncedwhenlocalizedintootherlanguages.)Tosolvethis,youwilladdleadingedgeconstraintsbetweenthethreetextfields.Control-dragfromtheNametextfieldtotheSerialtextfieldandselectLeading.ThendothesamefortheSerialtextfieldandtheValuetextfield.ThecompletedinterfacewilllooklikeFigure13.8.

Page 383: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure13.8Finalstackviewinterface

Stackviewsallowyoutocreateveryrichinterfacesinafractionofthetimeitwouldtaketoconfigurethemmanuallyusingconstraints.Constraintsarestilladded,buttheyarebeingmanagedbythestackviewitselfinsteadofbyyou.Stackviewsallowyoutohaveverydynamicinterfacesatruntime.YoucanaddandremoveviewsfromstackviewsbyusingaddArrangedSubview(_:),insertArrangedSubview(_:at:),andremoveArrangedSubview(_:).Youcanalsotogglethehiddenpropertyonaviewinastackview.Thestackviewwillautomaticallylayoutitscontenttoreflectthatvalue.

Page 384: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 385: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Segues

MostiOSapplicationshaveanumberofviewcontrollersthatusersnavigatebetween.Storyboardsallowyoutosetuptheseinteractionsassegueswithouthavingtowritecode.Aseguemovesanotherviewcontroller ’sviewontothescreenandisrepresentedbyaninstanceofUIStoryboardSegue.Eachseguehasastyle,anactionitem,andanidentifier.Thestyleofaseguedetermineshowtheviewcontrollerwillbepresented.Theactionitemistheviewobjectinthestoryboardfilethattriggersthesegue,likeabutton,atableviewcell,orsomeotherUIControl.Theidentifierisusedtoprogrammaticallyaccessthesegue.Thisisusefulwhenyouwanttotriggeraseguethatdoesnotcomefromanactionitem,likeashakeorsomeotherinterfaceelementthatcannotbesetupinthestoryboardfile.Let’sstartwithashowsegue.Ashowseguedisplaysaviewcontrollerdependingonthecontextinwhichitisdisplayed.Theseguewillbebetweenthetableviewcontrollerandthenewviewcontroller.Theactionitemswillbethetableview’scells;tappingacellwillshowtheviewcontrollermodally.InMain.storyboard,selecttheItemCellprototypecellontheItemsViewController.Control-dragfromthecelltothenewviewcontrollerthatyousetupintheprevioussection.(MakesureyouareControl-draggingfromthecellandnotthetableview!)Ablackpanelwillappearthatliststhepossiblestylesforthissegue.SelectShowfromtheSelectionSeguesection(Figure13.9).Figure13.9Settingupashowsegue

Noticethearrowthatgoesfromthetableviewcontrollertothenewviewcontroller.Thisisasegue.Theiconinthecircletellsyouthatthissegueisashowsegue–eachseguehasauniqueicon.Buildandruntheapplication.Tapacellandthenewviewcontrollerwillslideupfromthe

Page 386: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

bottomofthescreen.(Slidingupfromthebottomisthedefaultbehaviorwhenpresentingaviewcontrollermodally.)Sofar,sogood!Buttherearetwoproblemsatthemoment:TheviewcontrollerisnotdisplayingtheinformationfortheItemthatwasselected,andthereisnowaytodismisstheviewcontrollertoreturntotheItemsViewController.Youwillfixthefirstissueinthenextsection,andyouwillfixthesecondissueinChapter14.

Page 387: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 388: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

HookingUptheContent

TodisplaytheinformationfortheselectedItem,youwillneedtocreateanewUIViewControllersubclass.CreateanewSwiftfileandnameitDetailViewController.OpenDetailViewController.swiftanddeclareanewUIViewControllersubclassnamedDetailViewController.importFoundation

importUIKit

classDetailViewController:UIViewController{

}

Becauseyouneedtobeabletoaccessthesubviewsyoucreatedduringruntime,DetailViewControllerneedsoutletsforthem.TheplanistoaddfournewoutletstoDetailViewControllerandthenmaketheconnections.Inpreviousexercises,youdidthisintwodistinctsteps:First,youaddedtheoutletsintheSwiftfile,thenyoumadeconnectionsinthestoryboardfile.Youcandobothatonceusingtheassistanteditor.WithDetailViewController.swiftopen,Option-clickonMain.storyboardintheprojectnavigator.ThiswillopenthefileintheassistanteditorrightnexttoDetailViewController.swift.(YoucantoggletheassistanteditorbyclickingthemiddlebuttonfromtheEditorcontrolatthetopoftheworkspace.TheshortcuttodisplaytheassistanteditorisCommand-Option-Return,andtheshortcuttoreturntothestandardeditorisCommand-Return.)Yourwindowhasbecomealittlecluttered.Let’smakesometemporaryspace.HidethenavigatorareabyclickingtheleftbuttonintheViewcontrolatthetopoftheworkspace(theshortcutforthisisCommand-0).Then,hidethedocumentoutlineinInterfaceBuilderbyclickingthetogglebuttoninthelower-leftcorneroftheeditor.YourworkspaceshouldnowlooklikeFigure13.10.

Page 389: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure13.10Layingouttheworkspace

Beforeyouconnecttheoutlets,youneedtotellthedetailinterfacethatitshouldbeassociatedwiththeDetailViewController.SelecttheViewControlleronthecanvasandopenitsidentityinspector.ChangetheClasstobeDetailViewController(Figure13.11).Figure13.11Settingtheviewcontrollerclass

ThethreeinstancesofUITextFieldandbottominstanceofUILabelwillbeoutletsinDetailViewController.Control-dragfromtheUITextFieldnexttotheNamelabeltothetopofDetailViewController.swift,asshowninFigure13.12.

Page 390: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure13.12Draggingfromstoryboardtosourcefile

Letgoandapop-upwindowwillappear.EnternameFieldintotheNamefield,makesuretheStorageissettoStrong,andclickConnect(Figure13.13).Figure13.13Autogeneratinganoutletandmakingaconnection

Thiswillcreatean@IBOutletpropertyoftypeUITextFieldnamednameFieldinDetailViewController.Inaddition,thisUITextFieldisalreadyconnectedtothenameFieldoutletoftheDetailViewController.YoucanverifythisbyControl-clickingontheDetailViewControllertoseetheconnections.AlsonoticethathoveringyourmouseabovethenameFieldconnectioninthepanelthatappearswillrevealtheUITextFieldthatyouconnected.Twobirds,onestone.

Page 391: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

CreatetheotherthreeoutletsthesamewayandnamethemasshowninFigure13.14.Figure13.14Connectiondiagram

Afteryoumaketheconnections,DetailViewController.swiftshouldlooklikethis:importUIKit

classDetailViewController:UIViewController{

@IBOutletvarnameField:UITextField!

@IBOutletvarserialNumberField:UITextField!

@IBOutletvarvalueField:UITextField!

@IBOutletvardateLabel:UILabel!

}

Ifyourfilelooksdifferent,thenyouroutletsarenotconnectedcorrectly.Fixanydisparitiesbetweenyourfileandthecodeshownaboveinthreesteps:First,gothroughtheControl-drag

Page 392: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

processandmakeconnectionsagainuntilyouhavethefourlinesshownaboveinyourDetailViewController.swift.Second,removeanywrongcode(likenon-propertymethoddeclarationsorproperties)thatgotcreated.Finally,checkforanybadconnectionsinthestoryboardfile–inMain.storyboard,Control-clickontheDetailViewController.Ifthereareyellowwarningsignsnexttoanyconnection,clickthexiconnexttothoseconnectionstodisconnectthem.Itisimportanttoensurethattherearenobadconnectionsinaninterfacefile.Abadconnectiontypicallyhappenswhenyouchangethenameofapropertybutdonotupdatetheconnectionintheinterfacefileorwhenyoucompletelyremoveapropertybutdonotremoveitfromtheinterfacefile.Eitherway,abadconnectionwillcauseyourapplicationtocrashwhentheinterfacefileisloaded.Withtheconnectionsmade,youcanclosetheassistanteditorandreturntoviewingjustDetailViewController.swift.DetailViewControllerwillholdontoareferencetotheItemthatisbeingdisplayed.Whenitsviewisloaded,youwillsetthetextoneachtextfieldtotheappropriatevaluefromtheIteminstance.InDetailViewController.swift,addapropertyforanIteminstanceandoverrideviewWillAppear(_:)tosetuptheinterface.classDetailViewController:UIViewController{

@IBOutletvarnameField:UITextField!

@IBOutletvarserialNumberField:UITextField!

@IBOutletvarvalueField:UITextField!

@IBOutletvardateLabel:UILabel!

varitem:Item!

overridefuncviewWillAppear(_animated:Bool){

super.viewWillAppear(animated)

nameField.text=item.name

serialNumberField.text=item.serialNumber

valueField.text="\(item.valueInDollars)"

dateLabel.text="\(item.dateCreated)"

}

}

Thisworks,butinsteadofusingstringinterpolationtoprintoutthevalueInDollarsanddateCreated,itwouldbebettertouseaformatter.YouusedaninstanceofNumberFormatterinChapter4.Youwilluseanotheronehere,aswellasaninstanceofDateFormattertoformatthedateCreated.AddaninstanceofNumberFormatterandDateFormattertotheDetailViewController.UsetheseformattersinviewWillAppear(_:)toformatthevalueInDollarsanddateCreated.varitem:Item!

letnumberFormatter:NumberFormatter={

letformatter=NumberFormatter()

Page 393: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

formatter.numberStyle=.decimal

formatter.minimumFractionDigits=2

formatter.maximumFractionDigits=2

returnformatter

}()

letdateFormatter:DateFormatter={

letformatter=DateFormatter()

formatter.dateStyle=.medium

formatter.timeStyle=.none

returnformatter

}()

overridefuncviewWillAppear(_animated:Bool){

super.viewWillAppear(animated)

nameField.text=item.name

serialNumberField.text=item.serialNumber

valueField.text="\(item.valueInDollars)"

dateLabel.text="\(item.dateCreated)"

valueField.text=

numberFormatter.string(from:NSNumber(value:item.valueInDollars))

dateLabel.text=dateFormatter.string(from:item.dateCreated)

}

Page 394: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 395: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

PassingDataAround

Whenarowinthetableviewistapped,youneedawayoftellingtheDetailViewControllerwhichitemwasselected.Wheneverasegueistriggered,theprepare(for:sender:)methodiscalledontheviewcontrollerinitiatingthesegue.Thismethodhastwoarguments:theUIStoryboardSegue,whichgivesyouinformationaboutwhichsegueishappening,andthesender,whichistheobjectthattriggeredthesegue(aUITableViewCelloraUIButton,forexample).TheUIStoryboardSeguegivesyouthreepiecesofinformation:thesourceviewcontroller(wherethesegueoriginates),thedestinationviewcontroller(wherethesegueends),andtheidentifierofthesegue.Theidentifierletsyoudifferentiatesegues.Let’sgivethesegueausefulidentifier.OpenMain.storyboardagain.Selecttheshowseguebyclickingonthearrowbetweenthetwoviewcontrollersandopentheattributesinspector.Fortheidentifier,entershowItem(Figure13.15).Figure13.15Segueidentifier

Withyoursegueidentified,youcannowpassyourIteminstancesaround.OpenItemsViewController.swiftandimplementprepare(for:sender:).overridefuncprepare(forsegue:UIStoryboardSegue,sender:Any?){

//Ifthetriggeredsegueisthe"showItem"segue

switchsegue.identifier{

case"showItem"?:

//Figureoutwhichrowwasjusttapped

ifletrow=tableView.indexPathForSelectedRow?.row{

//Gettheitemassociatedwiththisrowandpassitalong

letitem=itemStore.allItems[row]

letdetailViewController

=segue.destinationas!DetailViewController

detailViewController.item=item

}

default:

preconditionFailure("Unexpectedsegueidentifier.")

Page 396: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

}

}

YoulearnedaboutswitchstatementsinChapter2.Here,youareusingonetoswitchoverthepossiblesegueidentifiers.Becausethesegue’sidentifierisanoptionalString,youincludea?afterthecasepattern(i.e.,after"showItem").ThedefaultblockusesthepreconditionFailure(_:)functiontocatchanyunexpectedsegueidentifiersandcrashtheapplication.Thiswouldbethecaseiftheprogrammereitherforgottogiveasegueanidentifieroriftherewasatyposomewherewiththesegueidentifiers.Ineithercase,itistheprogrammer’smistake,andusingpreconditionFailure(_:)canhelpyouidentifytheseproblemssooner.Buildandruntheapplication.TaponarowandtheDetailViewControllerwillslideonscreen,displayingthedetailsforthatitem.(YouwillfixtheinabilitytogobacktotheItemsViewControllerinChapter14.)ManyprogrammersnewtoiOSstrugglewithhowdataispassedbetweenviewcontrollers.HavingallofthedataintherootviewcontrollerandpassingsubsetsofthatdatatothenextUIViewController(asyoudidinthischapter)isacleanandefficientwayofperformingthistask.

Page 397: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 398: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

BronzeChallenge:MoreStackViews

QuizandWorldTrotteraregoodcandidatesforusingstackviews.UpdatebothoftheseapplicationstouseUIStackView.

Page 399: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 400: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

14UINavigationController

InChapter5,youlearnedaboutUITabBarControllerandhowitallowsausertoaccessdifferentscreens.Atabbarcontrollerisgreatforscreensthatareindependentofeachother,butwhatifyouhavescreensthatproviderelatedinformation?Forexample,theSettingsapplicationhasmultiplerelatedscreensofinformation:alistofsettings(likeSounds),adetailedpageforeachsetting,andaselectionpageforeachdetail(Figure14.1).Thistypeofinterfaceiscalledadrill-downinterface.Figure14.1Drill-downinterfaceinSettings

Inthischapter,youwilluseaUINavigationControllertoaddadrill-downinterfacetoHomepwnerthatletstheuserseeandeditthedetailsofanItem.ThesedetailswillbepresentedbytheDetailViewControllerthatyoucreatedinChapter13(Figure14.2).

Page 401: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure14.2HomepwnerwithUINavigationController

Page 402: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

UINavigationController

AUINavigationControllermaintainsanarrayofviewcontrollerspresentingrelatedinformationinastack.WhenaUIViewControllerisontopofthestack,itsviewisvisible.WhenyouinitializeaninstanceofUINavigationController,yougiveitaUIViewController.ThisUIViewControllerisaddedtothenavigationcontroller ’sviewControllersarrayandbecomesthenavigationcontroller ’srootviewcontroller.Therootviewcontrollerisalwaysonthebottomofthestack.(Notethatwhilethisviewcontrollerisreferredtoasthenavigationcontroller ’s“rootviewcontroller,”UINavigationControllerdoesnothavearootViewControllerproperty.)MoreviewcontrollerscanbepushedontopoftheUINavigationController’sstackwhiletheapplicationisrunning.TheseviewcontrollersareaddedtotheendoftheviewControllersarraythatcorrespondstothetopofthestack.UINavigationController’stopViewControllerpropertykeepsareferencetotheviewcontrolleratthetopofthestack.Whenaviewcontrollerispushedontothestack,itsviewslidesonscreenfromtheright.Whenthestackispopped(i.e.,thelastitemisremoved),thetopviewcontrollerisremovedfromthestackanditsviewslidesofftotheright,exposingtheviewofthenextviewcontrolleronthestack,whichbecomesthetopviewcontroller.Figure14.3showsanavigationcontrollerwithtwoviewcontrollers.TheviewofthetopViewControlleriswhattheusersees.

Page 403: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure14.3UINavigationController’sstack

UINavigationControllerisasubclassofUIViewController,soithasaviewofitsown.Itsviewalwayshastwosubviews:aUINavigationBarandtheviewoftopViewController(Figure14.4).

Page 404: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure14.4AUINavigationController’sview

Inthischapter,youwilladdaUINavigationControllertotheHomepwnerapplicationandmaketheItemsViewControllertheUINavigationController’srootviewcontroller.TheDetailViewControllerwillbepushedontotheUINavigationController’sstackwhenanItemisselected.ThisviewcontrollerwillallowtheusertoviewandeditthepropertiesofanItemselectedfromthetableviewofItemsViewController.TheobjectdiagramfortheupdatedHomepwnerapplicationisshowninFigure14.5.

Page 405: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure14.5Homepwnerobjectdiagram

Thisapplicationisgettingfairlylarge,asyoucansee.Fortunately,viewcontrollersandUINavigationControllerknowhowtodealwiththistypeofcomplicatedobjectdiagram.WhenwritingiOSapplications,itisimportanttotreateachUIViewControllerasitsownlittleworld.ThestuffthathasalreadybeenimplementedinCocoaTouchwilldotheheavylifting.BeginbygivingHomepwneranavigationcontroller.ReopentheHomepwnerproject.TheonlyrequirementsforusingaUINavigationControllerarethatyougiveitarootviewcontrollerandadditsviewtothewindow.OpenMain.storyboardandselecttheItemsViewController.Then,fromtheEditormenu,chooseEmbedIn→NavigationController.ThiswillsettheItemsViewControllertobetherootviewcontrollerofaUINavigationController.ItwillalsoupdatethestoryboardtosettheNavigationControllerastheinitialviewcontroller.YourDetailViewControllerinterfacemayhavemisplacedviewsnowthatitiscontainedwithinanavigationcontroller.Ifitdoes,selectthestackviewandclicktheUpdateFramesbuttonintheAutoLayoutconstraintmenu.Buildandruntheapplicationand…theapplicationcrashes.Whatishappening?You

Page 406: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

previouslycreatedacontractwiththeAppDelegatethataninstanceofItemsViewControllerwouldbetherootViewControllerofthewindow:letitemsController=window!.rootViewControlleras!ItemsViewController

YouhavenowbrokenthiscontractbyembeddingtheItemsViewControllerinaUINavigationController.Youneedtoupdatethecontract.OpenAppDelegate.swiftandupdateapplication(_:didFinishLaunchingWithOptions:)toreflectthenewviewcontrollerhierarchy.funcapplication(_application:UIApplication,didFinishLaunchingWithOptions

launchOptions:[UIApplicationLaunchOptionsKey:Any]?)->Bool{

//Overridepointforcustomizationafterapplicationlaunch.

//CreateanItemStore

letitemStore=ItemStore()

//AccesstheItemsViewControllerandsetitsitemstore

letitemsController=window!.rootViewControlleras!ItemsViewController

letnavController=window!.rootViewControlleras!UINavigationController

letitemsController=navController.topViewControlleras!ItemsViewController

itemsController.itemStore=itemStore

returntrue

}

Buildandruntheapplicationagain.Homepwnerworksagainandhasaverynice,iftotallyempty,UINavigationBaratthetopofthescreen(Figure14.6).Figure14.6Homepwnerwithanemptynavigationbar

NoticehowthescreenadjustedtofitItemsViewController’sviewaswellasthenewnavigationbar.UINavigationControllerdidthisforyou:WhiletheviewoftheItemsViewControlleractuallyunderlapsthenavigationbar,UINavigationControlleraddedpaddingtothetopsothateverythingfitsnicely.Thisisbecausethetoplayoutguidefortheviewcontrollerisadjusted,alongwithanyviewsconstrainedtothetoplayoutguide–likethestackview.

Page 407: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 408: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

NavigatingwithUINavigationController

Withtheapplicationstillrunning,createanewitemandselectthatrowfromtheUITableView.NotonlyareyoutakentoDetailViewController’sview,butyoualsogetafreeanimationandaBackbuttonintheUINavigationBar.TapthisbuttontogetbacktoItemsViewController.NoticethatyoudidnothavetochangetheshowseguethatyoucreatedinChapter13togetthisbehavior.Asmentionedinthatchapter,theshowseguepresentsthedestinationviewcontrollerinawaythatmakessensegiventhesurroundingcontext.Whenashowsegueistriggeredfromaviewcontrollerembeddedwithinanavigationcontroller,thedestinationviewcontrollerispushedontothenavigationcontroller ’sviewcontrollerstack.BecausetheUINavigationController’sstackisanarray,itwilltakeownershipofanyviewcontrolleraddedtoit.Thus,theDetailViewControllerisownedonlybytheUINavigationControlleraftertheseguefinishes.Whenthestackispopped,theDetailViewControllerisdestroyed.Thenexttimearowistapped,anewinstanceofDetailViewControlleriscreated.Havingaviewcontrollerpushthenextviewcontrollerisacommonpattern.Therootviewcontrollertypicallycreatesthenextviewcontroller,andthenextviewcontrollercreatestheoneafterthat,andsoon.Someapplicationsmayhaveviewcontrollersthatcanpushdifferentviewcontrollersdependingonuserinput.Forexample,thePhotosapppushesavideoviewcontrolleroranimageviewcontrollerontothenavigationstackdependingonwhattypeofmediaisselected.NoticethatthedetailviewforanitemcontainstheinformationfortheselectedItem.However,whileyoucaneditthisdata,theUITableViewwillnotreflectthosechangeswhenyoureturntoit.Tofixthisproblem,youneedtoimplementcodetoupdatethepropertiesoftheItembeingedited.Inthenextsection,youwillseewhentodothis.

Page 409: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 410: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

AppearingandDisappearingViews

WheneveraUINavigationControllerisabouttoswapviews,itcallstwomethods:viewWillDisappear(_:)andviewWillAppear(_:).TheUIViewControllerthatisabouttobepoppedoffthestackhasviewWillDisappear(_:)called.TheUIViewControllerthatwillthenbeontopofthestackhasviewWillAppear(_:)calledonit.Toholdontochangesinthedata,whenaDetailViewControllerispoppedoffthestackyouwillsetthepropertiesofitsitemtothecontentsofthetextfields.Whenimplementingthesemethodsforviewsappearinganddisappearing,itisimportanttocallthesuperclass’simplementation–itmighthavesomeworktodoandneedstobegiventhechancetodoit.InDetailViewController.swift,implementviewWillDisappear(_:).overridefuncviewWillDisappear(_animated:Bool){

super.viewWillDisappear(animated)

//"Save"changestoitem

item.name=nameField.text??""

item.serialNumber=serialNumberField.text

ifletvalueText=valueField.text,

letvalue=numberFormatter.number(from:valueText){

item.valueInDollars=value.intValue

}else{

item.valueInDollars=0

}

}

NowthevaluesoftheItemwillbeupdatedwhentheusertapstheBackbuttonontheUINavigationBar.WhenItemsViewControllerappearsbackonthescreen,themethodviewWillAppear(_:)iscalled.TakethisopportunitytoreloadtheUITableViewsotheusercanimmediatelyseethechanges.InItemsViewController.swift,overrideviewWillAppear(_:)toreloadthetableview.overridefuncviewWillAppear(_animated:Bool){

super.viewWillAppear(animated)

tableView.reloadData()

}

Buildandrunyourapplicationonceagain.Nowyoucanmovebackandforthbetweentheviewcontrollersthatyoucreatedandchangethedatawithease.

Page 411: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 412: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

DismissingtheKeyboard

Runtheapplication,addandselectanitem,andtouchthetextfieldwiththeitem’sname.Whenyoutouchthetextfield,akeyboardappearsonscreen(Figure14.7),asyousawinyourWorldTrotterappinChapter4.(Ifyouareusingthesimulatorandthekeyboarddoesnotappear,rememberthatyoucanpressCommand-Ktotogglethedevicekeyboard.)Figure14.7Keyboardappearswhenatextfieldistouched

TheappearanceofthekeyboardinresponsetoatouchisbuiltintotheUITextFieldclassaswellasUITextView,soyoudonothavetodoanythingextraforthekeyboardtoappear.However,attimesyouwillwanttomakesurethekeyboardbehavesasyouwantitto.Forexample,noticethatthekeyboardcoversmorethanathirdofthescreen.Rightnow,itdoesnotobscureanything,butsoonyouwilladdmoredetailsthatextendtothebottomofthescreen,anduserswillwantawaytohidethekeyboardwhenitisnotneeded.Inthissection,youaregoingtogivetheusertwowaystodismissthekeyboard:pressingthekeyboard’s

Page 413: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Returnkey,andtappinganywhereelseonthedetailviewcontroller ’sview.Butfirst,let’slookatthecombinationofeventsthatmaketexteditingpossible.

Eventhandlingbasics

Whenyoutouchaview,aneventiscreated.Thisevent(knownasa“touchevent”)istiedtoaspecificlocationintheviewcontroller ’sview.Thatlocationdetermineswhichviewinthehierarchythetoucheventisdeliveredto.Forexample,whenyoutapaUIButtonwithinitsbounds,itwillreceivethetoucheventandrespondinbutton-likefashion–bycallingtheactionmethodonitstarget.Itisperfectlyreasonabletoexpectthatwhenaviewinyourapplicationistouched,thatviewreceivesatouchevent,anditmaychoosetoreacttothateventorignoreit.However,viewsinyourapplicationcanalsorespondtoeventswithoutbeingtouched.Agoodexampleofthisisashake.Ifyoushakethedevicewithyourapplicationrunning,oneofyourviewsonthescreencanrespond.Butwhichone?Anotherinterestingcaseisrespondingtothekeyboard.DetailViewController’sviewcontainsthreeUITextFields.Whichonewillreceivethetextwhentheusertypes?Forboththeshakeandkeyboardevents,thereisnoeventlocationwithinyourviewhierarchytodeterminewhichviewwillreceivetheevent,soanothermechanismmustbeused.Thismechanismisthefirstresponderstatus.Manyviewsandcontrolscanbeafirstresponderwithinyourviewhierarchy–butonlyoneatatime.Thinkofitasaflagthatcanbepassedamongviews.Whicheverviewholdstheflagwillreceivetheshakeorkeyboardevent.InstancesofUITextFieldandUITextViewhaveanuncommonresponsetotouchevents.Whentouched,atextfieldoratextviewbecomesthefirstresponder,whichinturntriggersthesystemtoputthekeyboardonscreenandsendthekeyboardeventstothetextfieldorview.Thekeyboardandthetextfieldorviewhavenodirectconnection,buttheyworktogetherthroughthefirstresponderstatus.Thisisaneatwaytoensurethatthekeyboardinputisdeliveredtothecorrecttextfield.TheconceptofafirstresponderispartofthebroadertopicofeventhandlinginCocoaTouchprogrammingthatincludestheUIResponderclassandtheresponderchain.YouwilllearnmoreaboutthemwhenyouhandletoucheventsinChapter18,andyoucanalsovisitApple’sEventHandlingGuideforiOSformoreinformation.

DismissingbypressingtheReturnkey

Nowlet’sgetbacktoallowinguserstodismissthekeyboard.Ifyoutouchanothertextfieldintheapplication,thattextfieldwillbecomethefirstresponder,andthekeyboardwillstayonscreen.Thekeyboardwillonlygiveupandgoawaywhennotextfield(ortextview)isthefirstresponder.Todismissthekeyboard,then,youcallresignFirstResponder()onthetextfieldthatisthefirstresponder.

Page 414: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

TohavethetextfieldresigninresponsetotheReturnkeybeingpressed,youaregoingtoimplementtheUITextFieldDelegatemethodtextFieldShouldReturn(_:).ThismethodiscalledwhenevertheReturnkeyispressed.First,inDetailViewController.swift,haveDetailViewControllerconformtotheUITextFieldDelegateprotocol.classDetailViewController:UIViewController,UITextFieldDelegate{

Next,implementtextFieldShouldReturn(_:)tocallresignFirstResponder()onthetextfieldthatispassedin.functextFieldShouldReturn(_textField:UITextField)->Bool{

textField.resignFirstResponder()

returntrue

}

Finally,openMain.storyboardandconnectthedelegatepropertyofeachtextfieldtotheDetailViewController(Figure14.8).(Control-dragfromeachUITextFieldtotheDetailViewControllerandchoosedelegate.)Figure14.8Connectingthedelegatepropertyofatextfield

Buildandruntheapplication.TapatextfieldandthenpresstheReturnkeyonthekeyboard.Thekeyboardwilldisappear.Togetthekeyboardback,touchanytextfield.

Dismissingbytappingelsewhere

ItwouldbestylishtoalsodismissthekeyboardiftheusertapsanywhereelseonDetailViewController’sview.Todothis,youaregoingtouseagesturerecognizerwhentheviewistapped,justasyoudidintheWorldTrotterapp.Intheactionmethod,youwillcallresignFirstResponder()onthetextfield.OpenMain.storyboardandfindTapGestureRecognizerintheobjectlibrary.DragthisobjectontothebackgroundviewfortheDetailViewController.Youwillseeareferencetothisgesture

Page 415: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

recognizerinthescenedock.Intheprojectnavigator,Option-clickDetailViewController.swifttoopenitintheassistanteditor.Control-dragfromthetapgesturerecognizerinthestoryboardtotheimplementationofDetailViewController.Inthepop-upthatappears,selectActionfromtheConnectionmenu.NametheactionbackgroundTapped.FortheType,chooseUITapGestureRecognizer(Figure14.9).Figure14.9ConfiguringaUITapGestureRecognizeraction

ClickConnectandthestubfortheactionmethodwillappearinDetailViewController.swift.UpdatethemethodtocallendEditing(_:)ontheviewofDetailViewController.@IBActionfuncbackgroundTapped(_sender:UITapGestureRecognizer){

view.endEditing(true)

}

CallingendEditing(_:)isaconvenientwaytodismissthekeyboardwithouthavingtoknow(orcare)whichtextfieldisthefirstresponder.Whentheviewgetsthiscall,itcheckstoseeifanytextfieldinitshierarchyisthefirstresponder.Ifso,thenresignFirstResponder()iscalledonthatparticularview.Buildandrunyourapplication.Taponatextfieldtoshowthekeyboard.Tapontheviewoutsideofatextfieldandthekeyboardwilldisappear.Thereisonefinalcasewhereyouneedtodismissthekeyboard.WhentheusertapstheBackbutton,viewWillDisappear(_:)iscalledontheDetailViewControllerbeforeitispoppedoffthestack,andthekeyboarddisappearsinstantly,withnoanimation.Todismissthekeyboardmoresmoothly,updatetheimplementationofviewWillDisappear(_:)inDetailViewController.swifttocallendEditing(_:).overridefuncviewWillDisappear(_animated:Bool){

super.viewWillDisappear(animated)

//Clearfirstresponder

view.endEditing(true)

//"Save"changestoitem

item.name=nameField.text??""

item.serialNumber=serialNumberField.text

ifletvalueText=valueField.text,

letvalue=numberFormatter.number(from:valueText){

Page 416: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

item.valueInDollars=value.integerValue

}else{

item.valueInDollars=0

}

}

Page 417: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 418: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

UINavigationBar

Inthissection,youaregoingtogivetheUINavigationBaradescriptivetitlefortheUIViewControllerthatiscurrentlyontopoftheUINavigationController’sstack.EveryUIViewControllerhasanavigationItempropertyoftypeUINavigationItem.However,unlikeUINavigationBar,UINavigationItemisnotasubclassofUIView,soitcannotappearonthescreen.Instead,thenavigationitemsuppliesthenavigationbarwiththecontentitneedstodraw.WhenaUIViewControllercomestothetopofaUINavigationController’sstack,theUINavigationBarusestheUIViewController’snavigationItemtoconfigureitself,asshowninFigure14.10.Figure14.10UINavigationItem

Bydefault,aUINavigationItemisempty.Atthemostbasiclevel,aUINavigationItemhasasimpletitlestring.WhenaUIViewControllerismovedtothetopofthenavigationstackanditsnavigationItemhasavalidstringforitstitleproperty,thenavigationbarwilldisplaythatstring(Figure14.11).Figure14.11UINavigationItemwithtitle

ThetitlefortheItemsViewControllerwillalwaysremainthesame,soyoucansetthetitleofitsnavigationitemwithinthestoryboarditself.OpenMain.storyboard.Double-clickonthecenterofthenavigationbarabovetheItemsViewControllertoedititstitle.Giveitatitleof“Homepwner”(Figure14.12).

Page 419: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure14.12Settingthetitleinastoryboard

Buildandruntheapplication.NoticethestringHomepwneronthenavigationbar.Createandtaponarowandnoticethatthenavigationbarnolongerhasatitle.ItwouldbenicetohavetheDetailViewController’snavigationitemtitlebethenameoftheItemitisdisplaying.BecausethetitlewilldependontheItemthatisbeingdisplayed,youneedtosetthetitleofthenavigationItemdynamicallyincode.InDetailViewController.swift,addapropertyobservertotheitempropertythatupdatesthetitleofthenavigationItem.varitem:Item!{

didSet{

navigationItem.title=item.name

}

}

Buildandruntheapplication.CreateandtaparowandyouwillseethatthetitleofthenavigationbaristhenameoftheItemyouselected.Anavigationitemcanholdmorethanjustatitlestring,asshowninFigure14.13.TherearethreecustomizableareasforeachUINavigationItem:aleftBarButtonItem,arightBarButtonItem,andatitleView.TheleftandrightbarbuttonitemsarereferencestoinstancesofUIBarButtonItem,whichcontaintheinformationforabuttonthatcanonlybedisplayedonaUINavigationBaroraUIToolbar.Figure14.13UINavigationItemwitheverything

RecallthatUINavigationItemisnotasubclassofUIView.Instead,UINavigationItemencapsulatesinformationthatUINavigationBarusestoconfigureitself.Similarly,UIBarButtonItemisnotaview,butholdstheinformationabouthowasinglebuttonontheUINavigationBarshouldbedisplayed.(AUIToolbaralsouses

Page 420: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

instancesofUIBarButtonItemtoconfigureitself.)ThethirdcustomizableareaofaUINavigationItemisitstitleView.YoucaneitheruseabasicstringasthetitleorhaveasubclassofUIViewsitinthecenterofthenavigationitem.Youcannothaveboth.Ifitsuitsthecontextofaspecificviewcontrollertohaveacustomview(likeasegmentedcontroloratextfield,forexample),youwouldsetthetitleViewofthenavigationitemtothatcustomview.Figure14.13showsanexamplefromthebuilt-inMapsapplicationofaUINavigationItemwithacustomviewasitstitleView.Typically,however,atitlestringissufficient.

Addingbuttonstothenavigationbar

Inthissection,youaregoingtoreplacethetwobuttonsthatareinthetable’sheaderviewwithtwobarbuttonitemsthatwillappearintheUINavigationBarwhentheItemsViewControllerisontopofthestack.Abarbuttonitemhasatarget-actionpairthatworkslikeUIControl’starget-actionmechanism:Whentapped,itsendstheactionmessagetothetarget.First,let’sworkonabarbuttonitemforaddingnewitems.ThisbuttonwillsitontherightsideofthenavigationbarwhentheItemsViewControllerisontopofthestack.Whentapped,itwilladdanewItem.Beforeyouupdatethestoryboard,youneedtochangethemethodsignatureforaddNewItem(_:).CurrentlythismethodistriggeredbyaUIButton.NowthatyouarechangingthesendertoaUIBarButtonItem,youneedtoupdatethesignature.InItemsViewController.swift,updatethemethodsignatureforaddNewItem(_:).@IBActionfuncaddNewItem(_sender:UIButton){

@IBActionfuncaddNewItem(_sender:UIBarButtonItem){

...

}

NowopenMain.storyboardandthenopentheobjectlibrary.DragaBarButtonItemtotherightsideofItemsViewController’snavigationbar.Selectthisbarbuttonitemandopenitsattributesinspector.ChangetheSystemItemtoAdd(Figure14.14).

Page 421: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure14.14Systembarbuttonitem

Control-dragfromthisbarbuttonitemtotheItemsViewControllerandselectaddNewItem:(Figure14.15).Figure14.15ConnectingtheaddNewItem:action

Buildandruntheapplication.Tapthe+buttonandanewrowwillappearinthetable.Nowlet’sreplacetheEditbutton.Viewcontrollersexposeabarbuttonitemthatwillautomaticallytoggletheireditingmode.ThereisnowaytoaccessthisthroughInterfaceBuilder,soyouwillneedtoaddthisbarbuttonitemprogrammatically.InItemsViewController.swift,overridetheinit(coder:)methodtosettheleftbarbuttonitem.requiredinit?(coderaDecoder:NSCoder){

Page 422: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

super.init(coder:aDecoder)

navigationItem.leftBarButtonItem=editButtonItem

}

Buildandruntheapplication,addsomeitems,andtaptheEditbutton.TheUITableViewenterseditingmode!TheeditButtonItempropertycreatesaUIBarButtonItemwiththetitleEdit.Evenbetter,thisbuttoncomeswithatarget-actionpair:ItcallsthemethodsetEditing(_:animated:)onitsUIViewControllerwhentapped.OpenMain.storyboard.NowthatHomepwnerhasafullyfunctionalnavigationbar,youcangetridoftheheaderviewandtheassociatedcode.SelecttheheaderviewonthetableviewandpressDelete.Also,theUINavigationControllerwillhandleupdatingtheinsetsforthetableview.InItemsViewController.swift,deletethefollowingcode.overridefuncviewDidLoad(){

super.viewDidLoad()

//Gettheheightofthestatusbar

letstatusBarHeight=UIApplication.shared.statusBarFrame.height

letinsets=UIEdgeInsets(top:statusBarHeight,left:0,bottom:0,right:0)

tableView.contentInset=insets

tableView.scrollIndicatorInsets=insets

tableView.rowHeight=UITableViewAutomaticDimension

tableView.estimatedRowHeight=65

}

Finally,removethetoggleEditingMode(_:)method.@IBActionfunctoggleEditingMode(_sender:UIButton){

//Ifyouarecurrentlyineditingmode...

ifisEditing{

//Changetextofbuttontoinformuserofstate

sender.setTitle("Edit",for:.normal)

//Turnoffeditingmode

setEditing(false,animated:true)

}else{

//Changetextofbuttontoinformuserofstate

sender.setTitle("Done",for:.normal)

//Entereditingmode

setEditing(true,animated:true)

}

}

Buildandrunagain.TheoldEditandAddbuttonsaregone,leavingyouwithalovelyUINavigationBar(Figure14.16).

Page 423: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure14.16Homepwnerwithnavigationbar

Page 424: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 425: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

BronzeChallenge:DisplayingaNumberPad

ThekeyboardfortheUITextFieldthatdisplaysanItem’svalueInDollarsisaQWERTYkeyboard.Itwouldbebetterifitwereanumberpad.ChangetheKeyboardTypeofthatUITextFieldtotheNumberPad.(Hint:Youcandothisinthestoryboardfileusingtheattributesinspector.)

Page 426: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 427: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

SilverChallenge:ACustomUITextField

MakeasubclassofUITextFieldandoverridethebecomeFirstResponder()andresignFirstResponder()methods(inheritedfromUIResponder)sothatitsborderstylechangeswhenitisthefirstresponder.YoucanusetheborderStylepropertyofUITextFieldtoaccomplishthis.UseyoursubclassforthetextfieldsinDetailViewController.

Page 428: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 429: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

GoldChallenge:PushingMoreViewControllers

Currently,instancesofItemcannothavetheirdateCreatedpropertychanged.ChangeItemsothattheycan,andthenaddabuttonunderneaththedateLabelinDetailViewControllerwiththetitle“ChangeDate.”Whenthisbuttonistapped,pushanotherviewcontrollerinstanceontothenavigationstack.ThisviewcontrollershouldhaveaUIDatePickerinstancethatmodifiesthedateCreatedpropertyoftheselectedItem.

Page 430: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 431: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

15Camera

Inthischapter,youaregoingtoaddphotostotheHomepwnerapplication.YouwillpresentaUIImagePickerControllersothattheusercantakeandsaveapictureofeachitem.TheimagewillthenbeassociatedwithanIteminstanceandviewableintheitem’sdetailview(Figure15.1).Figure15.1Homepwnerwithcameraaddition

Imagestendtobeverylarge,soitisagoodideatostoreimagesseparatelyfromotherdata.Thus,youaregoingtocreateasecondstoreforimages.ImageStorewillfetchandcacheimagesastheyareneeded.

Page 432: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

DisplayingImagesandUIImageView

YourfirststepistohavetheDetailViewControllergetanddisplayanimage.AneasywaytodisplayanimageistoputaninstanceofUIImageViewonthescreen.OpenHomepwner.xcodeprojandMain.storyboard.ThendraganinstanceofUIImageViewontotheviewatthebottomofthestackview.Selecttheimageviewandopenitssizeinspector.Youwanttheverticalcontenthuggingandcontentcompressionresistanceprioritiesfortheimageviewtobelowerthanthoseoftheotherviews.ChangetheVerticalContentHuggingPrioritytobe248andtheVerticalContentCompressionResistancePrioritytobe749.YourlayoutwilllooklikeFigure15.2.Figure15.2UIImageViewonDetailViewController’sview

AUIImageViewdisplaysanimageaccordingtotheimageview’scontentModeproperty.Thispropertydetermineswheretopositionandhowtoresizethecontentwithinthe

Page 433: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

imageview’sframe.UIImageView’sdefaultvalueforcontentModeisUIViewContentMode.scaleToFill,whichadjuststheimagetoexactlymatchtheboundsoftheimageview.Ifyoukeepthedefault,animagetakenbythecamerawillbescaledtofitintothesquareUIImageView.Tomaintaintheimage’saspectratio,youhavetoupdatecontentMode.WiththeUIImageViewselected,opentheattributesinspector.FindtheContentModeattributeandchangeittoAspectFit(Figure15.3).Youwillnotseeachangeonthestoryboard,butnowimageswillberesizedtofitwithintheboundsoftheUIImageView.Figure15.3ChangingUIImageView’smodetoAspectFit

Next,Option-clickDetailViewController.swiftintheprojectnavigatortoopenitintheassistanteditor.Control-dragfromtheUIImageViewtothetopofDetailViewController.swift.NametheoutletimageViewandmakesurethestoragetypeisStrong.ClickConnect(Figure15.4).Figure15.4CreatingtheimageViewoutlet

ThetopofDetailViewController.swiftshouldnowlooklikethis:classDetailViewController:UIViewController,UITextFieldDelegate{

@IBOutletvarnameField:UITextField!

Page 434: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

@IBOutletvarserialNumberField:UITextField!

@IBOutletvarvalueField:UITextField!

@IBOutletvardateLabel:UILabel!

@IBOutletvarimageView:UIImageView!

Addingacamerabutton

Nowyouneedabuttontoinitiatethephoto-takingprocess.YouwillcreateaninstanceofUIToolbarandplaceitatthebottomofDetailViewController’sview.InMain.storyboard,pressCommand-Returntoclosetheassistanteditorandgiveyourselfmoreroomtoworkinthestoryboard.Youaregoingtoneedtotemporarilybreakyourinterfacetoaddthetoolbartotheinterface.SelectthebottomconstraintforthestackviewandpressDeletetoremoveit.Youneedtomakeroomforthetoolbaronthebottom.AsofXcode8.1,itisdifficulttoresizethestackview.Soinstead,dragthestackviewupabit(Figure15.5).Theviewwillbemisplacedfornow,butyouwillfixthisshortly.Figure15.5Movingthestackviewoutoftheway

Page 435: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Nowdragatoolbarfromtheobjectlibraryontothebottomoftheview.SelectthetoolbarandopentheAutoLayoutAddNewConstraintsmenu.ConfiguretheconstraintsexactlyasshowninFigure15.6andthenclickAdd5Constraints.Becauseyouchosetheoptiontoupdateframes,thestackviewisrepositionedtoitscorrectlocation.

Page 436: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure15.6Toolbarconstraints

AUIToolbarworksalotlikeaUINavigationBar–youcanaddinstancesofUIBarButtonItemtoit.However,whereanavigationbarhastwoslotsforbarbuttonitems,atoolbarhasanarrayofbarbuttonitems.Youcanplaceasmanybarbuttonitemsinatoolbarascanfitonthescreen.Bydefault,anewinstanceofUIToolbarthatiscreatedinaninterfacefilecomeswithoneUIBarButtonItem.Selectthisbarbuttonitemandopentheattributesinspector.ChangetheSystemItemtoCamera,andtheitemwillshowacameraicon(Figure15.7).

Page 437: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure15.7UIToolbarwithcamerabarbuttonitem

Buildandruntheapplicationandnavigatetoanitem’sdetailstoseethetoolbarwithitscamerabarbuttonitem.Youhavenotconnectedthecamerabuttontoanactionyet,sotappingonitwillnotdoanything.Thecamerabuttonneedsatargetandanaction.WithMain.storyboardstillopen,Option-clickDetailViewController.swiftintheprojectnavigatortoreopenitintheassistanteditor.InMain.storyboard,selectthecamerabuttonbyfirstclickingonthetoolbarandthenthebuttonitself.Control-dragfromtheselectedbuttontoDetailViewController.swift.IntheConnectionpop-upmenu,selectActionastheconnectiontype,nameittakePicture,selectUIBarButtonItemasthetype,andclickConnect(Figure15.8).

Page 438: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure15.8Creatinganaction

Ifyoumadeanymistakeswhilemakingthisconnection,youwillneedtoopenMain.storyboardanddisconnectanybadconnections.(Lookforyellowwarningsignsintheconnectionsinspector.)

Page 439: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 440: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

TakingPicturesandUIImagePickerController

InthetakePicture(_:)method,youwillinstantiateaUIImagePickerControllerandpresentitonthescreen.WhencreatinganinstanceofUIImagePickerController,youmustsetitssourceTypepropertyandassignitadelegate.Becausethereisset-upworkneededfortheimagepickercontroller,youneedtocreateandpresentitprogrammaticallyinsteadofthroughthestoryboard.

Settingtheimagepicker’ssourceType

ThesourceTypeconstanttellstheimagepickerwheretogetimages.Ithasthreepossiblevalues:UIImagePickerControllerSourceType.camera

Allowstheusertotakeanewphoto.UIImagePickerControllerSourceType.photoLibrary

Promptstheusertoselectanalbumandthenaphotofromthatalbum.UIImagePickerControllerSourceType.savedPhotosAlbum

Promptstheusertochoosefromthemostrecentlytakenphotos.Figure15.9ExamplesofthethreesourceTypes

Thefirstsourcetype,.camera,willnotworkonadevicethatdoesnothaveacamera.So

Page 441: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

beforeusingthistype,youhavetocheckforacamerabycallingthemethodisSourceTypeAvailable(_:)ontheUIImagePickerControllerclass:classfuncisSourceTypeAvailable(_type:UIImagePickerControllerSourceType)->Bool

CallingthismethodreturnsaBooleanvalueforwhetherthedevicesupportsthepassed-insourcetype.InDetailViewController.swift,findthestubfortakePicture(_:).AddthefollowingcodetocreatetheimagepickerandsetitssourceType.@IBActionfunctakePicture(_sender:UIBarButtonItem){

letimagePicker=UIImagePickerController()

//Ifthedevicehasacamera,takeapicture;otherwise,

//justpickfromphotolibrary

ifUIImagePickerController.isSourceTypeAvailable(.camera){

imagePicker.sourceType=.camera

}else{

imagePicker.sourceType=.photoLibrary

}

}

Settingtheimagepicker’sdelegate

Inadditiontoasourcetype,theUIImagePickerControllerinstanceneedsadelegate.WhentheuserselectsanimagefromtheUIImagePickerController’sinterface,thedelegateissentthemessageimagePickerController(_:didFinishPickingMediaWithInfo:).(Iftheusertapsthecancelbutton,thenthedelegatereceivesthemessageimagePickerControllerDidCancel(_:).)Theimagepicker ’sdelegatewillbetheinstanceofDetailViewController.AtthetopofDetailViewController.swift,declarethatDetailViewControllerconformstotheUINavigationControllerDelegateandtheUIImagePickerControllerDelegateprotocols.classDetailViewController:UIViewController,UITextFieldDelegate,

UINavigationControllerDelegate,UIImagePickerControllerDelegate{

WhyUINavigationControllerDelegate?UIImagePickerController’sdelegatepropertyisactuallyinheritedfromitssuperclass,UINavigationController,andwhileUIImagePickerControllerhasitsowndelegateprotocol,itsinheriteddelegatepropertyisdeclaredtoreferenceanobjectthatconformstoUINavigationControllerDelegate.InDetailViewController.swift,settheinstanceofDetailViewControllertobetheimagepicker ’sdelegateintakePicture(_:).@IBActionfunctakePicture(_sender:UIBarButtonItem){

letimagePicker=UIImagePickerController()

Page 442: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

//Ifthedevicehasacamera,takeapicture;otherwise,

//justpickfromphotolibrary

ifUIImagePickerController.isSourceTypeAvailable(.camera){

imagePicker.sourceType=.camera

}else{

imagePicker.sourceType=.photoLibrary

}

imagePicker.delegate=self

}

Presentingtheimagepickermodally

OncetheUIImagePickerControllerhasasourcetypeandadelegate,youcandisplayitbypresentingtheviewcontrollermodally.InDetailViewController.swift,addcodetotheendoftakePicture(_:)topresenttheUIImagePickerController.imagePicker.delegate=self

//Placeimagepickeronthescreen

present(imagePicker,animated:true,completion:nil)

}

Buildandruntheapplication.SelectanItemtoseeitsdetailsandthentapthecamerabuttonontheUIToolbarand…theapplicationcrashes.Takealookatthedescriptionofthecrashintheconsole.Homepwner[3575:64615][access]Thisapphascrashedbecauseitattemptedto

accessprivacy-sensitivedatawithoutausagedescription.Theapp'sInfo.plist

mustcontainanNSPhotoLibraryUsageDescriptionkeywithastringvalueexplaining

totheuserhowtheappusesthisdata.

Whenattemptingtoaccessprivateinformation,suchasauser ’sphotos,iOSpresentsaprompttotheuseraskingthemwhethertheywanttoallowaccesstotheapplication.Containedwithinthispromptisadescriptionforwhytheapplicationwantstoaccessthisinformation.Homepwnerismissingthisdescription,andthereforetheapplicationiscrashing.

Permissions

ThereareanumberofcapabilitiesoniOSthatrequireuserapprovalbeforeuse.Hereareasubsetofthosecapabilities:

CameraandphotosLocationMicrophoneHealthKitdata

Page 443: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

CalendarReminders

Foreachofthese,yourapplicationmustsupplyausagedescriptionthatspecifiesthereasonthatyourapplicationwantstoaccessthisinformation.Thisdescriptionwillbepresentedtotheuserwhenevertheapplicationaccessesthatcapability.Intheprojectnavigator,selecttheprojectatthetop.MakesuretheHomepwnertargetisselectedandopentheInfotabalongthetop(Figure15.10).Figure15.10Openingtheprojectinfo

HoveroverthelastentryinthislistofCustomiOSTargetPropertiesandclickthe+button.SettheKeyofthisnewentrytobeNSCameraUsageDescriptionandtheTypetobeaString.Double-clickontheValueforthisnewrowandenterthestring“Thisappusesthecameratoassociatephotoswithitems.”Thisisthestringthatwillbepresentedtotheuser.Nowrepeatthesamestepsabovetoaddausagedescriptionforthephotolibrary.TheKeywillbeNSPhotoLibraryUsageDescriptionoftypeStringandtheValuewillbe“ThisappusesthePhotoslibrarytoassociatephotoswithitems.”TheCustomiOSTargetPropertiessectionwillnowlooklikeFigure15.11.(Theentriesinyourlistmaybeinadifferentorder.)

Page 444: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure15.11Addinginthenewkeys

Buildandruntheapplicationandnavigatetoanitem.Tapthecamerabuttonandyouwillseethepermissiondialogpresentedwiththeusagedescriptionthatyouprovided(Figure15.12showsthedescriptionforthelibrary).Afteraccepting,theUIImagePickerController’sinterfacewillappearonthescreen(Figure15.13showsthecamerainterface),andyoucantakeapictureorchooseanexistingimageifyourdevicedoesnothaveacamera.Figure15.12Photoslibraryusagedescription

(Ifyouareworkingonthesimulator,therearesomedefaultimagesalreadyinthephotolibrary.Ifyouwouldliketoaddyourown,youcandraganimagefromyourcomputerontothesimulator,anditwillbeaddedtothesimulator ’sphotolibrary.Alternatively,youcanopenSafariinthesimulatorandnavigatetoapagewithanimage.ClickandholdtheimageandchooseSaveImagetosaveitinthesimulator ’sphotolibrary.)

Page 445: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure15.13UIImagePickerController’spreviewinterface

Savingtheimage

SelectinganimagedismissestheUIImagePickerControllerandreturnsyoutothedetailview.However,youdonothaveareferencetothephotooncetheimagepickerisdismissed.Tofixthis,youaregoingtoimplementthedelegatemethodimagePickerController(_:didFinishPickingMediaWithInfo:).Thismethodiscalledontheimagepicker ’sdelegatewhenaphotohasbeenselected.InDetailViewController.swift,implementthismethodtoputtheimageintotheUIImageViewandthencallthemethodtodismisstheimagepicker.funcimagePickerController(_picker:UIImagePickerController,

didFinishPickingMediaWithInfoinfo:[String:Any]){

Page 446: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

//Getpickedimagefrominfodictionary

letimage=info[UIImagePickerControllerOriginalImage]as!UIImage

//Putthatimageonthescreenintheimageview

imageView.image=image

//Takeimagepickeroffthescreen-

//youmustcallthisdismissmethod

dismiss(animated:true,completion:nil)

}

Buildandruntheapplicationagain.Take(orselect)aphoto.Theimagepickerisdismissed,andyouarereturnedtotheDetailViewController’sview,whereyouwillseetheselectedphoto.Homepwner’suserscouldhavehundredsofitemstocatalog,andeachonecouldhavealargeimageassociatedwithit.KeepinghundredsofinstancesofIteminmemoryisnotabigdeal.Keepinghundredsofimagesinmemorywouldbebad:First,youwillgetalowmemorywarning.Then,ifyourapp’smemoryfootprintcontinuestogrow,theOSwillterminateit.Thesolution,whichyouaregoingtoimplementinthenextsection,istostoreimagestodiskandonlyfetchthemintoRAMwhentheyareneeded.Thisfetchingwillbedonebyanewclass,ImageStore.Whentheapplicationreceivesalow-memorynotification,theImageStore’scachewillbeflushedtofreethememorythatthefetchedimageswereoccupying.

Page 447: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 448: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

CreatingImageStore

InChapter16,youwillhaveinstancesofItemwriteouttheirpropertiestoafile,whichwillthenbereadinwhentheapplicationstarts.However,becauseimagestendtobeverylarge,itisagoodideatokeepthemseparatefromotherdata.YouaregoingtostorethepicturestheusertakesinaninstanceofaclassnamedImageStore.Theimagestorewillfetchandcachetheimagesastheyareneeded.Itwillalsobeabletoflushthecacheifthedevicerunslowonmemory.CreateanewSwiftfilenamedImageStore.InImageStore.swift,definetheImageStoreclassandaddapropertythatisaninstanceofNSCache.importFoundation

importUIKit

classImageStore{

letcache=NSCache<NSString,UIImage>()

}

Thecacheworksverymuchlikeadictionary(whichyousawinChapter2).Youareabletoadd,remove,andupdatevaluesassociatedwithagivenkey.Unlikeadictionary,thecachewillautomaticallyremoveobjectsifthesystemgetslowonmemory.Whilethiscouldbeaprobleminthischapter(becauseimageswillonlyexistwithinthecache),youwillfixtheprobleminChapter16whenyouwillalsowritetheimagestothefilesystem.NotethatthecacheisassociatinganinstanceofNSStringwithUIImage.NSStringisObjective-C’sversionofString.DuetothewayNSCacheisimplemented(itisanObjective-Cclass,likemostofApple’sclassesthatyouhavebeenworkingwith),itrequiresyoutouseNSStringinsteadofString.Nowimplementthreemethodsforadding,retrieving,anddeletinganimagefromthedictionary.classImageStore{

letcache=NSCache<NSString,UIImage>()

funcsetImage(_image:UIImage,forKeykey:String){

cache.setObject(image,forKey:keyasNSString)

}

funcimage(forKeykey:String)->UIImage?{

returncache.object(forKey:keyasNSString)

}

funcdeleteImage(forKeykey:String){

cache.removeObject(forKey:keyasNSString)

}

}

ThesethreemethodsalltakeinakeyoftypeStringsothattherestofyourcodebasedoes

Page 449: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

nothavetothinkabouttheunderlyingimplementationofNSCache.YouthencasteachStringtoanNSStringwhenpassingittothecache.

Page 450: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 451: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

GivingViewControllersAccesstotheImageStore

TheDetailViewControllerneedsaninstanceofImageStoretofetchandstoreimages.YouwillinjectthisdependencyintotheDetailViewController’sdesignatedinitializer,justasyoudidforItemsViewControllerandItemStoreinChapter10.InDetailViewController.swift,addapropertyforanImageStore.varitem:Item!{

didSet{

navigationItem.title=item.name

}

}

varimageStore:ImageStore!

NowdothesameinItemsViewController.swift.varitemStore:ItemStore!

varimageStore:ImageStore!

Next,stillinItemsViewController.swift,updateprepare(for:sender:)tosettheimageStorepropertyonDetailViewController.overridefuncprepare(forsegue:UIStoryboardSegue,sender:Any?){

//Ifthetriggeredsegueisthe"showItem"segue"

switchsegue.identifier{

case"showItem"?:

//Figureoutwhichrowwasjusttapped

ifletrow=tableView.indexPathForSelectedRow?.row{

//Gettheitemassociatedwiththisrowandpassitalong

letitem=itemStore.allItems[row]

letdetailViewController

=segue.destinationas!DetailViewController

detailViewController.item=item

detailViewController.imageStore=imageStore

}

default:

preconditionFailure("Unexpectedsegueidentifier.")

}

}

Finally,updateAppDelegate.swifttocreateandinjecttheImageStore.funcapplication(_application:UIApplication,didFinishLaunchingWithOptions

launchOptions:[UIApplicationLaunchOptionsKey:Any]?)->Bool{

//Overridepointforcustomizationafterapplicationlaunch.

//CreateanItemStore

letitemStore=ItemStore()

//CreateanImageStore

letimageStore=ImageStore()

//AccesstheItemsViewControllerandsetitsitemstoreandimagestore

letnavController=window!.rootViewControlleras!UINavigationController

letitemsController=navController.topViewControlleras!ItemsViewController

itemsController.itemStore=itemStore

itemsController.imageStore=imageStore

Page 452: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 453: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

CreatingandUsingKeys

Whenanimageisaddedtothestore,itwillbeputintothecacheunderauniquekey,andtheassociatedItemobjectwillbegiventhatkey.WhentheDetailViewControllerwantsanimagefromthestore,itwillaskitsitemforthekeyandsearchthecachefortheimage.AddapropertytoItem.swifttostorethekey.letdateCreated:Date

letitemKey:String

Theimagekeysneedtobeuniqueforyourcachetowork.Whiletherearemanywaystohacktogetherauniquestring,youaregoingtousetheCocoaTouchmechanismforcreatinguniversallyuniqueidentifiers(UUIDs),alsoknownasgloballyuniqueidentifiers(GUIDs).ObjectsoftypeNSUUIDrepresentaUUIDandaregeneratedusingthetime,acounter,andahardwareidentifier,whichisusuallytheMACaddressoftheWi-Ficard.Whenrepresentedasastring,UUIDslooksomethinglikethis:4A73B5D2-A6F4-4B40-9F82-EA1E34C1DC04

InItem.swift,generateaUUIDandsetitastheitemKey.init(name:String,serialNumber:String?,valueInDollars:Int){

self.name=name

self.valueInDollars=valueInDollars

self.serialNumber=serialNumber

self.dateCreated=Date()

self.itemKey=UUID().uuidString

super.init()

}

Then,inDetailViewController.swift,updateimagePickerController(_:didFinishPickingMediaWithInfo:)tostoretheimageintheImageStore.funcimagePickerController(_picker:UIImagePickerController,

didFinishPickingMediaWithInfoinfo:[String:Any]){

//Getpickedimagefrominfodictionary

letimage=info[UIImagePickerControllerOriginalImage]as!UIImage

//StoretheimageintheImageStorefortheitem'skey

imageStore.setImage(image,forKey:item.itemKey)

//Putthatimageonthescreenintheimageview

imageView.image=image

//Takeimagepickeroffthescreen-

//youmustcallthisdismissmethod

dismiss(animated:true,completion:nil)

}

Eachtimeanimageiscaptured,itwillbeaddedtothestore.BoththeImageStoreandtheItemwillknowthekeyfortheimage,sobothwillbeabletoaccessitasneeded(Figure15.14).

Page 454: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure15.14Accessingimagesfromthecache

Similarly,whenanitemisdeleted,youneedtodeleteitsimagefromtheimagestore.InItemsViewController.swift,updatetableView(_:commit:forRowAt:)toremovetheitem’simagefromtheimagestore.overridefunctableView(_tableView:UITableView,

commiteditingStyle:UITableViewCellEditingStyle,

forRowAtindexPath:IndexPath){

//Ifthetableviewisaskingtocommitadeletecommand...

ifeditingStyle==.delete{

letitem=itemStore.allItems[indexPath.row]

lettitle="Delete\(item.name)?"

letmessage="Areyousureyouwanttodeletethisitem?"

letac=UIAlertController(title:title,

message:message,

preferredStyle:.actionSheet)

letcancelAction=UIAlertAction(title:"Cancel",

style:.cancel,

handler:nil)

ac.addAction(cancelAction)

letdeleteAction=UIAlertAction(title:"Delete",style:.destructive,

handler:{(action)->Voidin

//Removetheitemfromthestore

self.itemStore.removeItem(item)

//Removetheitem'simagefromtheimagestore

self.imageStore.deleteImage(forKey:item.itemKey)

Page 455: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

//Alsoremovethatrowfromthetableviewwithananimation

self.tableView.deleteRows(at:[indexPath],with:.automatic)

})

ac.addAction(deleteAction)

//Presentthealertcontroller

present(ac,animated:true,completion:nil)

}

}

Page 456: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 457: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

WrappingUpImageStore

NowthattheImageStorecanstoreimagesandinstancesofItemhaveakeytogetanimage(Figure15.14),youneedtoteachDetailViewControllerhowtograbtheimagefortheselectedItemandplaceitinitsimageView.TheDetailViewController’sviewwillappearwhentheusertapsarowinItemsViewControllerandwhentheUIImagePickerControllerisdismissed.Inbothofthesesituations,theimageViewshouldbepopulatedwiththeimageoftheItembeingdisplayed.Currently,itisonlyhappeningwhentheUIImagePickerControllerisdismissed.InDetailViewController.swift,makethishappeninviewWillAppear(_:).overridefuncviewWillAppear(_animated:Bool){

super.viewWillAppear(animated)

nameField.text=item.name

serialNumberField.text=item.serialNumber

valueField.text=

numberFormatter.string(from:NSNumber(value:item.valueInDollars))

dateLabel.text=dateFormatter.string(from:item.dateCreated)

//Gettheitemkey

letkey=item.itemKey

//Ifthereisanassociatedimagewiththeitem

//displayitontheimageview

letimageToDisplay=imageStore.image(forKey:key)

imageView.image=imageToDisplay

}

Buildandruntheapplication.Createanitemandselectitfromthetableview.Then,tapthecamerabuttonandtakeapicture.Theimagewillappearasitshould.Popoutfromtheitem’sdetailstothelistofitems.Unlikebefore,ifyoutapanddrilldowntoseethedetailsoftheitemyouaddedapictureto,youwillseetheimage.

Page 458: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 459: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

BronzeChallenge:EditinganImage

UIImagePickerControllerhasabuilt-ininterfaceforeditinganimageonceithasbeenselected.AllowtheusertoedittheimageandusetheeditedimageinsteadoftheoriginalimageinDetailViewController.

Page 460: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 461: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

SilverChallenge:RemovinganImage

Addabuttonthatclearstheimageforanitem.

Page 462: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 463: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

GoldChallenge:CameraOverlay

UIImagePickerControllerhasacameraOverlayViewproperty.MakeitsothatpresentingtheUIImagePickerControllershowsacrosshairinthemiddleoftheimagecapturearea.

Page 464: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 465: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

FortheMoreCurious:NavigatingImplementationFiles

Bothofyourviewcontrollershavequiteafewmethodsintheirimplementationfiles.TobeaneffectiveiOSdeveloper,youmustbeabletogotothecodeyouarelookingforquicklyandeasily.ThesourceeditorjumpbarinXcodeisonetoolatyourdisposal(Figure15.15).Figure15.15Sourceeditorjumpbar

Thejumpbarshowsyouwhereexactlyyouarewithintheproject(andalsowherethecursoriswithinagivenfile).Figure15.16breaksdownthejumpbardetails.Figure15.16Jumpbardetails

Thebreadcrumbtrailnavigationofthejumpbarmirrorstheprojectnavigationhierarchy.Ifyouclickonanyofthesections,youwillbepresentedwithapopoverofthatsectionintheprojecthierarchy.Fromthere,youcaneasilynavigatetootherpartsoftheproject.Figure15.17showsthefilepopoverfortheHomepwnerfolder.Figure15.17Filepopover

Perhapsmostusefulistheabilitytonavigateeasilywithinanimplementationfile.Ifyouclickonthelastelementinthebreadcrumbtrail,youwillgetapopoverwiththecontentsofthefile,includingallofthemethodsimplementedwithinthatfile.Whilethepopoverisvisible,youcantypetofiltertheitemsinthelist.Atanypoint,youcan

Page 466: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

usetheupanddownarrowkeysandthenpresstheReturnkeytojumptothatmethodinthecode.Figure15.18showswhatyougetwhenyousearchfor“tableview”inItemsViewController.swift.Figure15.18Filepopoverwith“tableview”search

//MARK:

Asyourclassesgetlonger,itcangetmoredifficulttofindamethodburiedinalonglistofmethods.Agoodwaytoorganizeyourmethodsistouse//MARK:comments.Twouseful//MARK:commentsarethedividerandthelabel://Thisisadivider

//MARK:-

//Thisisalabel

//MARK:MyAwesomeMethods

Thedividerandlabelcanbecombined://MARK:-Viewlifecycle

overridefuncviewDidLoad(){...}

overridefuncviewWillAppear(_animated:Bool){...}

//MARK:-Actions

funcaddNewItem(_sender:UIBarButtonItem){...}

Adding//MARK:commentstoyourcodedoesnotchangethecodeitself;itjusttellsXcodehowtovisuallyorganizeyourmethods.Youcanseetheresultsbyopeningthecurrentfileiteminthejumpbar.Figure15.19presentsawell-organizedItemsViewController.swift.

Page 467: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure15.19Filepopoverwith//MARK:s

Ifyoumakeahabitofusing//MARK:comments,youwillforceyourselftoorganizeyourcode.Ifdonethoughtfully,thiswillmakeyourcodemorereadableandeasiertoworkwith.

Page 468: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 469: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

16Saving,Loading,andApplicationStates

TherearemanywaystosaveandloaddatainaniOSapplication.ThischapterwilltakeyouthroughsomeofthemostcommonmechanismsaswellastheconceptsyouneedforwritingtoorreadingfromthefilesysteminiOS.Alongtheway,youwillbeupdatingHomepwnersothatitsdatapersistsbetweenruns(Figure16.1).Figure16.1Homepwnerinthetaskswitcher

Page 470: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Archiving

MostiOSapplicationsare,atbase,doingthesamething:providinganinterfacefortheusertomanipulatedata.Everyobjectinanapplicationhasaroleinthisprocess.Modelobjectsareresponsibleforholdingontothedatathattheusermanipulates.Viewobjectsreflectthatdata,andcontrollersareresponsibleforkeepingtheviewsandthemodelobjectsinsync.Therefore,savingandloading“data”almostalwaysmeanssavingandloadingmodelobjects.InHomepwner,themodelobjectsthatausermanipulatesareinstancesofItem.ForHomepwnertobeausefulapplication,instancesofItemmustpersistbetweenrunsoftheapplication.YouwillbeusingarchivingtosaveandloadItemobjects.ArchivingisoneofthemostcommonwaysofpersistingmodelobjectsiniOS.Archivinganobjectinvolvesrecordingallofitspropertiesandsavingthemtothefilesystem.Unarchivingre-createstheobjectfromthatdata.ClasseswhoseinstancesneedtobearchivedandunarchivedmustconformtotheNSCodingprotocolandimplementitstworequiredmethods,encode(with:)andinit(coder:).protocolNSCoding{

funcencode(withaCoder:NSCoder)

init?(coderaDecoder:NSCoder)

}

Whenobjectsareaddedtoaninterfacefile,suchasastoryboardfile,theyarearchived.Atruntime,theobjectsareloadedintomemorybybeingunarchivedfromtheinterfacefile.UIViewandUIViewControllerbothconformtotheNSCodingprotocol,sobothcanbearchivedandunarchivedwithoutanyextraeffortfromyou.YourItemclass,ontheotherhand,doesnotcurrentlyconformtoNSCoding.OpenHomepwner.xcodeprojandaddthisprotocoldeclarationinItem.swift.classItem:NSObject,NSCoding{

Thenextstepistoimplementtherequiredmethods.Let’sstartwithencode(with:).WhenanItemissentthemessageencode(with:),itwillencodeallofitspropertiesintotheNSCoderobjectthatispassedasanargument.Whilesaving,youwilluseNSCodertowriteoutastreamofdata.Thatstreamwillbeorganizedaskey-valuepairsandstoredonthefilesystem.InItem.swift,implementencode(with:)toaddthenamesandvaluesoftheitem’spropertiestothestream.funcencode(withaCoder:NSCoder){

aCoder.encode(name,forKey:"name")

aCoder.encode(dateCreated,forKey:"dateCreated")

aCoder.encode(itemKey,forKey:"itemKey")

aCoder.encode(serialNumber,forKey:"serialNumber")

aCoder.encode(valueInDollars,forKey:"valueInDollars")

}

TofindoutwhichencodingmethodstouseforotherSwifttypes,youcancheckthedocumentationforNSCoder.Regardlessofthetypeoftheencodedvalue,thereisalwaysa

Page 471: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

key,whichisastringthatidentifieswhichpropertyisbeingencoded.Byconvention,thiskeyisthenameofthepropertybeingencoded.Encodingisarecursiveprocess.Whenaninstanceisencoded(thatis,whenitisthefirstargumentinencode(_:forKey:)),thatinstanceissentencode(with:).Duringtheexecutionofitsencode(with:)method,itencodesitspropertiesusingencode(_:forKey:)(Figure16.2).Thus,eachinstanceencodesanypropertiesthatitreferences,whichencodeanypropertiesthattheyreference,andsoon.Figure16.2Encodinganobject

ThepurposeofthekeyistoretrievetheencodedvaluewhenthisItemisloadedfromthefilesystemlater.Objectsbeingloadedfromanarchivearesentthemessageinit(coder:).Thismethodshouldgraballoftheobjectsthatwereencodedinencode(with:)andassignthemtotheappropriateproperty.InItem.swift,implementinit(coder:).requiredinit(coderaDecoder:NSCoder){

name=aDecoder.decodeObject(forKey:"name")as!String

dateCreated=aDecoder.decodeObject(forKey:"dateCreated")as!Date

itemKey=aDecoder.decodeObject(forKey:"itemKey")as!String

serialNumber=aDecoder.decodeObject(forKey:"serialNumber")as!String?

valueInDollars=aDecoder.decodeInteger(forKey:"valueInDollars")

super.init()

}

NoticethatthismethodhasanNSCoderargument,too.Ininit(coder:),theNSCoderisfullofdatatobeconsumedbytheItembeinginitialized.AlsonoticethatyoucalldecodeObject(forKey:)onthecontainertogetobjectsand

Page 472: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

decodeInteger(forKey:)togetthevalueInDollars.InChapter10,wetalkedabouttheinitializerchainanddesignatedinitializers.Theinit(coder:)methodisnotpartofthisdesignpattern.YouwillkeepItem’sdesignatedinitializerthesame,andinit(coder:)willnotcallit.InstancesofItemarenowNSCodingcompliantandcanbesavedtoandloadedfromthefilesystemusingarchiving.Youcanbuildtheapplicationnowtomakesuretherearenosyntaxerrors,butyoudonotyethaveawaytokickoffthesavingandloading.Youalsoneedaplaceonthefilesystemtostorethesaveditems.

Page 473: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 474: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

ApplicationSandbox

EveryiOSapplicationhasitsownapplicationsandbox.Anapplicationsandboxisadirectoryonthefilesystemthatisbarricadedfromtherestofthefilesystem.Yourapplicationmuststayinitssandbox,andnootherapplicationcanaccessitssandbox.Figure16.3showstheapplicationsandboxforiTunes/iCloud.Figure16.3Applicationsandbox

Theapplicationsandboxcontainsanumberofdirectories:Documents/

Thisdirectoryiswhereyouwritedatathattheapplicationgeneratesduringruntimeandthatyouwanttopersistbetweenrunsoftheapplication.ItisbackedupwhenthedeviceissynchronizedwithiTunesoriCloud.Ifsomethinggoeswrongwiththedevice,filesinthisdirectorycanberestoredfromiTunesoriCloud.InHomepwner,thefilethatholdsthedataforallyouritemswillbestoredhere.Library/Caches/

Thisdirectoryiswhereyouwritedatathattheapplicationgeneratesduringruntimeandthatyouwanttopersistbetweenrunsoftheapplication.However,unliketheDocumentsdirectory,itdoesnotgetbackedupwhenthedeviceissynchronizedwithiTunesoriCloud.Amajorreasonfornotbackingupcacheddataisthatthedatacanbeverylargeandextendthetimeittakestosynchronizeyourdevice.Datastoredsomewhereelse–likeawebserver–canbeplacedinthisdirectory.Iftheuserneedstorestorethedevice,thisdatacanbedownloadedfromthewebserveragain.Ifthedeviceisverylowondiskspace,thesystemmaydeletethecontentsofthisdirectory.Library/Preferences/

ThisdirectoryiswhereanypreferencesarestoredandwheretheSettingsapplicationlooksforapplicationpreferences.Library/PreferencesishandledautomaticallybytheclassNSUserDefaultsandisbackedupwhenthedeviceissynchronizedwithiTunesoriCloud.tmp/

Thisdirectoryiswhereyouwritedatathatyouwillusetemporarilyduringanapplication’sruntime.TheOSmaypurgefilesinthisdirectorywhenyourapplicationisnotrunning.

Page 475: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

However,tobetidyyoushouldexplicitlyremovefilesfromthisdirectorywhenyounolongerneedthem.ThisdirectorydoesnotgetbackedupwhenthedeviceissynchronizedwithiTunesoriCloud.

ConstructingafileURL

TheinstancesofItemfromHomepwnerwillbesavedtoasinglefileintheDocumentsdirectory.TheItemStorewillhandlewritingtoandreadingfromthatfile.Todothis,theItemStoreneedstoconstructaURLtothisfile.ImplementanewpropertyinItemStore.swifttostorethisURL.varallItems=[Item]()

letitemArchiveURL:URL={

letdocumentsDirectories=

FileManager.default.urls(for:.documentDirectory,in:.userDomainMask)

letdocumentDirectory=documentsDirectories.first!

returndocumentDirectory.appendingPathComponent("items.archive")

}()

Insteadofassigningavaluetothepropertydirectly,thevalueisbeingsetusingaclosure.YoumayrecallthatyoudidthiswiththenumberFormatterpropertyinChapter4.Noticethattheclosureherehasasignatureof()->URL,meaningitdoesnottakeinanyargumentsanditreturnsaninstanceofURL.WhentheItemStoreclassisinstantiated,thisclosurewillberunandthereturnvaluewillbeassignedtotheitemArchiveURLproperty.Usingaclosurelikethisallowsyoutosetthevalueforavariableorconstantthatrequiresmultiplelinesofcode,whichcanbeveryusefulwhenconfiguringobjects.Thismakesyourcodemoremaintainablebecauseitkeepsthepropertyandthecodeneededtogeneratethepropertytogether.Themethodurls(for:in:)searchesthefilesystemforaURLthatmeetsthecriteriagivenbythearguments.(Double-checkthatyourfirstargumentis.documentDirectoryandnot.documentationDirectory.Autocomplete’sfirstsuggestionis.documentationDirectory,soitiseasytointroducethiserrorandendupwiththewrongURL.)IniOS,thelastargumentisalwaysthesame.(ThismethodisborrowedfrommacOS,wheretherearesignificantlymoreoptions.)ThefirstargumentisaSearchPathDirectoryenumerationthatspecifiesthedirectoryinthesandboxyouwanttheURLfor.Forexample,searchingfor.cachesDirectorywillreturntheCachesdirectoryintheapplication’ssandbox.YoucansearchthedocumentationforSearchPathDirectorytolocatetheotheroptions.RememberthattheseenumerationvaluesaresharedbyiOSandmacOS,sonotallofthemwillworkoniOS.Thereturnvalueofurls(for:in:)isanarrayofURLs.ItisanarraybecauseinmacOStheremaybemultipleURLsthatmeetthesearchcriteria.IniOS,however,therewillonlybeone(ifthedirectoryyousearchedforisanappropriatesandboxdirectory).Therefore,the

Page 476: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

nameofthearchivefileisappendedtothefirstandonlyURLinthearray.ThiswillbewherethearchiveofIteminstanceswilllive.

Page 477: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 478: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

NSKeyedArchiverandNSKeyedUnarchiver

Younowhaveaplacetosavedataonthefilesystemandamodelobjectthatcanbesavedtothefilesystem.Thefinaltwoquestionsare:Howdoyoukickoffthesavingandloadingprocesses,andwhendoyoudoit?TosaveinstancesofItem,youwillusetheclassNSKeyedArchiverwhentheapplication“exits.”InItemStore.swift,implementanewmethodthatcallsarchiveRootObject(_:toFile:)ontheNSKeyedArchiverclass.funcsaveChanges()->Bool{

print("Savingitemsto:\(itemArchiveURL.path)")

returnNSKeyedArchiver.archiveRootObject(allItems,toFile:itemArchiveURL.path)

}

ThearchiveRootObject(_:toFile:)methodtakescareofsavingeverysingleIteminallItemstotheitemArchiveURL.Yes,itisthatsimple.HereishowarchiveRootObject(_:toFile:)works:

ThemethodbeginsbycreatinganinstanceofNSKeyedArchiver.(NSKeyedArchiverisaconcretesubclassoftheabstractclassNSCoder.)Themethodencode(with:)iscalledonallItemsandispassedtheinstanceofNSKeyedArchiverasanargument.TheallItemsarraythencallsencode(with:)toalloftheobjectsitcontains,passingthesameNSKeyedArchiver.Thus,allyourinstancesofItemencodetheirinstancevariablesintotheverysameNSKeyedArchiver(Figure16.4).TheNSKeyedArchiverwritesthedataitcollectedtothepath.

Figure16.4ArchivingtheallItemsarray

WhentheuserpressestheHomebuttononthedevice,themessage

Page 479: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

applicationDidEnterBackground(_:)issenttotheAppDelegate.ThatiswhenyouwanttosendsaveChangestotheItemStore.

OpenAppDelegate.swiftandaddapropertytotheclasstostoretheItemStoreinstance.YouwillneedapropertytoreferencetheinstanceinapplicationDidEnterBackground(_:).classAppDelegate:UIResponder,UIApplicationDelegate{

varwindow:UIWindow?

letitemStore=ItemStore()

Thenupdateapplication(_:didFinishLaunchingWithOptions:)tousethispropertyinsteadofthelocalconstant.funcapplication(_application:UIApplication,didFinishLaunchingWithOptions

launchOptions:[UIApplicationLaunchOptionsKey:Any]?)->Bool{

//Overridepointforcustomizationafterapplicationlaunch.

//CreateanItemStore

letitemStore=ItemStore()

//CreateanImageStore

letimageStore=ImageStore()

//AccesstheItemsViewControllerandsetitsitemstoreandimagestore

letnavController=window!.rootViewControlleras!UINavigationController

letitemsController=navController.topViewControlleras!ItemsViewController

itemsController.itemStore=itemStore

itemsController.imageStore=imageStore

returntrue

}

Becausethepropertyandthelocalconstantwerenamedthesame,youonlyneededtoremovethecodethatcreatedthelocalconstant.Now,stillinAppDelegate.swift,implementapplicationDidEnterBackground(_:)tokickoffsavingtheIteminstances.(Thismethodmayhavealreadybeenimplementedbythetemplate.Ifso,makesuretoaddthiscodetotheexistingmethodinsteadofwritinganewone.)funcapplicationDidEnterBackground(_application:UIApplication){

letsuccess=itemStore.saveChanges()

if(success){

print("SavedalloftheItems")

}else{

print("CouldnotsaveanyoftheItems")

}

}

Buildandruntheapplicationonthesimulator.CreateafewinstancesofItem,thenpresstheHomebuttontoleavetheapplication.Checktheconsoleandyoushouldseealogstatementindicatingthattheitemsweresaved.WhileyoucannotyetloadtheseinstancesofItembackintotheapplication,youcanstillverifythatsomethingwassaved.

Page 480: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Intheconsole’slogstatements,findonethatlogsouttheitemArchiveURLlocationandanotherthatindicateswhethersavingwassuccessful.Ifsavingwasnotsuccessful,confirmthatyouritemArchiveURLisbeingcreatedcorrectly.Iftheitemsweresavedsuccessfully,copythepaththatisprintedtotheconsole.OpenFinderandpressCommand-Shift-G.PastethefilepaththatyoucopiedfromtheconsoleandpressReturn.Youwillbetakentothedirectorythatcontainstheitems.archivefile.PressCommand-Uptonavigatetotheparentdirectoryofitems.archive.Thisistheapplication’ssandboxdirectory.Here,youcanseetheDocuments,Library,andtmpdirectoriesalongsidetheapplicationitself(Figure16.5).Figure16.5Homepwner’ssandbox

Thelocationofthesandboxdirectorycanchangebetweenrunsoftheapplication;however,thecontentsofthesandboxwillremainunchanged.Duetothis,youmayneedtocopyandpastethedirectoryintoFinderfrequentlywhileworkingonanapplication.

Loadingfiles

Nowlet’sturntoloadingthesefiles.ToloadinstancesofItemwhentheapplicationlaunches,youwillusetheclassNSKeyedUnarchiverwhentheItemStoreiscreated.InItemStore.swift,overrideinit()toaddthefollowingcode.init(){

ifletarchivedItems=

NSKeyedUnarchiver.unarchiveObject(withFile:itemArchiveURL.path)as?[Item]{

allItems=archivedItems

}

}

TheunarchiveObject(withFile:)methodwillcreateaninstanceofNSKeyedUnarchiverandloadthearchivelocatedattheitemArchiveURLintothatinstance.TheNSKeyedUnarchiverwilltheninspectthetypeoftherootobjectinthearchiveandcreateaninstanceofthattype.Inthiscase,thetypewillbeanarrayofItemsbecauseyoucreatedthisarchivewitharootobjectoftype[Item].(IftherootobjectwereaninstanceofIteminstead,thenunarchiveObject(withFile:)wouldreturnanItem.)Thenewlycreatedarrayisthensentinit(coder:)and,asyoumayhaveguessed,theNSKeyedUnarchiverispassedastheargument.Thearraystartsdecodingitscontents(instancesofItem)fromtheNSKeyedUnarchiverandsendseachoftheseobjectsthemessageinit(coder:),passingthesameNSKeyedUnarchiver.

Page 481: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Buildandruntheapplication.Youritemswillbeavailableuntilyouexplicitlydeletethem.Onethingtonoteabouttestingyoursavingandloadingcode:IfyoukillHomepwnerfromXcode,themethodapplicationDidEnterBackground(_:)willnotgetachancetobecalledandtheitemarraywillnotbesaved.YoumustpresstheHomebuttonfirstandthenkillitfromXcodebyclickingtheStopbutton.

Page 482: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 483: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

ApplicationStatesandTransitions

InHomepwner,theitemsarearchivedwhentheapplicationentersthebackgroundstate.Itisusefultounderstandthestatesanapplicationcanbein,whatcausesapplicationstotransitionbetweenstates,andhowyourcodecanbenotifiedofthesetransitions.ThisinformationissummarizedinFigure16.6.Figure16.6Statesofatypicalapplication

Whenanapplicationisnotrunning,itisinthenotrunningstateanditdoesnotexecuteanycodeorhaveanymemoryreservedinRAM.Aftertheuserlaunchesanapplication,itenterstheactivestate.Whenintheactivestate,anapplication’sinterfaceisonthescreen,itisacceptingevents,anditscodeishandlingthoseevents.Whileintheactivestate,anapplicationcanbetemporarilyinterruptedbyasystemeventlikeanSMSmessage,pushnotification,phonecall,oralarm.Anoverlaywillappearontopofyourapplicationtohandlethisevent,andtheapplicationenterstheinactivestate.Intheinactivestate,anapplicationisvisiblebehindtheoverlayandisexecutingcode,butitisnotreceivingevents.Applicationstypicallyspendverylittletimeintheinactivestate.YoucanforceanactiveapplicationintotheinactivestatebypressingtheLockbuttonatthetopofthedevice.Theapplicationwillstayinactiveuntilthedeviceisunlocked.WhentheuserpressestheHomebuttonorswitchestoanotherapplicationinsomeotherway,

Page 484: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

theapplicationentersthebackgroundstate.(Actually,itspendsabriefmomentintheinactivestatebeforetransitioningtothebackgroundstate.)Inthebackgroundstate,anapplication’sinterfaceisnotvisibleorreceivingevents,butitcanstillexecutecode.Bydefault,anapplicationthatentersthebackgroundstatehasabout10secondsbeforeitentersthesuspendedstate.Yourapplicationshouldnotrelyonthisnumber;instead,itshouldsaveuserdataandreleaseanysharedresourcesasquicklyaspossible.Anapplicationinthesuspendedstatecannotexecutecode.Youcannotseeitsinterface,andanyresourcesitdoesnotneedwhilesuspendedaredestroyed.Asuspendedapplicationisessentiallyflash-frozenandcanbequicklythawedwhentheuserrelaunchesit.Table16.1summarizesthecharacteristicsofthedifferentapplicationstates.Table16.1Applicationstates

State Visible ReceivesEvents ExecutesCodeNotRunning no no noActive yes yes yesInactive mostly no yesBackground no no yesSuspended no no no

Youcanseewhatapplicationsareinthebackgroundorsuspendedbydouble-tappingtheHomebuttontogettothetaskswitcher(Figure16.7).YoucandothisinthesimulatorbypressingCommand-Shift-Htwice.(Recentlyrunapplicationsthathavebeenterminatedmayalsoappearinthisdisplay.)Figure16.7Backgroundandsuspendedapplicationsinthetaskswitcher

Page 485: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Anapplicationinthesuspendedstatewillremaininthatstateaslongasthereisadequatesystemmemory.WhentheOSdecidesmemoryisgettinglow,itwillterminatesuspendedapplicationsasneeded.Asuspendedapplicationgetsnoindicationthatitisabouttobeterminated.Itissimplyremovedfrommemory.(Anapplicationmayremaininthetaskswitcherafterithasbeenterminated,butitwillhavetorelaunchwhentapped.)Whenanapplicationchangesitsstate,amethodiscalledontheapplicationdelegate.HerearesomeofthemethodsfromtheUIApplicationDelegateprotocolthatannounceapplicationstatetransitions.(ThesearealsoshowninFigure16.6.)optionalfuncapplication(_application:UIApplication,didFinishLaunchingWithOptions

launchOptions:[UIApplicationLaunchOptionsKey:Any]?)->Bool

optionalfuncapplicationDidBecomeActive(_application:UIApplication)

optionalfuncapplicationWillResignActive(_application:UIApplication)

optionalfuncapplicationDidEnterBackground(_application:UIApplication)

optionalfuncapplicationWillEnterForeground(_application:UIApplication)

Youcanimplementthesemethodstotaketheappropriateactionsforyourapplication.Transitioningtothebackgroundstateisagoodplacetosaveanyoutstandingchangesbecause

Page 486: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

itisthelasttimeyourapplicationcanexecutecodebeforeitentersthesuspendedstate.Onceinthesuspendedstate,anapplicationcanbeterminatedatthewhimoftheOS.

Page 487: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 488: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

WritingtotheFilesystemwithData

YourarchivinginHomepwnersavesandloadstheitemKeyforeachItem,butwhatabouttheimages?Atthemoment,theyarelostwhentheappentersthebackgroundstate.Inthissection,youwillextendtheimagestoretosaveimagesastheyareaddedandfetchthemastheyareneeded.TheimagesforIteminstancesshouldalsobestoredintheDocumentsdirectory.Youcanusetheimagekeygeneratedwhentheusertakesapicturetonametheimageinthefilesystem.ImplementanewmethodinImageStore.swiftnamedimageURL(forKey:)tocreateaURLinthedocumentsdirectoryusingagivenkey.funcimageURL(forKeykey:String)->URL{

letdocumentsDirectories=

FileManager.default.urls(for:.documentDirectory,in:.userDomainMask)

letdocumentDirectory=documentsDirectories.first!

returndocumentDirectory.appendingPathComponent(key)

}

Tosaveandloadanimage,youaregoingtocopytheJPEGrepresentationoftheimageintoabufferinmemory.Insteadofjustcreatingabuffer,Swiftprogrammershaveahandyclasstocreate,maintain,anddestroythesesortsofbuffers–Data.ADatainstanceholdssomenumberofbytesofbinarydata,andyouwilluseDatatostoreimagedata.InImageStore.swift,modifysetImage(_:forKey:)togetaURLandsavetheimage.funcsetImage(_image:UIImage,forKeykey:String){

cache.setObject(image,forKey:keyasNSString)

//CreatefullURLforimage

leturl=imageURL(forKey:key)

//TurnimageintoJPEGdata

ifletdata=UIImageJPEGRepresentation(image,0.5){

//WriteittofullURL

let_=try?data.write(to:url,options:[.atomic])

}

}

Let’sexaminethiscodemoreclosely.ThefunctionUIImageJPEGRepresentationtakestwoparameters:aUIImageandacompressionquality.ThecompressionqualityisaFloatfrom0to1,where1isthehighestquality(leastcompression).ThefunctionreturnsaninstanceofDataifthecompressionsucceedsandnilifitdoesnot.ThisDatainstancecanbewrittentothefilesystembycallingwrite(to:options:).ThebytesheldintheDataarethenwrittentotheURLspecifiedbythefirstparameter.Thesecondparameterallowsforsomeoptionstobepassedintothemethod.Ifthe.atomicoptionispresent,thefileiswrittentoatemporaryplaceonthefilesystem,and,oncethewritingoperationiscomplete,thatfileisrenamedtotheURLofthefirstparameter,replacinganypreviouslyexistingfile.Writingatomicallypreventsdatacorruptionshouldyourapplication

Page 489: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

crashduringthewriteprocedure.Itisworthnotingthatthiswayofwritingdatatothefilesystemisnotarchiving.WhileDatainstancescanbearchived,usingthemethodwrite(to:options:)copiesthebytesintheDatadirectlytothefilesystem.Nowthattheimageisstoredinthefilesystem,theImageStorewillneedtoloadthatimagewhenitisrequested.Theinitializerinit(contentsOfFile:)ofUIImagewillreadinanimagefromafile,givenaURL.InImageStore.swift,updatethemethodimage(forKey:)sothattheImageStorewillloadtheimagefromthefilesystemifitdoesnotalreadyhaveit.funcimage(forKeykey:String)->UIImage?{

returncache.object(forKey:keyasNSString)

ifletexistingImage=cache.object(forKey:keyasNSString){

returnexistingImage

}

leturl=imageURL(forKey:key)

guardletimageFromDisk=UIImage(contentsOfFile:url.path)else{

returnnil

}

cache.setObject(imageFromDisk,forKey:keyasNSString)

returnimageFromDisk

}

Whatisthatguardstatement?guardisaconditionalstatement,likeanifstatement.Thecompilerwillonlycontinuepasttheguardstatementiftheconditionwithintheguardistrue.Here,theconditioniswhethertheUIImageinitializationissuccessful.Iftheinitializationfails,theelseblockisexecuted,whichallowsyoutohaveanearlyreturn.Iftheinitializationsucceeds,anyvariablesorconstantsboundintheguardstatement(here,imageFromDisk)areusableaftertheguardstatement.Thecodeaboveisfunctionallyequivalenttothefollowingcode:ifletimageFromDisk=UIImage(contentsOfFile:url.path){

cache.setObject(imageFromDisk,forKey:key)

returnimageFromDisk

}

returnnil

Whileyoucoulddothis,guardprovidesbothacleaner–and,moreimportantly,asafer–waytoensurethatyouexitifyoudonothavewhatyouneed.Usingguardalsoforcesthefailurecasetobedirectlytiedtotheconditionbeingchecked.Thismakesthecodemorereadableandeasiertoreasonabout.Youareabletosaveanimagetodiskandretrieveanimagefromdisk,sothelastthingyouneedtodoisaddfunctionalitytoremoveanimagefromdisk.InImageStore.swift,makesurethatwhenanimageisdeletedfromthestore,itisalsodeletedfromthefilesystem.(Youwillseeanerrorwhenyoutypeinthiscode,whichwewilldiscussnext.)

Page 490: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

funcdeleteImage(forKeykey:String){

cache.removeObject(forKey:keyasNSString)

leturl=imageURL(forKey:key)

FileManager.default.removeItem(at:url)

}

Let’stakealookattheerrormessagethatthiscodegenerated,showninFigure16.8.Figure16.8Errorwhenremovingtheimagefromdisk

ThiserrormessageislettingyouknowthatthemethodremoveItem(at:)canfail,butyouarenothandlingtheerror.Let’sfixthis.

Page 491: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 492: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

ErrorHandling

Itisoftenusefultohaveawayofrepresentingthepossibilityoffailurewhencreatingmethods.Youhaveseenonewayofrepresentingfailurethroughoutthisbookwiththeuseofoptionals.Optionalsprovideasimplewaytorepresentfailurewhenyoudonotcareaboutthereasonforfailure.ConsiderthecreationofanIntfromaString.lettheMeaningOfLife="42"

letnumberFromString=Int(theMeaningOfLife)

ThisinitializeronInttakesaStringparameterandreturnsanoptionalInt(anInt?).ThisisbecausethestringmaynotbeabletoberepresentedasanInt.ThecodeabovewillsuccessfullycreateanInt,butthefollowingcodewillnot:letpi="ApplePie"

letnumberFromString=Int(pi)

Thestring“ApplePie”cannotberepresentedasanInt,sonumberFromStringwillcontainnil.Anoptionalworkswellforrepresentingfailureherebecauseyoudonotcarewhyitfailed.Youjustwanttoknowwhetheritwassuccessful.Whenyouneedtoknowwhysomethingfailed,anoptionalwillnotprovideenoughinformation.Thinkaboutremovingtheimagefromthefilesystem–whymightthatfail?PerhapsthereisnofileatthespecifiedURL,ortheURLismalformed,oryoudonothavepermissiontoremovethatfile.Thereareanumberofreasonsthismethodcouldfail,andyoumightwanttohandleeachcasedifferently.Swiftprovidesaricherrorhandlingsystemwithcompilersupporttoensurethatyourecognizewhensomethingbadcouldhappen.YoualreadysawthiswhentheSwiftcompilertoldyouthatyouwerenothandlingapossibleerrorwhenremovingthefilefromdisk.Ifamethodcouldgenerateanerror,itsmethodsignatureneedstoindicatethisusingthethrowskeyword.HereisthemethoddefinitionforremoveItem(at:):funcremoveItem(atURL:URL)throws

Thethrowskeywordindicatesthatthismethodcouldthrowanerror.(Ifyouarefamiliarwiththrowingexceptioninotherlanguages,Swift’serrorhandlingisnotthesameasthrowingexception.)Byusingthiskeyword,thecompilerensuresthatanyonewhousesthismethodknowsthatthismethodcanthrowanerror–and,moreimportantly,thatthecalleralsohandlesanypotentialerrors.Thisishowthecompilerwasabletoletyouknowthatyouarenothandlingerrorswhenattemptingtoremoveafilefromdisk.Tocallamethodthatcanthrow,youuseado-catchstatement.Withinthedoblock,youannotateanymethodsthatmightthrowanerrorusingthetrykeywordtoreinforcetheideathatthecallmightfail.InImageStore.swift,updatedeleteImage(forKey:)tocallremoveItem(at:)usingado-catchstatement.funcdeleteImage(forKeykey:String){

cache.removeObject(forKey:keyasNSString)

leturl=imageURL(forKey:key)

Page 493: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

FileManager.default.removeItem(at:url)

do{

tryFileManager.default.removeItem(at:url)

}catch{

}

}

Ifamethoddoesthrowanerror,thentheprogramimmediatelyexitsthedoblock;nofurthercodeinthedoblockisexecuted.Atthatpoint,theerrorispassedtothecatchblockforittobehandledinsomeway.Now,updatedeleteImage(forKey:)toprintouttheerrortotheconsole.funcdeleteImage(forKeykey:String){

cache.removeObject(forKey:keyasNSString)

leturl=imageURL(forKey:key)

do{

tryFileManager.default.removeItem(at:url)

}catch{

print("Errorremovingtheimagefromdisk:\(error)")

}

}

Withinthecatchblock,thereisanimpliciterrorconstantthatcontainsinformationdescribingtheerror.Youcanoptionallygivethisconstantanexplicitname.UpdatedeleteImage(forKey:)againtouseanexplicitnamefortheerrorbeingcaught.funcdeleteImage(forKeykey:String){

cache.removeObject(forKey:keyasNSString)

leturl=imageURL(forKey:key)

do{

tryFileManager.default.removeItem(at:url)

}catchletdeleteError{

print("Errorremovingtheimagefromdisk:\(errordeleteError)")

}

}

Thereisalotmorethatyoucandowitherrorhandling,butthisisthebasicknowledgethatyouneedfornow.Wewillcovermoredetailsasyouprogressthroughthisbook.BuildandruntheapplicationnowthattheImageStoreiscomplete.TakeaphotoforanitemandexittheapplicationtotheHomescreen(onthesimulator,selectHardware→HomeorpressShift-Command-H;onahardwaredevicesimplypresstheHomebutton).Launchtheapplicationagain.Selectingthatsameitemwillshowallitssaveddetails–includingthephotoyoujusttook.Noticethattheimagesaresavedimmediatelyafterbeingtaken,whiletheinstancesofItemaresavedonlywhentheapplicationentersthebackground.Yousavetheimagesrightawaybecausetheyarejusttoobigtokeepinmemoryforlong.

Page 494: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 495: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

BronzeChallenge:PNG

InsteadofsavingeachimageasaJPEG,saveitasaPNG.

Page 496: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 497: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

FortheMoreCurious:ApplicationStateTransitions

Let’swritesomequickcodetogetabetterunderstandingofthedifferentapplicationstatetransitions.InAppDelegate.swift,implementtheapplicationstatetransitiondelegatemethodssothattheyprintoutthenameofthemethod.Youwillneedtoaddfourmoremethods.(Checktomakesurethetemplatehasnotalreadycreatedthesemethodsbeforewritingbrandnewones.)Ratherthanhardcodingthenameofthemethodinthecalltoprint(),usethe#functionexpression.Atcompiletime,the#functionexpressionwillevaluatetoaStringrepresentingthenameofthemethod.funcapplicationWillResignActive(_application:UIApplication){

print(#function)

}

funcapplicationDidEnterBackground(_application:UIApplication){

print(#function)

letsuccess=itemStore.saveChanges()

ifsuccess{

print("SavedalloftheItems")

}else{

print("CouldnotsaveanyoftheItems")

}

}

funcapplicationWillEnterForeground(_application:UIApplication){

print(#function)

}

funcapplicationDidBecomeActive(_application:UIApplication){

print(#function)

}

funcapplicationWillTerminate(_application:UIApplication){

print(#function)

}

Finally,addthesameprint()statementtothetopofapplication(_:didFinishLaunchingWithOptions:).funcapplication(_application:UIApplication,didFinishLaunchingWithOptions

launchOptions:[UIApplicationLaunchOptionsKey:Any]?)->Bool{

print(#function)

...

}

Buildandruntheapplication.Youwillseethattheapplicationgetssentapplication(_:didFinishLaunchingWithOptions:)andthenapplicationDidBecomeActive(_:).Playaroundtoseewhatactionscausewhattransitions.PresstheHomebuttonandtheconsolewillreportthattheapplicationbrieflyinactivatedandthenwentintothebackgroundstate.RelaunchtheapplicationbytappingitsiconontheHomescreenorinthetaskswitcher.Theconsolewillreportthattheapplicationenteredthe

Page 498: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

foregroundandthenbecameactive.PresstheHomebuttontoexittheapplicationagain.Then,double-presstheHomebuttontoopenthetaskswitcher.SwipetheHomepwnerapplicationupandoffthisdisplaytoquittheapplication.Notethatnomethodiscalledonyourapplicationdelegateatthispoint–itissimplyterminated.

Page 499: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 500: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

FortheMoreCurious:ReadingandWritingtotheFilesystem

InadditiontoarchivingandData’sbinaryreadandwritemethods,thereareafewmoremethodsfortransferringdatatoandfromthefilesystem.Oneofthem,CoreData,iscomingupinChapter22.Acoupleothersareworthmentioninghere.UsingDataworkswellforbinarydata.Fortextdata,Stringhastwoinstancemethods:write(to:atomically:encoding:)andinit(contentsOf:encoding:).Theyareusedasfollows://SavesomeStringtothefilesystem

do{

trysomeString.write(to:someURL,

atomically:true,

encoding:.utf8)

}catch{

print("ErrorwritingtoURL:\(error)")

}

//LoadsomeStringfromthefilesystem

do{

letmyEssay=tryString(contentsOf:someURL,encoding:.utf8)

print(myEssay)

}catch{

print("ErrorreadingfromURL:\(error)")

}

Notethatinmanylanguages,anythingunexpectedresultsinanexceptionbeingthrown.InSwift,exceptionsarenearlyalwaysusedtoindicateprogrammererror.Whenanexceptionisthrown,theinformationaboutwhatwentwrongisinanNSExceptionobject.Thatinformationisusuallyjustahinttotheprogrammer,like,“Youtriedtoaccesstheseventhobjectinthisarray,butthereareonlytwo.”Thesymbolsforthecallstack(asitappearedwhentheexceptionwasthrown)arealsointheNSException.Whendoyouuseexceptions,andwhendoyouuseerrorhandling?Ifyouarewritingamethodthatshouldonlybecalledwithanoddnumberasanargument,throwanexceptionifitiscalledwithanevennumber–thecallerismakinganerrorandyouwanttohelpthatprogrammerfindtheerror.Ifyouarewritingamethodthatwantstoreadthecontentsofaparticulardirectorybutdoesnothavethenecessaryprivileges,useSwift’serrorhandlingandthrowanerrortothecallertoindicatewhyyouwereunabletofulfillthisveryreasonablerequest.Propertylistserializabletypescanalsobewrittentothefilesystem.TheonlytypesthatarepropertylistserializableareString,NSNumber(includingprimitiveslikeInt,Double,andBool),Date,Data,Array<Element>,andDictionary<Key:Hashable,Value>.WhenanArray<Element>orDictionary<Key,Value>iswrittentothefilesystemwiththesemethods,anXMLpropertylistiscreated.AnXMLpropertylistisacollectionoftaggedvalues,like:<?xmlversion="1.0"encoding="UTF-8"?>

<!DOCTYPEplistPUBLIC"-//Apple//DTDPLIST1.0//EN"

"http://www.apple.com/DTDs/PropertyList-1.0.dtd">

<plistversion="1.0">

Page 501: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

<array>

<dict>

<key>firstName</key>

<string>Christian</string>

<key>lastName</key>

<string>Keur</string>

</dict>

<dict>

<key>firstName</key>

<string>Aaron</string>

<key>lastName</key>

<string>Hillegass</string>

</dict>

</array>

</plist>

XMLpropertylistsareaconvenientwaytostoredatabecausetheycanbereadonnearlyanysystem.Manywebserviceapplicationsusepropertylistsasinputandoutput.Thecodeforwritingandreadingapropertylistlookslikethis:letauthors=[

["firstName":"Christian","lastName":"Keur"],

["firstName":"Aaron","lastName":"Hillegass"]

]

//Writearraytodisk

ifPropertyListSerialization.propertyList(authors,

isValidFor:.xml){

do{

letdata=tryPropertyListSerialization.data(with:authors,

format:.xml,

options:[])

data.write(to:url,options:[.atomic])

}catch{

print("Errorwritingplist:\(error)")

}

}

//Readarrayfromdisk

do{

letdata=tryData(contentsOf:url,options:[])

letauthors=tryNSPropertyListSerialization.propertyList(from:data,

options:[],

format:nil)

print("Readinauthors:\(authors)")

}catch{

print("Errorreadingplist:\(error)")

}

Page 502: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 503: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

FortheMoreCurious:TheApplicationBundle

WhenyoubuildaniOSapplicationprojectinXcode,youcreateanapplicationbundle.Theapplicationbundlecontainstheapplicationexecutableandanyresourcesyouhavebundledwithyourapplication.Resourcesarethingslikestoryboardfiles,images,andaudiofiles–anyfilesthatwillbeusedatruntime.Whenyouaddaresourcefiletoaproject,Xcodeissmartenoughtorealizethatitshouldbebundledwithyourapplication.Howcanyoutellwhichfilesarebeingbundledwithyourapplication?SelecttheHomepwnerprojectfromtheprojectnavigator.CheckouttheBuildPhasespaneintheHomepwnertarget.EverythingunderCopyBundleResourceswillbeaddedtotheapplicationbundlewhenitisbuilt.EachitemintheHomepwnertargetgroupisoneofthephasesthatoccurswhenyoubuildaproject.TheCopyBundleResourcesphaseiswherealloftheresourcesinyourprojectgetcopiedintotheapplicationbundle.Youcancheckoutwhatanapplicationbundlelookslikeonthefilesystemafteryouinstallanapplicationonthesimulator.Printtheapplicationbundlepathtotheconsoleandthennavigatetothatdirectory.print(Bundle.main.bundlePath)

Control-clicktheapplicationbundleandchooseShowPackageContentsfromthecontextualmenu(Figure16.9).Figure16.9Viewinganapplicationbundle

AFinderwindowwillappearshowingyouthecontentsoftheapplicationbundle(Figure16.10).WhenusersdownloadyourapplicationfromtheAppStore,thesefilesarecopiedtotheirdevices.

Page 504: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure16.10Theapplicationbundle

Youcanloadfilesfromtheapplication’sbundleatruntime.TogetthefullURLforfilesintheapplicationbundle,youneedtogetareferencetotheapplicationbundleandthenaskitfortheURLofaresource.//Getareferencetotheapplicationbundle

letapplicationBundle=Bundle.main

//AskfortheURLtoaresourcenamedmyImage.pnginthebundle

ifleturl=applicationBundle.url(forResource:"myImage",ofType:"png"){

//DosomethingwithURL

}

IfyouaskfortheURLtoafilethatisnotintheapplication’sbundle,thismethodwillreturnnil.Ifthefiledoesexist,thenthefullURLisreturned,andyoucanusethisURLtoloadthefilewiththeappropriateclass.Bearinmindthatfileswithintheapplicationbundleareread-only.Youcannotmodifythem,norcanyoudynamicallyaddfilestotheapplicationbundleatruntime.Filesintheapplicationbundlearetypicallythingslikebuttonimages,interfacesoundeffects,ortheinitialstateofadatabaseyoushipwithyourapplication.Youwillusethismethodinlaterchapterstoloadthesetypesofresourcesatruntime.

Page 505: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 506: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

17SizeClasses

Often,youwantanapplication’sinterfacetohaveadifferentlayoutdependingonthedimensionsandorientationofthescreen.Inthischapter,youwillmodifytheinterfaceforDetailViewControllerinHomepwnersothatwhenitappearsonascreenthathasarelativelysmallheight,thesetoftextfieldsandtheimageviewaresidebysideinsteadofstackedontopofoneanother(Figure17.1).Figure17.1TwolayoutsforHomepwner’sDetailViewController

Therelativesizesofscreensaredefinedinsizeclasses.Asizeclassrepresentsarelativeamountofscreenspaceinagivendimension.Eachdimension(widthandheight)caneitherbecompactorregular,sotherearefourpossiblecombinationsofsizeclasses:CompactWidth|CompactHeight

iPhoneswith3.5,4,or4.7-inchscreensinlandscapeorientationCompactWidth|RegularHeight

iPhonesofallsizesinportraitorientationRegularWidth|CompactHeight

iPhoneswith5.5-inchscreensinlandscapeorientationRegularWidth|RegularHeight

iPadsofallsizesinallorientationsNoticethatthesizeclassescoverbothscreensizesandorientations.Insteadofthinkingabout

Page 507: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

interfacesintermsoforientationordevice,itisbettertothinkintermsofsizeclasses.

Page 508: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

ModifyingTraitsforaSpecificSizeClass

Wheneditingtheinterfaceforaspecificsizeclasscombination,youareabletochange:propertiesformanyviewswhetheraspecificsubviewisinstalledwhetheraspecificconstraintisinstalledtheconstantofaconstraintthefontforsubviewsthatdisplaytext

InHomepwner,youaregoingtofocusonthefirstiteminthatlist–adjustingviewpropertiesdependingonthesizeclassconfiguration.Thegoalistohavetheimageviewbeontherightsideofthelabelsandtextfieldsinacompactheightenvironment.Inaregularheightenvironment,theimageviewwillbebelowthelabelsandtextfields(asitcurrentlyis).Stackviewswillmakethisremarkablyeasy.Tobegin,youaregoingtoembedtheexistingverticalstackviewwithinanotherstackview.Thiswillmakeiteasytoaddanimageviewtotherightsideofthelabelsandtextfields.OpenHomepwner.xcodeprojandMain.storyboard.Selecttheverticalstackviewandclickthe icontoembedthisstackviewwithinanotherstackview.Withthisnewstackviewselected,opentheAutoLayoutAddNewConstraintsmenu,configureitasshowninFigure17.2,andaddtheconstraints.

Page 509: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure17.2Stackviewconstraints

Next,openthenewstackview’sattributesinspector.IncreasetheSpacingtobe8.Nowyouaregoingtomovetheimageviewfromtheinnerstackviewtotheouterstackviewthatyoujustcreated.Thisishowyouwillbeabletohavetheimageviewontherightsideoftherestoftheinterface:Inacompactheightenvironment,thestackviewwillbesettobehorizontalandtheimageviewwilltakeuptherightsideoftheinterface.Movingtheimageviewfromonestackviewtotheothercanbealittletricky,soyouaregoingtodoitinafewsteps.OpenthedocumentoutlineandexpandthesectionfortheDetailViewControllerScene.ExpandtheoutertwostackviewsasshowninFigure17.3.

Page 510: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure17.3Expandingthedocumentoutline

DragtheImageViewrightabovethestackviewthatitiscurrentlycontainedwithin(Figure17.4).Thiswillmoveitfromtheinnerstackviewtotheouterstackview.Figure17.4Movingtheimageviewtotheouterstackview

Finally,collapsetheinnerstackviewanddragtheImageViewtobebelowitinthestack(Figure17.5).MakesuretheImageViewisindentedatthesamelevelastheinnerstackview.

Page 511: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Youmayneedtoupdateframesatthispointtogetridofanywarnings.Figure17.5Movingtheimageviewbelowtheinnerstackview

Buildandruntheapplication.Confirmthatthebehaviorofthestackviewisunchanged.Atthispoint,youhaveupdatedeverythingthatiscommontoallsizeclasses.Nextyouwillmodifyspecificsizeclassestochangethelayoutofthecontent.AtthebottomofInterfaceBuilder,clickonthetextViewas:iPhone7(wChR)toexpandtheviewoptions.ThenselectthelandscapeOrientation(Figure17.6).LeavetheDeviceasiPhone7.

Page 512: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure17.6DetailViewControllerviewedasiPhone7landscape

Next,youwillupdatethepropertiesfortheouterstackviewsothattheimageviewisontherightside.Selecttheouterstackviewandopenitsattributesinspector.UndertheStackViewheading,findtheAxispropertyandclickthe+buttononitsleftside.Fromthepop-upmenu,chooseAnyfortheWidthvariationandCompactfortheHeightvariation(Figure17.7).ClickAddVariation.ThiswillallowyoutocustomizetheaxispropertyforalliPhonesinlandscape.Figure17.7Addingasize-class-specificoption

Forthenewoption(hC),chooseHorizontal(Figure17.8).Now,whenevertheinterfacehasa

Page 513: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

compactheight,theouterstackviewwillhaveahorizontalconfiguration.Whentheinterfacehasaregularheight,theouterstackviewwillhaveaverticalconfiguration.Figure17.8Customizingtheaxis

Thelastchangeyouwanttomakeisfortheinnerstackviewandtheimageviewtofilltheouterstackviewequally.Todothis,youwillcustomizetheouterstackview’sdistribution.Withtheattributesinspectorstillopenfortheouterstackview,clickonthe+nexttoDistributionandonceagainselectAnyfortheWidthvariationandCompactfortheHeightvariationfromthepop-upmenu.ChangethedistributionforthissizeclasstobeFillEqually(Figure17.9).Figure17.9Customizingthedistribution

Buildandruntheapplication.Selectanitemanddrilldowntoitsdetailstoaddaphoto,ifitdoesnotalreadyhaveone.Rotatebetweenportraitandlandscape(onthesimulator,youcanuseCommandplustheleftorrightarrowkeytorotate)andnoticehowtheinterfaceislaidoutasyouspecifiedforbothregularandcompactheight.Withthat,yourHomepwnerapplicationiscomplete.Youhavebuiltanappwithaflexibleinterfacethatcantakephotosandstoredata,andwehopeyouareproudofyouraccomplishment!Takesometimetocelebrate.

Page 514: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 515: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

BronzeChallenge:StackedTextFieldandLabels

Inacompactheightenvironment,makeitsothetextfieldsandlabelsarestackedverticallyinsteadofhorizontally(Figure17.10).Figure17.10Textfieldsandlabelsstacked

Page 516: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 517: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

18TouchEventsandUIResponder

Inthenexttwochapters,youwillcreateTouchTracker,anappthatletstheuserdrawbytouchingthescreen.Inthischapter,youwillcreateaviewthatdrawslinesinresponsetotheuserdraggingacrossit(Figure18.1).Usingmultitouch,theuserwillbeabletodrawmorethanonelineatatime.Figure18.1TouchTracker

Page 518: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

TouchEvents

AsasubclassofUIResponder,aUIViewcanoverridefourmethodstohandlethefourdistincttouchevents:

oneormorefingerstouchthescreenfunctouchesBegan(_touches:Set<UITouch>,withevent:UIEvent?)

oneormorefingersmoveacrossthescreen(thismessageissentrepeatedlyasafingermoves)functouchesMoved(_touches:Set<UITouch>,withevent:UIEvent?)

oneormorefingersareremovedfromthescreenfunctouchesEnded(_touches:Set<UITouch>,withevent:UIEvent?)

asystemevent,likeanincomingphonecall,interruptsatouchbeforeitendsfunctouchesCancelled(_touches:Set<UITouch>,withevent:UIEvent?)

Let’swalkthroughthetypicallifecycleofatouch.Whentheuser ’sfingertouchesthescreen,aninstanceofUITouchiscreated.ThetouchesBegan(_:with:)methodiscalledontheUIViewthatthefingertouched,andtheUITouchispassedinthroughtheSetoftouches.Asthefingermovesaroundthescreen,thetouchobjectisupdatedtocontainthecurrentlocationofthefingeronthescreen.Then,thesameUIViewthatthetouchbeganonissentthemessagetouchesMoved(_:with:).TheSetthatispassedasanargumenttothismethodcontainsthesameUITouchthatoriginallywascreatedwhenthefingeritrepresentstouchedthescreen.Whenthefingerisremovedfromthescreen,thetouchobjectisupdatedonelasttimetocontainthefinallocationofthefinger,andtheviewthatthetouchbeganonissentthemessagetouchesEnded(_:with:).Afterthatmethodfinishesexecuting,theUITouchobjectisdestroyed.Fromthisinformation,youcandrawafewconclusionsabouthowtouchobjectswork:

OneUITouchcorrespondstoonefingeronthescreen.Thistouchobjectlivesaslongasthefingerisonthescreenandalwayscontainsthecurrentpositionofthefingeronthescreen.Theviewthatthefingerstartedonwillreceiveeverytoucheventmessageforthatfinger.EvenifthefingermovesbeyondtheframeoftheUIViewthatthetouchbeganon,thetouchesMoved(_:with:)andtouchesEnded(_:with:)methodswillstillbecalledonthatview.Thus,ifatouchbeginsonaview,thenthatviewownsthetouchforthelifeofthetouch.Youdonothaveto–norshouldyouever–keepareferencetoaUITouchobject.TheapplicationwillgiveyouaccesstoatouchobjectviatheUIRespondermethodscalledatthedistinctpointsinthetouch’slifecycle.

Everytimeatouchdoessomething–likebegins,moves,orends–atoucheventisaddedtoa

Page 519: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

queueofeventsthattheUIApplicationobjectmanages.Inpractice,thequeuerarelyfillsup,andeventsaredeliveredimmediately.ThedeliveryofthesetoucheventsinvolvessendingoneoftheUIRespondermessagestotheviewthatownsthetouch.Whataboutmultipletouches?Ifmultiplefingersdothesamethingattheexactsametimetothesameview,allofthesetoucheventsaredeliveredatonce.Eachtouchobject–oneforeachfinger–isincludedintheSetpassedasanargumentintheUIRespondermessages.However,thewindowofopportunityforthe“exactsametime”isfairlyshort.So,insteadofonerespondermessagewithallofthetouches,thereareusuallymultiplerespondermessageswithoneormoreofthetouches.Youwillseehowtohandlemultipletoucheslaterinthischapter.

Page 520: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 521: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

CreatingtheTouchTrackerApplication

Nowlet’sgetstartedwithyourapplication.InXcode,createanewsingleviewuniversalprojectandnameitTouchTracker(Figure18.2).Figure18.2CreatingTouchTracker

InbuildingTouchTracker,youaregoingtousethedefaultviewcontrollerandthestoryboardthatthetemplatecreated.Foritsviewandmodellayers,youaregoingtocreateacustomviewclassandacustomstructure.Figure18.3showsthemajorpiecesofTouchTracker.

Page 522: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure18.3ObjectdiagramforTouchTracker

Let’sbeginwithyourcustomstruct.

Page 523: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 524: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

CreatingtheLineStruct

YouaregoingtocreatethecustomLinetype.Sofar,allofthetypesthatyouhavecreatedhavebeenclasses.Infact,theyhavebeenCocoaTouchsubclasses;forexample,youhavecreatedsubclassesofNSObject,UIViewController,andUIView.Linewillbeastruct.Youhaveusedstructsthroughoutthisbook–CGRect,CGSize,andCGPointareallstructs.SotooareString,Int,Array,andDictionary.Nowyouaregoingtocreateoneofyourown.CreateanewSwiftfilenamedLine.InLine.swift,importCoreGraphicsanddeclaretheLinestruct.DeclaretwoCGPointpropertiesthatwilldeterminethebeginningandendingpointfortheline.importFoundation

importCoreGraphics

structLine{

varbegin=CGPoint.zero

varend=CGPoint.zero

}

Structs

Structsdifferfromclassesinanumberofways:Structsdonotsupportinheritance.Structsgetamember-wiseinitializerifnootherinitializersaredeclared.Themember-wiseinitializertakesinanargumentforeachpropertywithinthetype.TheLinestruct,forexample,hasthemember-wiseinitializerinit(begin:CGPoint,end:CGPoint).Ifallpropertieshavedefaultvaluesandnootherinitializersaredeclared,structsalsogainanemptyinitializer(init())thatcreatesaninstanceandsetsallofthepropertiestotheirdefaultvalue.Perhapsmostimportantly,structs(andenums)arevaluetypes–asopposedtoclasses,whicharereferencetypes.

Valuetypesvsreferencetypes

Valuetypesaretypeswhosevaluesarecopiedwhentheyareassignedtoanotherinstanceorpassedintheargumentofafunction.Thismeansthatassigninganinstanceofavaluetypetoanotheractuallyassignsacopyofthefirstinstancetothesecondinstance.ValuetypesplayanimportantroleinSwift.Forexample,arraysanddictionariesarebothvaluetypes.Allenumsandstructsyouwritearevaluetypesaswell.

Page 525: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Referencetypesarenotcopiedwhentheyareassignedtoaninstanceorpassedintoanargumentofafunction.Instead,areferencetothesameinstanceispassed.Classesandclosuresarereferencetypes.Sowhichdoyouchoose?Ingeneral,wesuggeststartingoutwithavaluetype(suchasastruct)unlessyouabsolutelyknowyouneedthebenefitsofareferencetype.Valuetypesareeasiertoreasonaboutbecauseyoudonotneedtoworryaboutwhathappenstoaninstancewhenyouchangevaluesonacopy.Ifyouwouldlikeadeeperdiscussiononthistopic,checkoutSwiftProgramming:TheBigNerdRanchGuide.

Page 526: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 527: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

CreatingDrawView

Inadditiontoacustomstruct,TouchTrackerneedsacustomview.CreateanewSwiftfilenamedDrawView.InDrawView.swift,definetheDrawViewclass.Addtwoproperties:anoptionalLinetokeeptrackofalinethatispossiblybeingdrawnandanarrayofLinestokeeptrackoflinesthathavebeendrawn.importFoundation

importUIKit

classDrawView:UIView{

varcurrentLine:Line?

varfinishedLines=[Line]()

}

AninstanceofDrawViewwillbetheviewoftheapplication’srootViewController,thedefaultViewControllerincludedintheproject.TheviewcontrollerneedstoknowthatitsviewwillbeaninstanceofDrawView.OpenMain.storyboard.SelecttheViewandopentheidentityinspector(Command-Option-3).UnderCustomClass,changetheClasstoDrawView(Figure18.4).Figure18.4Changingtheviewclass

Page 528: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 529: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

DrawingwithDrawView

AninstanceofDrawViewneedstobeabledrawlines.YouaregoingtowriteamethodthatusesUIBezierPathtocreateandstrokeapathbasedonthepropertiesofagivenLine.Thenyouwilloverridedraw(_:)todrawthelinesinthearrayoffinishedlinesaswellasthecurrentline,ifany.InDrawView.swift,implementthemethodforstrokinglinesandoverridedraw(_:).varcurrentLine:Line?

varfinishedLines=[Line]()

funcstroke(_line:Line){

letpath=UIBezierPath()

path.lineWidth=10

path.lineCapStyle=.round

path.move(to:line.begin)

path.addLine(to:line.end)

path.stroke()

}

overridefuncdraw(_rect:CGRect){

//Drawfinishedlinesinblack

UIColor.black.setStroke()

forlineinfinishedLines{

stroke(line)

}

ifletline=currentLine{

//Ifthereisalinecurrentlybeingdrawn,doitinred

UIColor.red.setStroke()

stroke(line)

}

}

Page 530: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 531: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

TurningTouchesintoLines

Alineisdefinedbytwopoints.YourLinestoresthesepointsaspropertiesnamedbeginandend.Whenatouchbegins,youwillcreateaLineandsetbothofitspropertiestothepointwherethetouchbegan.Whenthetouchmoves,youwillupdatetheLine’send.Whenthetouchends,youwillhaveyourcompleteLine.InDrawView.swift,implementtouchesBegan(_:with:)tocreateanewline.overridefunctouchesBegan(_touches:Set<UITouch>,withevent:UIEvent?){

lettouch=touches.first!

//Getlocationofthetouchinview'scoordinatesystem

letlocation=touch.location(in:self)

currentLine=Line(begin:location,end:location)

setNeedsDisplay()

}

Thiscodefirstfiguresoutthelocationofthetouchwithintheview’scoordinatesystem.ThenitcallssetNeedsDisplay(),whichflagstheviewtoberedrawnattheendoftherunloop.Next,alsoinDrawView.swift,implementtouchesMoved(_:with:)sothatitupdatestheendofthecurrentLine.overridefunctouchesMoved(_touches:Set<UITouch>,withevent:UIEvent?){

lettouch=touches.first!

letlocation=touch.location(in:self)

currentLine?.end=location

setNeedsDisplay()

}

Finally,stillinDrawView.swift,updatetheendlocationofthecurrentLineandaddittothefinishedLinesarraywhenthetouchends.overridefunctouchesEnded(_touches:Set<UITouch>,withevent:UIEvent?){

ifvarline=currentLine{

lettouch=touches.first!

letlocation=touch.location(in:self)

line.end=location

finishedLines.append(line)

}

currentLine=nil

setNeedsDisplay()

}

Buildandruntheapplicationanddrawsomelinesonthescreen.Whileyouaredrawing,thelineswillappearinred.Oncefinished,theywillappearinblack.

Page 532: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Handlingmultipletouches

Whendrawinglines,youmayhavenoticedthathavingmorethanonefingeronthescreendoesnotdoanything–thatis,youcanonlydrawonelineatatime.Let’supdateDrawViewsothatyoucandrawasmanylinesasyoucanfitfingersonthescreen.Bydefault,aviewwillonlyacceptonetouchatatime.IfonefingerhasalreadytriggeredtouchesBegan(_:with:)buthasnotfinished–andthereforehasnottriggeredtouchesEnded(_:with:)–subsequenttouchesareignored.Inthiscontext,“ignored”meansthatneithertouchesBegan(_:with:)noranyotherUIRespondermethodrelatedtotheextratoucheswillbecalledontheDrawView.InMain.storyboard,selecttheDrawViewandopentheattributesinspector.ChecktheboxlabeledMultipleTouch(Figure18.5),whichwillsettheDrawViewinstance’smultipleTouchesEnabledpropertytotrue.Figure18.5MultipleTouchenabled

NowthatDrawViewwillacceptmultipletouches,eachtimeafingertouchesthescreen,moves,orisremovedfromthescreen,theappropriateUIResponderwillbecalledontheview.However,younowhaveaproblem:YourUIRespondercodeassumestherewillonlybeonetouchactiveandonelinebeingdrawnatatime.Forexample,eachtouch-handlingmethodasksforthefirstelementinthesetoftouchesitreceives.Inasingle-touchview,therewillonlyeverbeoneobjectintheset,soaskingforanyobjectalwaysreturnsthetouchthattriggeredtheevent.Inamultiple-touchview,thesetcancontainmorethanonetouch.Also,DrawViewhasonlyoneproperty(currentLine)thathangsontoalineinprogress.Obviously,youwillneedtoholdasmanylinesastherearetouchescurrentlyonthescreen.Whileyoucouldcreateafewmoreproperties,likecurrentLine1andcurrentLine2,itwouldbeahassletomanagewhichpropertycorrespondstowhichtouch.Insteadofaddingmoreproperties,youaregoingtoreplacethesingleLinewithadictionary

Page 533: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

containinginstancesofLine.InDrawView.swift,addanewpropertytoreplacecurrentLine.classDrawView:UIView{

varcurrentLine:Line?

varcurrentLines=[NSValue:Line]()

ThekeytostorethelineinthedictionarywillbederivedfromtheUITouchobjectthatthelinecorrespondsto.Asmoretoucheventsoccur,youcanusethesamealgorithmtoderivethekeyfromtheUITouchthattriggeredtheeventanduseittolookuptheappropriateLineinthedictionary.NowyouneedtoupdatetheUIRespondermethodstoaddlinesthatarecurrentlybeingdrawntothisdictionary.InDrawView.swift,updatethecodeintouchesBegan(_:with:).overridefunctouchesBegan(_touches:Set<UITouch>,withevent:UIEvent?){

lettouch=touches.first!

//Getlocationofthetouchinview'scoordinatesystem

letlocation=touch.location(in:self)

currentLine=Line(begin:location,end:location)

//Logstatementtoseetheorderofevents

print(#function)

fortouchintouches{

letlocation=touch.location(in:self)

letnewLine=Line(begin:location,end:location)

letkey=NSValue(nonretainedObject:touch)

currentLines[key]=newLine

}

setNeedsDisplay()

}

Inthiscode,youfirstprintoutthenameofthemethodusingthe#functionexpression.Second,youenumerateoverallofthetouchesthatbegan,becauseitispossibleformorethanonetouchtobeginatthesametime.(Typically,touchesbeginatdifferenttimesandtouchesBegan(_:with:)getscalledmultipletimesontheDrawViewforeachtouch.Butyouhavetopreparefortheimprobable,ifnottheimpossible.)Next,noticetheuseofNSValue(nonretainedObject:)toderivethekeytostoretheLine.ThismethodcreatesanNSValueinstancethatholdsontotheaddressoftheUITouchobjectthatwillbeassociatedwiththisline.BecauseaUITouchiscreatedwhenatouchbegins,updatedthroughoutitslifetime,anddestroyedwhenthetouchends,theaddressofthatobjectwillbeconstantthrougheachtouch-event-handlingmethod.Figure18.6showsthenewstateofaffairs.

Page 534: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure18.6ObjectdiagramformultitouchTouchTracker

Youmaybewondering:WhynotusetheUITouchitselfasthekey?WhygothroughthehoopofcreatinganNSValue?ThedocumentationforUITouchsaysthatyoushouldneverkeepastrongreferencetoaUITouchobject.Thedetailsofmemorymanagementareoutsidethescopeofthisbook,buttoavoidcreatingastrongreferencetoatouchobject,youwrapthememoryaddressoftheUITouchinaninstanceofNSValueusingitsinit(nonretainedObject:)initializer.Thedocumentationforthismethodstates:“Thismethodisusefulifyouwanttoaddanobjecttoacollectionbutdon’twantthecollectiontocreateastrongreferencetoit,”whichisexactlywhatyouwant.BecausethesameUITouchobjectisreusedfortheentiretyofthattouch’slifecycle(andthereforehasthesamememoryaddress),youcanre-createthesameNSValueusingthesameUITouch.Next,updatetouchesMoved(_:with:)inDrawView.swiftsothatitcanlookuptherightLine.overridefunctouchesMoved(_touches:Set<UITouch>,withevent:UIEvent?){

lettouch=touches.first!

letlocation=touch.location(in:self)

currentLine?.end=location

//Logstatementtoseetheorderofevents

print(#function)

fortouchintouches{

letkey=NSValue(nonretainedObject:touch)

currentLines[key]?.end=touch.location(in:self)

}

setNeedsDisplay()

}

Now,updatetouchesEnded(_:with:)tomoveanyfinishedlinesintothefinishedLinesarray.

Page 535: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

overridefunctouchesEnded(_touches:Set<UITouch>,withevent:UIEvent?){

ifvarline=currentLine{

lettouch=touches.first!

letlocation=touch.location(in:self)

line.end=location

finishedLines.append(line)

}

currentLine=nil

//Logstatementtoseetheorderofevents

print(#function)

fortouchintouches{

letkey=NSValue(nonretainedObject:touch)

ifvarline=currentLines[key]{

line.end=touch.location(in:self)

finishedLines.append(line)

currentLines.removeValue(forKey:key)

}

}

setNeedsDisplay()

}

Finally,updatedraw(_:)todraweachlineincurrentLines.overridefuncdraw(_rect:CGRect){

//Drawfinishedlinesinblack

UIColor.black.setStroke()

forlineinfinishedLines{

stroke(line)

}

ifletline=currentLine{

//Ifthereisalinecurrentlybeingdrawn,doitinred

UIColor.red.setStroke()

stroke(line)

}

//Drawcurrentlinesinred

UIColor.red.setStroke()

for(_,line)incurrentLines{

stroke(line)

}

}

Buildandruntheapplicationandstartdrawinglineswithmultiplefingers.(Onthesimulator,holddowntheOptionkeywhileyoudragtosimulatemultiplefingers.)Noticetheorderingofthelogmessagesintheconsole.YoushouldknowthatwhenaUIRespondermethodliketouchesMoved(_:with:)iscalledonaview,onlythetouchesthathavemovedwillbeinthesetoftouches.Thus,itispossibleforthreetouchestobeonaview,butonlyonetouchtobeinthesetoftouchespassedintooneofthesemethods.Additionally,onceaUITouchbeginsonaview,alltoucheventmethodsarecalledonthatsameviewoverthetouch’slifetime,evenifthattouchmovesoffoftheviewitbeganon.

Page 536: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

ThelastthingleftforthebasicsofTouchTrackeristohandlewhathappenswhenatouchiscanceled.AtouchcanbecanceledwhentheapplicationisinterruptedbytheOS(forexample,whenaphonecallcomesin)whileatouchiscurrentlyonthescreen.Whenatouchiscanceled,anystateitsetupshouldbereverted.Inthiscase,youshouldremoveanylinesinprogress.InDrawView.swift,implementtouchesCancelled(_:with:).overridefunctouchesCancelled(_touches:Set<UITouch>,withevent:UIEvent?){

//Logstatementtoseetheorderofevents

print(#function)

currentLines.removeAll()

setNeedsDisplay()

}

Page 537: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 538: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

@IBInspectable

WhenworkinginInterfaceBuilder,youareabletomodifyattributesfortheviewsthatyouaddtothecanvas.Forexample,youcansetthebackgroundcoloronaview,thetextonalabel,andthecurrentprogressonaslider.YoucanaddthissamebehaviortoyourowncustomUIViewsubclassesforcertaintypes.Let’saddintheabilityfortheDrawView’scurrentlinecolor,finishedlinecolor,andlinethicknesstobecustomizedthroughInterfaceBuilder.InDrawView.swift,declarethreepropertiestoreferencethesevalues.Givethemdefaultvaluesandhavetheviewflagitselfforredrawingwheneverthesepropertieschange.varcurrentLines=[NSValue:Line]()

varfinishedLines=[Line]()

@IBInspectablevarfinishedLineColor:UIColor=UIColor.black{

didSet{

setNeedsDisplay()

}

}

@IBInspectablevarcurrentLineColor:UIColor=UIColor.red{

didSet{

setNeedsDisplay()

}

}

@IBInspectablevarlineThickness:CGFloat=10{

didSet{

setNeedsDisplay()

}

}

The@IBInspectablekeywordletsInterfaceBuilderknowthatthisisapropertythatyouwanttocustomizethroughtheattributesinspector.Manyofthecommontypesaresupportedby@IBInspectable:Booleans,strings,numbers,CGPoint,CGSize,CGRect,UIColor,UIImage,andafewmoreareallcandidates.Nowupdatestroke(_:)anddrawView(_:)tousethesenewproperties.funcstroke(_line:Line){

letpath=UIBezierPath()

path.lineWidth=10

path.lineWidth=lineThickness

path.lineCapStyle=.round

path.move(to:line.begin)

path.addLine(to:line.end)

path.stroke()

}

overridefuncdraw(_rect:CGRect){

//Drawfinishedlinesinblack

UIColor.black.setStroke()

finishedLineColor.setStroke()

forlineinfinishedLines{

Page 539: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

stroke(line)

}

//Drawcurrentlinesinred

UIColor.red.setStroke()

currentLineColor.setStroke()

for(_,line)incurrentLines{

stroke(line)

}

}

Now,whenyouaddaDrawViewtothecanvasinInterfaceBuilder,youcancustomizethesethreepropertiesintheattributesinspectortobedifferentfordifferentinstances(Figure18.7).Figure18.7CustomizingDrawView

Page 540: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 541: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

SilverChallenge:Colors

MakeitsothattheangleatwhichalineisdrawndictatesitscoloronceithasbeenaddedtocurrentLines.

Page 542: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 543: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

GoldChallenge:Circles

Usetwofingerstodrawcircles.Tryhavingeachfingerrepresentonecorneroftheboundingboxaroundthecircle.RecallthatyoucansimulatetwofingersonthesimulatorbyholdingdowntheOptionkey.(Hint:Thisismucheasierifyoutracktouchesthatareworkingonacircleinaseparatedictionary.)

Page 544: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 545: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

FortheMoreCurious:TheResponderChain

InChapter14,wetalkedbrieflyaboutthefirstresponder.AUIRespondercanbeafirstresponderandreceivetouchevents.UIViewisoneexampleofaUIRespondersubclass,buttherearemanyothers,includingUIViewController,UIApplication,andUIWindow.Youareprobablythinking,“Butyoucan’ttouchaUIViewController.It’snotanonscreenobject.”Youareright–youcannotsendatoucheventdirectlytoaUIViewController,butviewcontrollerscanreceiveeventsthroughtheresponderchain.EveryUIRespondercanreferenceanotherUIResponderthroughitsnextproperty,andtogethertheseobjectsmakeuptheresponderchain(Figure18.8).Atoucheventstartsattheviewthatwastouched.ThenextresponderofaviewistypicallyitsUIViewController(ifithasone)oritssuperview(ifitdoesnot).Thenextresponderofaviewcontrolleristypicallyitsview’ssuperview.Thetop-mostsuperviewisthewindow.Thewindow’snextresponderisthesingletoninstanceofUIApplication.Figure18.8Responderchain

HowdoesaUIRespondernothandleanevent?Itcallsthesamemethodonitsnextresponder.ThatiswhatthedefaultimplementationofmethodsliketouchesBegan(_:with:)does.Soifamethodisnotoverridden,itsnextresponderwillattempttohandlethetouchevent.Iftheapplication(thelastobjectintheresponderchain)doesnothandletheevent,thenitisdiscarded.Youcanexplicitlycallamethodonanextresponder,too.Let’ssaythereisaviewthattrackstouches,butifadouble-tapoccurs,itsnextrespondershouldhandleit.Thecodewouldlooklikethis:overridefunctouchesBegan(_touches:Set<UITouch>,withevent:UIEvent?){

lettouch=touches.first!

iftouch.tapCount==2{

Page 546: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

next?.touchesBegan(touches,with:event)

}else{

//Goontohandletouchesthatarenotdouble-taps

}

}

Page 547: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 548: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

FortheMoreCurious:UIControl

TheclassUIControlisthesuperclassforseveralclassesinCocoaTouch,includingUIButtonandUISlider.Youhaveseenhowtosetthetargetsandactionsforthesecontrols.NowwecantakeacloserlookathowUIControloverridesthesameUIRespondermethodsyouimplementedinthischapter.InUIControl,eachpossiblecontroleventisassociatedwithaconstant.Buttons,forexample,typicallysendactionmessagesontheUIControlEvents.touchUpInsidecontrolevent.Atargetregisteredforthiscontroleventwillonlyreceiveitsactionmessageiftheusertouchesthecontrolandthenliftsthefingeroffthescreeninsidetheframeofthecontrol.Forabutton,however,youcanhaveactionsonothereventtypes.Forexample,youmighttriggeramethodiftheuserremovesthefingerinsideoroutsidetheframe.Assigningthetargetandactionprogrammaticallywouldlooklikethis:button.addTarget(self,

action:#selector(Thermostat.resetTemperature(_:)),

for:[.touchUpInside,.touchUpOutside])

NowconsiderhowUIControlhandlesUIControlEvents.touchUpInside.//Nottheexactcode.Thereisabitmoregoingon!

overridefunctouchesEnded(_touches:Set<UITouch>,withevent:UIEvent?){

//Referencetothetouchthatisending

lettouch=touches.first!

//Locationofthatpointinthiscontrol'scoordinatesystem

lettouchLocation=touch.location(in:self)

//Isthatpointstillinmyviewingbounds?

ifbounds.contains(touchLocation){

//Sendoutactionmessagestoalltargetsregisteredforthisevent!

sendActions(for:.touchUpInside)

}

else{

//Thetouchendedoutsidethebounds:differentcontrolevent

sendActions(for:.touchUpOutside)

}

}

Sohowdotheseactionsgetsenttotherighttarget?AttheendoftheUIRespondermethodimplementations,thecontrolcallsthemethodsendActions(for:)onitself.Thismethodlooksatallofthetarget-actionpairsthecontrolhas.Ifanyofthemareregisteredforthecontroleventpassedastheargument,thecorrespondingactionmethodiscalledonthosetargets.However,acontrolnevercallsamethoddirectlyonitstargets.Instead,itroutesthesemethodcallsthroughtheUIApplicationobject.Whynothavecontrolscalltheactionmethodsdirectlyonthetargets?Controlscanalsohavenil-targetedactions.IfaUIControl’stargetisnil,theUIApplicationfindsthefirstresponderofitsUIWindowandcallstheactionmethodonit.

Page 549: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 550: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

19UIGestureRecognizerandUIMenuController

InChapter18,youhandledrawtouchesbyimplementingmethodsfromUIResponder.Sometimesyouwanttodetectaspecificpatternoftouchesthatmakeagesture,likeapinchoraswipe.Insteadofwritingcodetodetectcommongesturesyourself,youcanuseinstancesofUIGestureRecognizer.AUIGestureRecognizerinterceptstouchesthatareontheirwaytobeinghandledbyaview.Whenitrecognizesaparticulargesture,itcallsamethodontheobjectofyourchoice.ThereareseveraltypesofgesturerecognizersbuiltintotheSDK.Inthischapter,youwillusethreeofthemtoallowTouchTrackeruserstoselect,move,anddeletelines(Figure19.1).YouwillalsoseehowtouseanotherinterestingiOSclass,UIMenuController.Figure19.1TouchTrackerbytheendofthechapter

Page 551: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

UIGestureRecognizerSubclasses

YoudonotinstantiateUIGestureRecognizeritself.Instead,thereareanumberofsubclassesofUIGestureRecognizer,andeachoneisresponsibleforrecognizingaparticulargesture.TouseaninstanceofaUIGestureRecognizersubclass,yougiveitatarget-actionpairandattachittoaview.Wheneverthegesturerecognizerrecognizesitsgestureontheview,itwillsendtheactionmessagetoitstarget.AllUIGestureRecognizeractionmessageshavethesameform:funcaction(_gestureRecognizer:UIGestureRecognizer){}

Whenrecognizingagesture,thegesturerecognizerinterceptsthetouchesdestinedfortheview(Figure19.2).Thus,thetypicalUIRespondermethodsliketouchesBegan(_:with:)maynotbecalledonaviewwithgesturerecognizers.Figure19.2Gesturerecognizersintercepttouches

Page 552: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 553: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

DetectingTapswithUITapGestureRecognizer

ThefirstUIGestureRecognizersubclassyouwilluseisUITapGestureRecognizer.Whentheusertapsthescreentwice,allofthelinesonthescreenwillbecleared.OpenTouchTracker.xcodeprojandDrawView.swift.Addaninit?(coder:)methodandinstantiateaUITapGestureRecognizerthatrequirestwotapstofireandcallstheactionmethodonitstarget.requiredinit?(coderaDecoder:NSCoder){

super.init(coder:aDecoder)

letdoubleTapRecognizer=UITapGestureRecognizer(target:self,

action:#selector(DrawView.doubleTap(_:)))

doubleTapRecognizer.numberOfTapsRequired=2

addGestureRecognizer(doubleTapRecognizer)

}

Nowwhenadouble-tapoccursonaninstanceofDrawView,themethoddoubleTap(_:)willbecalledonthatinstance.ImplementthismethodinDrawView.swift.funcdoubleTap(_gestureRecognizer:UIGestureRecognizer){

print("Recognizedadoubletap")

currentLines.removeAll()

finishedLines.removeAll()

setNeedsDisplay()

}

NoticethattheargumenttotheactionmethodforagesturerecognizeristheinstanceofUIGestureRecognizerthatcalledthemethod.Inthecaseofadouble-tap,youdonotneedanyinformationfromtherecognizer,butyouwillneedinformationfromtheotherrecognizersyouinstalllaterinthechapter.Buildandruntheapplication,drawafewlines,anddouble-tapthescreentoclearthem.Youmayhavenoticed(especiallyonthesimulator)thatthefirsttapofadouble-tapresultsinasmallreddotbeingdrawn.ThisdotappearsbecausetouchesBegan(_:with:)iscalledontheDrawViewonthefirsttap,creatingaveryshortline.Checktheconsoleandyouwillseethefollowingsequenceofevents:touchesBegan(_:with:)

Recognizedadoubletap

touchesCancelled(_:with:)

Gesturerecognizersworkbyinspectingtoucheventstodeterminewhethertheirparticulargesturehasoccurred.Beforeagestureisrecognized,thegesturerecognizerinterceptsalltheUIRespondermethodcalls.Ifithasnotrecognizeditsgesture,eachcallisforwardedontotheview.Recognizingataprequiresthatatouchbeginandend.ThismeansthattheUITapGestureRecognizercannotknowwhetherthetouchisatapwhentouchesBegan(_:with:)isoriginallycalled,sothemethodiscalledontheviewaswell.Whenthetouchends,thetapisrecognizedandthegesturerecognizerclaimsthetouchforitself.ItdoessobycallingtouchesCancelled(_:with:)ontheview.Afterthat,no

Page 554: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

moreUIRespondermethodswillbecalledontheviewforthatparticulartouch.Topreventthisreddotfromappearingtemporarily,youmustpreventtouchesBegan(_:with:)frombeingcalledontheview.YoucantellaUIGestureRecognizertodelaycallingtouchesBegan(_:with:)onitsviewifitisstillpossiblethatitsgesturemightberecognizedforthattouch.InDrawView.swift,modifyinit?(coder:)todojustthis.requiredinit?(coderaDecoder:NSCoder){

super.init(coder:aDecoder)

letdoubleTapRecognizer=UITapGestureRecognizer(target:self,

action:#selector(DrawView.doubleTap(_:)))

doubleTapRecognizer.numberOfTapsRequired=2

doubleTapRecognizer.delaysTouchesBegan=true

addGestureRecognizer(doubleTapRecognizer)

}

Buildandruntheapplication,drawsomelines,andthendouble-taptoclearthem.Youwillnolongerseethereddotwhiledouble-tapping.

Page 555: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 556: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

MultipleGestureRecognizers

Thenextstepistoaddanothergesturerecognizerthatallowstheusertoselectaline.(Later,auserwillbeabletodeletetheselectedline.)YouwillinstallanotherUITapGestureRecognizerontheDrawViewthatonlyrequiresonetap.InDrawView.swift,modifyinit?(coder:)toaddthisgesturerecognizer.requiredinit?(coderaDecoder:NSCoder){

super.init(coder:aDecoder)

letdoubleTapRecognizer=UITapGestureRecognizer(target:self,

action:#selector(DrawView.doubleTap(_:)))

doubleTapRecognizer.numberOfTapsRequired=2

doubleTapRecognizer.delaysTouchesBegan=true

addGestureRecognizer(doubleTapRecognizer)

lettapRecognizer=

UITapGestureRecognizer(target:self,action:#selector(DrawView.tap(_:)))

tapRecognizer.delaysTouchesBegan=true

addGestureRecognizer(tapRecognizer)

}

Now,implementtap(_:)inDrawView.swifttologthetaptotheconsole.functap(_gestureRecognizer:UIGestureRecognizer){

print("Recognizedatap")

}

Buildandruntheapplication.Trytappinganddouble-tapping.Tappingoncelogstheappropriatemessagetotheconsole.Double-tapping,however,triggersbothtap(_:)anddoubleTap(_:).Insituationswhereyouhavemultiplegesturerecognizers,itisnotuncommontohaveonegesturerecognizerfireandclaimatouchwhenyoureallywantedanothergesturerecognizertohandleit.Inthesecases,yousetupdependenciesbetweenrecognizersthatsay,“Waitamomentbeforeyoufire,becausethistouchmightbemine!”Ininit?(coder:),makeitsothetapRecognizerwaitsuntilthedoubleTapRecognizerfailstorecognizeadouble-tapbeforeclaimingthesingletapforitself.requiredinit?(coderaDecoder:NSCoder){

super.init(coder:aDecoder)

letdoubleTapRecognizer=UITapGestureRecognizer(target:self,

action:#selector(DrawView.doubleTap(_:)))

doubleTapRecognizer.numberOfTapsRequired=2

doubleTapRecognizer.delaysTouchesBegan=true

addGestureRecognizer(doubleTapRecognizer)

lettapRecognizer=

UITapGestureRecognizer(target:self,action:#selector(DrawView.tap(_:)))

tapRecognizer.delaysTouchesBegan=true

tapRecognizer.require(toFail:doubleTapRecognizer)

addGestureRecognizer(tapRecognizer)

}

Page 557: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Buildandruntheapplicationagainandtryoutsometaps.Asingletapnowtakesasmallamountoftimetofireafterthetapoccurs,butdouble-tappingnolongertriggersthetap(_:)message.Next,let’sbuildontheDrawViewsothattheusercanselectalinewhenitistapped.First,addapropertyatthetopofDrawView.swifttoholdontotheindexofaselectedline.classDrawView:UIView{

varcurrentLines=[NSValue:Line]()

varfinishedLines=[Line]()

varselectedLineIndex:Int?

Nowmodifydraw(_:)todrawtheselectedlineingreen.overridefuncdraw(_rect:CGRect){

finishedLineColor.setStroke()

forlineinfinishedLines{

stroke(line)

}

currentLineColor.setStroke()

for(_,line)incurrentLines{

stroke(line)

}

ifletindex=selectedLineIndex{

UIColor.green.setStroke()

letselectedLine=finishedLines[index]

stroke(selectedLine)

}

}

StillinDrawView.swift,addanindexOfLine(at:)methodthatreturnstheindexoftheLineclosesttoagivenpoint.funcindexOfLine(atpoint:CGPoint)->Int?{

//Findalineclosetopoint

for(index,line)infinishedLines.enumerated(){

letbegin=line.begin

letend=line.end

//Checkafewpointsontheline

fortinstride(from:CGFloat(0),to:1.0,by:0.05){

letx=begin.x+((end.x-begin.x)*t)

lety=begin.y+((end.y-begin.y)*t)

//Ifthetappedpointiswithin20points,let'sreturnthisline

ifhypot(x-point.x,y-point.y)<20.0{

returnindex

}

}

}

//Ifnothingiscloseenoughtothetappedpoint,thenwedidnotselectaline

returnnil

}

Thestride(from:to:by:)methodwillallowttostartatthefromvalueandgoupto(butnotreach)thetovalue,incrementingthevalueoftbythebyvalue.

Page 558: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Thereareother,betterwaystodeterminetheclosestlinetoapoint,butthissimpleimplementationwillworkforyourpurposes.Thepointtobepassedinisthepointwherethetapoccurred.Youcaneasilygetthisinformation.EveryUIGestureRecognizerhasalocation(in:)method.Callingthismethodonthegesturerecognizerwillgiveyouthecoordinatewherethegestureoccurredinthecoordinatesystemoftheviewthatispassedastheargument.InDrawView.swift,updatetap(_:)tocalllocation(in:)onthegesturerecognizer,passtheresulttoindexOfLine(at:),andmakethereturnedindextheselectedLineIndex.functap(_gestureRecognizer:UIGestureRecognizer){

print("Recognizedatap")

letpoint=gestureRecognizer.location(in:self)

selectedLineIndex=indexOfLine(at:point)

setNeedsDisplay()

}

Iftheuserdouble-tapstoclearalllineswhilealineisselected,theapplicationwilltrap.Toaddressthis,updatedoubleTap(_:)tosettheselectedLineIndextonil.funcdoubleTap(_gestureRecognizer:UIGestureRecognizer){

print("Recognizedadoubletap")

selectedLineIndex=nil

currentLines.removeAll()

finishedLines.removeAll()

setNeedsDisplay()

}

Buildandruntheapplication.Drawafewlinesandthentapone.Thetappedlineshouldappearingreen(rememberthatittakesamomentbeforethetapisknownnottobeadouble-tap).

Page 559: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 560: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

UIMenuController

Nextyouaregoingtomakeitsothatwhentheuserselectsaline,amenuwiththeoptiontodeletethatlineappearswheretheusertapped.Thereisabuilt-inclassforprovidingthissortofmenucalledUIMenuController(Figure19.3).AmenucontrollerhasalistofUIMenuItemobjectsandispresentedinanexistingview.Eachitemhasatitle(whatshowsupinthemenu)andanaction(themessageitsendsthefirstresponderofthewindow).Figure19.3AUIMenuController

ThereisonlyoneUIMenuControllerperapplication.Whenyouwishtopresentthisinstance,youfillitwithmenuitems,giveitarectangletopresentfrom,andsetittobevisible.DothisinDrawView.swift’stap(_:)methodiftheuserhastappedonaline.Iftheusertappedsomewherethatisnotnearaline,thecurrentlyselectedlinewillbedeselectedandthemenucontrollerwillhide.functap(_gestureRecognizer:UIGestureRecognizer){

print("Recognizedatap")

letpoint=gestureRecognizer.location(in:self)

selectedLineIndex=indexOfLine(at:point)

//Grabthemenucontroller

letmenu=UIMenuController.shared

ifselectedLineIndex!=nil{

//MakeDrawViewthetargetofmenuitemactionmessages

becomeFirstResponder()

//Createanew"Delete"UIMenuItem

letdeleteItem=UIMenuItem(title:"Delete",

action:#selector(DrawView.deleteLine(_:)))

menu.menuItems=[deleteItem]

//Tellthemenuwhereitshouldcomefromandshowit

lettargetRect=CGRect(x:point.x,y:point.y,width:2,height:2)

menu.setTargetRect(targetRect,in:self)

menu.setMenuVisible(true,animated:true)

}else{

//Hidethemenuifnolineisselected

menu.setMenuVisible(false,animated:true)

}

setNeedsDisplay()

}

Foramenucontrollertoappear,aviewthatrespondstoatleastoneactionmessageintheUIMenuController’smenuitemsmustbethefirstresponderofthewindow–thisiswhyyoucalledthemethodbecomeFirstResponder()ontheDrawViewbeforesettingup

Page 561: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

themenucontroller.Ifyouhaveacustomviewclassthatneedstobecomethefirstresponder,youmustalsooverridecanBecomeFirstResponder.InDrawView.swift,overridethispropertytoreturntrue.overridevarcanBecomeFirstResponder:Bool{

returntrue

}

Finally,implementdeleteLine(_:)inDrawView.swift.funcdeleteLine(_sender:UIMenuController){

//RemovetheselectedlinefromthelistoffinishedLines

ifletindex=selectedLineIndex{

finishedLines.remove(at:index)

selectedLineIndex=nil

//Redraweverything

setNeedsDisplay()

}

}

Whenbeingpresented,themenucontrollergoesthrougheachmenuitemandasksthefirstresponderifitimplementstheactionmethodforthatitem.Ifthefirstresponderdoesnotimplementthatmethod,thenthemenucontrollerwillnotshowtheassociatedmenuitem.Ifnomenuitemshavetheiractionmethodsimplementedbythefirstresponder,themenuisnotshownatall.Buildandruntheapplication.Drawaline,taponit,andthenselectDeletefromthemenuitem.Ifyouselectalineandthendouble-taptoclearalllines,themenucontrollerwillstillbevisible.IftheselectedLineIndexeverbecomesnil,themenucontrollershouldnotbevisible.AddapropertyobservertoselectedLineIndexinDrawView.swiftthatsetsthemenucontrollertobenotvisibleiftheindexissettonil.varselectedLineIndex:Int?{

didSet{

ifselectedLineIndex==nil{

letmenu=UIMenuController.shared

menu.setMenuVisible(false,animated:true)

}

}

}

Buildandruntheapplication.Drawaline,selectit,andthendouble-tapthebackground.Thelineandthemenucontrollerwillnolongerbevisible.

Page 562: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 563: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

MoreGestureRecognizers

Inthissection,youaregoingtoaddtheabilityforausertoselectalinebypressingandholding(alongpress)andthenmovetheselectedlinebydraggingthefinger(apan).ThiswillrequiretwomoresubclassesofUIGestureRecognizer:UILongPressGestureRecognizerandUIPanGestureRecognizer.

UILongPressGestureRecognizer

InDrawView.swift,instantiateaUILongPressGestureRecognizerininit?(coder:)andaddittotheDrawView....

addGestureRecognizer(tapRecognizer)

letlongPressRecognizer=UILongPressGestureRecognizer(target:self,

action:#selector(DrawView.longPress(_:)))

addGestureRecognizer(longPressRecognizer)

}

NowwhentheuserholdsdownontheDrawView,themethodlongPress(_:)willbecalledonit.Bydefault,atouchmustbeheld0.5secondstobecomealongpress,butyoucanchangetheminimumPressDurationofthegesturerecognizerifyoulike.Sofar,youhaveworkedwithtapgestures.Atapisadiscretegesture.Bythetimeitisrecognized,thegestureisover,andtheactionmessagehasbeendelivered.Alongpress,ontheotherhand,isacontinuousgesture.Continuousgesturesoccurovertime.Tokeeptrackofwhatisgoingonwithacontinuousgesture,youcancheckarecognizer ’sstateproperty.Forexample,consideratypicallongpress:

Whentheusertouchesaview,thelong-pressrecognizernoticesapossiblelongpress,butitmustwaittoseewhetherthetouchisheldlongenoughtobecomealong-pressgesture.Therecognizer ’sstateisUIGestureRecognizerState.possible.Oncetheuserholdsthetouchlongenough,thelongpressisrecognizedandthegesturehasbegun.Therecognizer ’sstateisUIGestureRecognizerState.began.Whentheuserremovesthefinger,thegesturehasended.Therecognizer ’sstateisUIGestureRecognizerState.ended.

Whenthelong-pressgesturerecognizertransitionsfrompossibletobeganandfrombegantoended,itsendsitsactionmessagetoitstarget.Todeterminewhichtransitiontriggeredtheaction,youcheckthegesturerecognizer ’sstate.Rememberthatthelongpressispartofalargerfeature.Inthenextsection,youwillenabletheusertomovetheselectedlinebydraggingitwiththesamefingerthatbeganthelongpress.SohereistheplanforimplementingthelongPress(_:)actionmethod:Whentherecognizerisinthebeganstate,youwillselecttheclosestlinetowherethegestureoccurred.Whentherecognizerisintheendedstate,youwilldeselecttheline.

Page 564: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

InDrawView.swift,implementlongPress(_:).funclongPress(_gestureRecognizer:UIGestureRecognizer){

print("Recognizedalongpress")

ifgestureRecognizer.state==.began{

letpoint=gestureRecognizer.location(in:self)

selectedLineIndex=indexOfLine(at:point)

ifselectedLineIndex!=nil{

currentLines.removeAll()

}

}elseifgestureRecognizer.state==.ended{

selectedLineIndex=nil

}

setNeedsDisplay()

}

Buildandruntheapplication.Drawalineandthenpressandholdit;thelinewillturngreenandbecometheselectedline.Whenyouletgo,thelinewillreverttoitsformercolorandwillnolongerbetheselectedline.

UIPanGestureRecognizerandsimultaneousrecognizers

InDrawView.swift,declareaUIPanGestureRecognizerasapropertysothatyouhaveaccesstoitinallofyourmethods.classDrawView:UIView{

varcurrentLines=[NSValue:Line]()

varfinishedLines=[Line]()

varselectedLineIndex:Int?{

...

}

varmoveRecognizer:UIPanGestureRecognizer!

Next,inDrawView.swift,addcodetoinit?(coder:)toinstantiateaUIPanGestureRecognizer,setoneofitsproperties,andaddittotheDrawView.letlongPressRecognizer=UILongPressGestureRecognizer(target:self,

action:#selector(DrawView.longPress(_:)))

addGestureRecognizer(longPressRecognizer)

moveRecognizer=UIPanGestureRecognizer(target:self,

action:#selector(DrawView.moveLine(_:)))

moveRecognizer.cancelsTouchesInView=false

addGestureRecognizer(moveRecognizer)

}

WhatiscancelsTouchesInView?EveryUIGestureRecognizerhasthisproperty,whichdefaultstotrue.WhencancelsTouchesInViewistrue,thegesturerecognizerwill“eat”anytouchitrecognizes,andtheviewwillnotgetachancetohandlethetouchviathetraditionalUIRespondermethods,liketouchesBegan(_:with:).Usually,thisiswhatyouwant,butnotalways.Inthiscase,ifthepangesturerecognizerwere

Page 565: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

toeatitstouches,thenuserswouldnotbeabletodrawlines.WhenyousetcancelsTouchesInViewtofalse,youensurethatanytouchrecognizedbythegesturerecognizerwillalsobedeliveredtotheviewviatheUIRespondermethods.InDrawView.swift,addasimpleimplementationfortheactionmethod:funcmoveLine(_gestureRecognizer:UIPanGestureRecognizer){

print("Recognizedapan")

}

Buildandruntheappanddrawsomelines.BecausecancelsTouchesInViewisfalse,thepangestureisrecognized,butlinescanstillbedrawn.YoucancommentoutthelinethatsetscancelsTouchesInViewandrunagaintoseethedifference.Soon,youwillupdatemoveLine(_:)toredrawtheselectedlineastheuser ’sfingermovesacrossthescreen.Butfirstyouneedtwogesturerecognizerstobeabletohandlethesametouch.Normally,whenagesturerecognizerrecognizesitsgesture,iteatsitandnootherrecognizergetsachancetohandlethattouch.Tryit:Runtheapp,drawaline,pressandholdtoselecttheline,andthenmoveyourfingeraround.Theconsolereportsthelongpressbutnotthepan.Inthiscase,thedefaultbehaviorisproblematic:Youruserswillpressandholdtoselectalineandthenpantomovetheline–withoutliftingthefingerinbetween.Thus,thetwogestureswilloccursimultaneously,andthepangesturerecognizermustbeallowedtorecognizeapaneventhoughthelong-pressgesturehasalreadyrecognizedalongpress.Toallowagesturerecognizertorecognizeitsgesturesimultaneouslywithanothergesturerecognizer,youimplementamethodfromtheUIGestureRecognizerDelegateprotocol:optionalfuncgestureRecognizer(_gestureRecognizer:UIGestureRecognizer,

shouldRecognizeSimultaneouslyWith

otherGestureRecognizer:UIGestureRecognizer)->Bool

Thefirstparameteristhegesturerecognizerthatisaskingforguidance.Itsaystoitsdelegate,“Sothere’smeandthisotherrecognizer,andoneofusjustrecognizedagesture.Shouldtheonewhodidnotrecognizeitstayinthepossiblestateandcontinuetotrackthistouch?”Notethatthecallitselfdoesnottellyouwhichofthetworecognizershasrecognizeditsgesture–and,thus,whichofthemwillpotentiallybedeprivedofthechancetorecognizeitsgesture.Bydefault,themethodreturnsfalse,andthegesturerecognizerstillinthepossiblestateleavesthetouchinthehandsofthegesturealreadyintherecognizedstate.Youcanimplementthemethodtoreturntruetoallowbothrecognizerstorecognizetheirgesturesinthesametouch.(Ifyouneedtodeterminewhichofthetworecognizershasrecognizeditsgesture,youcanchecktherecognizers’stateproperties.)Toenablepanningwhilelongpressing,youaregoingtogivethepangesturerecognizeradelegate(theDrawView).Then,whenthelong-pressrecognizerrecognizesitsgesture,thepangesturerecognizerwillcallthesimultaneousrecognitionmethodonitsdelegate.YouwillimplementthismethodinDrawViewtoreturntrue.Thiswillallowthepangesturerecognizertorecognizeanypanningthatoccurswhilealongpressisinprogress.

Page 566: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

First,inDrawView.swift,declarethatDrawViewconformstotheUIGestureRecognizerDelegateprotocol.classDrawView:UIView,UIGestureRecognizerDelegate{

varcurrentLines=[NSValue:Line]()

varfinishedLines=[Line]()

varselectedLineIndex:Int?{

...

}

varmoveRecognizer:UIPanGestureRecognizer!

Next,ininit?(coder:),settheDrawViewtobethedelegateoftheUIPanGestureRecognizer.letlongPressRecognizer=UILongPressGestureRecognizer(target:self,

action:#selector(DrawView.longPress(_:)))

addGestureRecognizer(longPressRecognizer)

moveRecognizer=UIPanGestureRecognizer(target:self,

action:#selector(DrawView.moveLine(_:)))

moveRecognizer.delegate=self

moveRecognizer.cancelsTouchesInView=false

addGestureRecognizer(moveRecognizer)

}

Finally,inDrawView.swift,implementthedelegatemethodtoreturntrue.funcgestureRecognizer(_gestureRecognizer:UIGestureRecognizer,

shouldRecognizeSimultaneouslyWith

otherGestureRecognizer:UIGestureRecognizer)->Bool{

returntrue

}

Forthissituation,whereonlyyourpangesturerecognizerhasadelegate,thereisnoneedtodomorethanreturntrue.Inmorecomplicatedscenarios,youwouldusethepassed-ingesturerecognizerstomorecarefullycontrolsimultaneousrecognition.Now,whenalongpressbegins,theUIPanGestureRecognizerwillcontinuetokeeptrackofthetouch,andiftheuser ’sfingerbeginstomove,thepanrecognizerwillrecognizethepan.Toseethedifference,runtheapp,drawaline,selectit,andthenpan.Theconsolewillreportbothgestures.(TheUIGestureRecognizerDelegateprotocolincludesothermethodstohelpyoutweakthebehaviorofyourgesturerecognizers.Visittheprotocolreferencepageformoreinformation.)Inadditiontothestatesyouhavealreadyseen,apangesturerecognizersupportsthechangedstate.Whenafingerstartstomove,thepanrecognizerentersthebeganstateandcallsamethodonitstarget.Whilethefingermovesaroundthescreen,therecognizertransitionstothechangedstateandcallstheactionmethodonitstargetrepeatedly.Whenthefingerleavesthescreen,therecognizer ’sstateissettoended,andthemethodiscalledonthetargetforthefinaltime.ThenextstepistoimplementthemoveLine(_:)methodthatthepanrecognizercallsonitstarget.Inthisimplementation,youwillcallthemethodtranslationInView(_:)onthe

Page 567: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

panrecognizer.ThisUIPanGestureRecognizermethodreturnshowfarthepanhasmovedasaCGPointinthecoordinatesystemoftheviewpassedastheargument.Whenthepangesturebegins,thispropertyissettothezeropoint(wherexandyare0).Asthepanmoves,thisvalueisupdated–ifthepangoesfartotheright,ithasahighxvalue;ifthepanreturnstowhereitbegan,itstranslationgoesbacktothezeropoint.InDrawView.swift,implementmoveLine(_:).NoticethatbecauseyouwillsendthegesturerecognizeramethodfromtheUIPanGestureRecognizerclass,theparameterofthismethodmustbeareferencetoaninstanceofUIPanGestureRecognizerratherthanUIGestureRecognizer.funcmoveLine(_gestureRecognizer:UIPanGestureRecognizer){

print("Recognizedapan")

//Ifalineisselected...

ifletindex=selectedLineIndex{

//Whenthepanrecognizerchangesitsposition...

ifgestureRecognizer.state==.changed{

//Howfarhasthepanmoved?

lettranslation=gestureRecognizer.translation(in:self)

//Addthetranslationtothecurrentbeginningandendpointsoftheline

//Makesuretherearenocopyandpastetypos!

finishedLines[index].begin.x+=translation.x

finishedLines[index].begin.y+=translation.y

finishedLines[index].end.x+=translation.x

finishedLines[index].end.y+=translation.y

//Redrawthescreen

setNeedsDisplay()

}

}else{

//Ifnolineisselected,donotdoanything

return

}

}

Buildandruntheapplication.Touchandholdonalineandbegindragging–andyouwillimmediatelynoticethatthelineandyourfingerarewayoutofsync.Whatisgoingon?Youareaddingthecurrenttranslationoverandoveragaintotheline’soriginalendpoints.Youreallyneedthegesturerecognizertoreportthechangeintranslationsincethelasttimethismethodwascalledinstead.Fortunately,youcandothis.Youcansetthetranslationofapangesturerecognizerbacktothezeropointeverytimeitreportsachange.Then,thenexttimeitreportsachange,itwillhavethetranslationsincethelastevent.NearthebottomofmoveLine(_:)inDrawView.swift,addthefollowinglineofcode.finishedLines[index].end.x+=translation.x

finishedLines[index].end.y+=translation.y

gestureRecognizer.setTranslation(CGPoint.zero,in:self)

//Redrawthescreen

setNeedsDisplay()

Buildandruntheapplicationandmovealinearound.Worksgreat!

Page 568: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 569: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

MoreonUIGestureRecognizer

YouhaveonlyscratchedthesurfaceofUIGestureRecognizer.Therearemoresubclasses,moreproperties,andmoredelegatemethods–andyoucanevencreaterecognizersofyourown.ThissectionwillgiveyouanideaofwhatUIGestureRecognizeriscapableof.Youcanstudythedocumentationtolearnevenmore.Whenagesturerecognizerisonaview,itisreallyhandlingalloftheUIRespondermethods,liketouchesBegan(_:with:),foryou.Gesturerecognizersareprettygreedy,sotheytypicallydonotletaviewreceivetouchevents,ortheyatleastdelaythedeliveryofthoseevents.Youcansetpropertiesontherecognizer,likedelaysTouchesBegan,delaysTouchesEnded,andcancelsTouchesInView,tochangethisbehavior.Ifyouneedfinercontrolthanthisall-or-nothingapproach,youcanimplementdelegatemethodsfortherecognizer.Attimes,youmayhavetwogesturerecognizerslookingforverysimilargestures.Youcanchainrecognizerstogethersothatoneisrequiredtofailforthenextonetostartusingthemethodrequire(toFail:).Youusedthismethodininit?(coder:)tomakethetaprecognizerwaitforthedouble-taprecognizertofail.Onethingyoumustunderstandtomastergesturerecognizersishowtheyinterprettheirstate.Overall,therearesevenstatesarecognizercanenter:

UIGestureRecognizerState.possible

UIGestureRecognizerState.failed

UIGestureRecognizerState.began

UIGestureRecognizerState.cancelled

UIGestureRecognizerState.changed

UIGestureRecognizerState.recognized

UIGestureRecognizerState.ended

Thepossiblestateiswhererecognizersspendmostoftheirtime.Whenagesturetransitionstoanystateotherthanthepossiblestateorthefailedstate,theactionmessageoftherecognizerissentanditsstatepropertycanbecheckedtoseewhy.Thefailedstateisusedbyrecognizerswatchingforamultitouchgesture.Atsomepoint,theuser ’sfingersmayachieveapositionfromwhichtheycannolongermakethatrecognizer ’sgesture.Atthatpoint,thegesturerecognizerfails.Arecognizerentersthecanceledstatewhenitisinterrupted,suchasbyanincomingphonecall.Ifagestureiscontinuous,likeapan,thegesturerecognizerwillenterthebeganstateandthengointothechangedstateuntilthegestureends.Whenthegestureends(oriscanceled),therecognizerenterstheended(orcanceled)stateandsendsitsactionmessageafinaltimebeforereturningtothepossiblestate.

Page 570: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Forgesturerecognizersthatpickuponadiscretegesturelikeatap,youwillonlyseetherecognizedstate(whichhasthesamevalueastheendedstate).Thefourbuilt-inrecognizersthatyoudidnotimplementinthischapterareUIPinchGestureRecognizer,UISwipeGestureRecognizer,UIScreenEdgePanGestureRecognizer,andUIRotationGestureRecognizer.Eachhaspropertiesthatallowyoutofine-tuneitsbehavior.Thedocumentationwillshowyouhow.Finally,ifthereisagesturethatyouwanttorecognizethatisnotimplementedbythebuilt-insubclassesofUIGestureRecognizer,youcansubclassUIGestureRecognizeryourself.Thisisanintenseundertakingandoutsidethescopeofthisbook.YoucanreadtheMethodsforSubclassingsectionoftheUIGestureRecognizerdocumentationtolearnwhatisrequired.

Page 571: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 572: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

SilverChallenge:MysteriousLines

Thereisabugintheapplication.Ifyoutaponalineandthenstartdrawinganewonewhilethemenuisvisible,youwilldragtheselectedlineanddrawanewlineatthesametime.Fixthisbug.

Page 573: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 574: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

GoldChallenge:SpeedandSize

Piggy-backoffofthepangesturerecognizertorecordthevelocityofthepanwhenyouaredrawingaline.Adjustthethicknessofthelinebeingdrawnbasedonthisspeed.Makenoassumptionsabouthowsmallorlargethevelocityvalueofthepanrecognizercanbe.(Inotherwords,logavarietyofvelocitiestotheconsolefirst.)

Page 575: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 576: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

PlatinumChallenge:Colors

Haveathree-fingerswipeupwardbringupapanelthatshowscolors.Selectingoneofthosecolorsshouldmakeanylinesyoudrawafterwardappearinthatcolor.Noextralinesshouldbedrawnbyputtingupthatpanel–oranylinesdrawnshouldbeimmediatelydeletedwhentheapplicationrealizesthatitisdealingwithathree-fingerswipe.

Page 577: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 578: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

FortheMoreCurious:UIMenuControllerandUIResponderStandardEditActions

TheUIMenuControlleristypicallyresponsibleforshowingtheuseran“edit”menuwhenitisdisplayed.(Thinkofatextfieldortextviewwhenyoupressandhold.)Therefore,anunmodifiedmenucontroller(onethatyoudonotsetthemenuitemsfor)alreadyhasdefaultmenuitemsthatitpresents,likeCut,Copy,andotherfamiliaroptions.Eachitemhasanactionmessagewiredup.Forexample,cut:issenttotheviewpresentingthemenucontrollerwhentheCutmenuitemistapped.AllinstancesofUIResponderimplementthesemethods,but,bydefault,thesemethodsdonotdoanything.SubclasseslikeUITextFieldoverridethesemethodstodosomethingappropriatefortheircontext,likecutthecurrentlyselectedtext.ThemethodsarealldeclaredintheUIResponderStandardEditActionsprotocol.IfyouoverrideamethodfromUIResponderStandardEditActionsinaview,itsmenuitemwillautomaticallyappearinanymenuyoushowforthatview.ThisworksbecausethemenucontrollercallsthemethodcanPerformAction(_:withSender:)onitsview,whichreturnstrueorfalsedependingonwhethertheviewimplementsthismethod.Ifyouwanttoimplementoneofthesemethodsbutdonotwantittoappearinthemenu,youcanoverridecanPerformAction(_:withSender:)toreturnfalse:overridefunccanPerformAction(_action:Selector,

withSendersender:Any?)->Bool{

ifaction==#selector(copy(_:)){

returnfalse

}else{

//Elsereturnthedefaultbehavior

returnsuper.canPerformAction(action,withSender:sender)

}

}

Page 579: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 580: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

20WebServices

Inthenextfourchapters,youwillcreateanapplicationnamedPhotoramathatreadsinalistofinterestingphotosfromFlickr.Thischapterwilllaythefoundationandfocusonimplementingthewebservicerequestsresponsibleforfetchingthemetadataforinterestingphotosaswellasdownloadingtheimagedataforaspecificphoto.InChapter21,youwilldisplayalloftheinterestingphotosinagridlayout.Figure20.1showsPhotoramaattheendofthischapter.Figure20.1Photorama

YourwebbrowserusesHTTPtocommunicatewithawebserver.Inthesimplestinteraction,thebrowsersendsarequesttotheserverspecifyingaURL.Theserverrespondsbysendingbacktherequestedpage(typicallyHTMLandimages),whichthebrowserformatsanddisplays.Inmorecomplexinteractions,browserrequestsincludeotherparameters,suchasformdata.Theserverprocessestheseparametersandreturnsacustomized,ordynamic,webpage.Webbrowsersarewidelyusedandhavebeenaroundforalongtime,sothetechnologiessurroundingHTTParestableandwelldeveloped:HTTPtrafficpassesneatlythroughmostfirewalls,webserversareverysecureandhavegreatperformance,andwebapplicationdevelopmenttoolshavebecomeeasytouse.YoucanwriteaclientapplicationforiOSthatleveragestheHTTPinfrastructuretotalktoaweb-enabledserver.Theserversideofthisapplicationisawebservice.Yourclient

Page 581: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

applicationandthewebservicecanexchangerequestsandresponsesviaHTTP.BecauseHTTPdoesnotcarewhatdataittransports,theseexchangescancontaincomplexdata.ThisdataistypicallyinJSON(JavaScriptObjectNotation)orXMLformat.Ifyoucontrolthewebserveraswellastheclient,youcanuseanyformatyoulike.Ifnot,youhavetobuildyourapplicationtousewhatevertheserversupports.PhotoramawillmakeawebservicerequesttogetinterestingphotosfromFlickr.Thewebserviceishostedathttps://api.flickr.com/services/rest.ThedatathatisreturnedwillbeJSONthatdescribesthephotos.

Page 582: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

StartingthePhotoramaApplication

CreateanewSingleViewApplicationfortheUniversaldevicefamily.NamethisapplicationPhotorama,asshowninFigure20.2.Figure20.2Creatingasingleviewapplication

Let’sknockoutthebasicUIbeforefocusingonwebservices.CreateanewSwiftfilenamedPhotosViewController.InPhotosViewController.swift,definethePhotosViewControllerclassandgiveitanimageViewproperty.importFoundation

importUIKit

classPhotosViewController:UIViewController{

@IBOutletvarimageView:UIImageView!

}

Intheprojectnavigator,deletetheexistingViewController.swift.OpenMain.storyboardandselecttheViewController.OpenitsidentityinspectorandchangetheClasstoPhotosViewController.WiththePhotosViewControllerstillselected,selecttheEditormenuandchooseEmbedIn→NavigationController.SelecttheNavigationControllerandopenitsattributesinspector.UndertheViewControllerheading,makesuretheboxforIsInitialViewControllerischecked.DraganImageViewontothecanvasforPhotosViewControllerandaddconstraintstopinittoalledgesofthesuperview.ConnecttheimageviewtotheimageViewoutleton

Page 583: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

PhotosViewController.OpentheattributesinspectorfortheimageviewandchangetheContentModetoAspectFill.Finally,double-clickonthecenterofthenavigationbarforthePhotosViewControllerandgiveitatitleof“Photorama.”YourinterfacewilllooklikeFigure20.3.Figure20.3InitialPhotoramainterface

Buildandruntheapplicationtomakesuretherearenoerrors.

Page 584: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 585: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

BuildingtheURL

Communicationwithserversisdoneviarequests.Arequestencapsulatesinformationabouttheinteractionbetweentheapplicationandtheserver,anditsmostimportantpieceofinformationisthedestinationURL.Inthissection,youwillbuilduptheURLforretrievinginterestingphotosfromtheFlickrwebservice.Thearchitectureoftheapplicationwillreflectbestpractices.Forexample,eachtypethatyoucreatewillencapsulateasingleresponsibility.Thiswillmakeyourtypesrobustandflexibleandyourapplicationeasiertoreasonabout.TobeagoodiOSdeveloper,younotonlyneedtogetthejobdone,butyoualsoneedtogetitdonethoughtfullyandwithforesight.

FormattingURLsandrequests

Theformatofawebservicerequestvariesdependingontheserverthattherequestisreachingoutto.Therearenoset-in-stoneruleswhenitcomestowebservices.Youwillneedtofindthedocumentationforthewebservicetoknowhowtoformatarequest.Aslongasaclientapplicationsendstheserverwhatitwants,youhaveaworkingexchange.Flickr ’sinterestingphotoswebservicewantsaURLthatlookslikethis:https://api.flickr.com/services/rest/?method=flickr.interestingness.getList

&api_key=a6d819499131071f158fd740860a5a88&extras=url_h,date_taken

&format=json&nojsoncallback=1

Webservicerequestscomeinallsortsofformats,dependingonwhatthecreatorofthatwebserviceistryingtoaccomplish.Theinterestingphotoswebservice,wherepiecesofinformationarebrokenupintokey-valuepairs,isprettycommon.Thekey-valuepairsthataresuppliedaspartoftheURLarecalledqueryitems.EachofthequeryitemsfortheinterestingphotosrequestisdefinedbyandisuniquetotheFlickrAPI.

ThemethoddetermineswhichendpointyouwanttohitontheFlickrAPI.Fortheinterestingphotos,thisisthestring"flickr.interestingness.getList".Theapi_keyisakeythatFlickrgeneratestoauthorizeanapplicationtousetheFlickrAPI.Theextrasareattributespassedintocustomizetheresponse.Here,theurl_h,date_takenvaluetellstheFlickrserverthatyouwantthephotoURLstoalsocomebackintheresponsealongwiththedatethephotowastaken.TheformatitemspecifiesthatyouwantthepayloadcomingbacktobeJSON.ThenojsoncallbackitemspecifiesthatyouwantJSONbackinitsrawformat.

URLComponents

Page 586: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Youwillcreatetwotypestodealwithallofthewebserviceinformation.TheFlickrAPIstructwillberesponsibleforknowingandhandlingallFlickr-relatedinformation.ThisincludesknowinghowtogeneratetheURLsthattheFlickrAPIexpectsaswellasknowingtheformatoftheincomingJSONandhowtoparsethatJSONintotherelevantmodelobjects.ThePhotoStoreclasswillhandletheactualwebservicecalls.Let’sstartbycreatingtheFlickrAPIstruct.CreateanewSwiftfilenamedFlickrAPIanddeclaretheFlickrAPIstruct,whichwillcontainalloftheknowledgethatisspecifictotheFlickrAPI.importFoundation

structFlickrAPI{

}

YouaregoingtouseanenumerationtospecifywhichendpointontheFlickrservertohit.Forthisapplication,youwillonlybeworkingwiththeendpointtogetinterestingphotos.However,FlickrsupportsmanyadditionalAPIs,suchassearchingforimagesbasedonastring.Usinganenumnowwillmakeiteasiertoaddendpointsinthefuture.InFlickrAPI.swift,createtheMethodenumeration.EachcaseofMethodhasarawvaluethatmatchesthecorrespondingFlickrendpoint.importFoundation

enumMethod:String{

caseinterestingPhotos="flickr.interestingness.getList"

}

structFlickrAPI{

}

InChapter2,youlearnedthatenumerationscanhaverawvaluesassociatedwiththem.AlthoughtherawvaluesareoftenInts,youcanseehereagreatuseofStringastherawvaluefortheMethodenumeration.Nowdeclareatype-levelpropertytoreferencethebaseURLstringforthewebservicerequests.enumMethod:String{

caseinterestingPhotos="flickr.interestingness.getList"

}

structFlickrAPI{

staticletbaseURLString="https://api.flickr.com/services/rest"

}

Atype-levelproperty(ormethod)isonethatisaccessedonthetypeitself–inthiscase,theFlickrAPItype.Forstructs,typepropertiesandmethodsaredeclaredwiththestatickeyword;classesusetheclasskeyword.YouusedatypemethodontheUIViewclassinChapter8whenyoucalledtheanimate(withDuration:animations:)method.YoualsousedatypemethodonUIImagePickerControllerinChapter15whenyoucalled

Page 587: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

theisSourceTypeAvailable(_:)method.Here,youaredeclaringatype-levelpropertyonFlickrAPI.ThebaseURLStringisanimplementationdetailoftheFlickrAPItype,andnoothertypeneedstoknowaboutit.Instead,theywillaskforacompletedURLfromFlickrAPI.TokeepotherfilesfrombeingabletoaccessbaseURLString,markthepropertyasprivate.structFlickrAPI{

privatestaticletbaseURLString="https://api.flickr.com/services/rest"

}

Thisiscalledaccesscontrol.Youcancontrolwhatcanaccessthepropertiesandmethodsonyourowntypes.Therearefivelevelsofaccesscontrolthatcanbeappliedtotypes,properties,andmethods:

open–Thisisusedonlyforclasses,andmostlybyframeworkorthird-partylibraryauthors.Anythingcanaccessthisclass,property,ormethod.Additionally,classesmarkedasopencanbesubclassedandmethodscanbeoverriddenoutsideofthemodule.public–Thisisverysimilartoopen;however,classescanonlybesubclassedandmethodscanonlybeoverriddeninside(notoutsideof)themodule.internal–Thisisthedefault.Anythinginthecurrentmodulecanaccessthistype,property,ormethod.Foranapp,onlyfileswithinyourprojectcanaccessthese.Ifyouwriteathird-partylibrary,thenonlyfileswithinthatthird-partylibrarycanaccessthem–appsthatuseyourthird-partylibrarycannot.fileprivate–Anythinginthesamesourcefilecanseethistype,property,ormethod.private–Anythingwithintheenclosingscopecanaccessthistype,property,ormethod.

NowyouaregoingtocreateatypemethodthatbuildsuptheFlickrURLforaspecificendpoint.Thismethodwillaccepttwoarguments:ThefirstwillspecifywhichendpointtohitusingtheMethodenumeration,andthesecondwillbeanoptionaldictionaryofqueryitemparametersassociatedwiththerequest.ImplementthismethodinyourFlickrAPIstructinFlickrAPI.swift.Fornow,thismethodwillreturnanemptyURL.privatestaticfuncflickrURL(method:Method,

parameters:[String:String]?)->URL{

returnURL(string:"")!

}

NoticethattheflickrURL(method:parameters:)methodisprivate.ItisanimplementationdetailoftheFlickrAPIstruct.AninternaltypemethodwillbeexposedtotherestoftheprojectforeachofthespecificendpointURLs(currently,justtheinterestingphotosendpoint).TheseinternaltypemethodswillcallthroughtotheflickrURL(method:parameters:)method.InFlickrAPI.swift,defineandimplementtheinterestingPhotosURLcomputedproperty.staticvarinterestingPhotosURL:URL{

Page 588: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

returnflickrURL(method:.interestingPhotos,

parameters:["extras":"url_h,date_taken"])

}

TimetoconstructthefullURL.YouhavethebaseURLdefinedasaconstant,andthequeryitemsarebeingpassedintotheflickrURL(method:parameters:)methodviatheparametersargument.YouwillbuilduptheURLusingtheURLComponentsclass,whichisdesignedtotakeinthesevariouscomponentsandconstructaURLfromthem.UpdatetheflickrURL(method:parameters:)methodtoconstructaninstanceofURLComponentsfromthebaseURL.Then,loopovertheincomingparametersandcreatetheassociatedURLQueryIteminstances.privatestaticfuncflickrURL(method:Method,

parameters:[String:String]?)->URL{

returnURL(string:"")!

varcomponents=URLComponents(string:baseURLString)!

varqueryItems=[URLQueryItem]()

ifletadditionalParams=parameters{

for(key,value)inadditionalParams{

letitem=URLQueryItem(name:key,value:value)

queryItems.append(item)

}

}

components.queryItems=queryItems

returncomponents.url!

}

ThelaststepinsettinguptheURListopassintheparametersthatarecommontoallrequests:method,api_key,format,andnojsoncallback.TheAPIkeyisatokengeneratedbyFlickrtoidentifyyourapplicationandauthenticateitwiththewebservice.WehavegeneratedanAPIkeyforthisapplicationbycreatingaFlickraccountandregisteringthisapplication.(IfyouwouldlikeyourownAPIkey,youwillneedtoregisteranapplicationatwww.flickr.com/services/apps/create.)InFlickrAPI.swift,createaconstantthatreferencesthistoken.structFlickrAPI{

privatestaticletbaseURLString="https://api.flickr.com/services/rest"

privatestaticletapiKey="a6d819499131071f158fd740860a5a88"

Double-checktomakesureyouhavetypedintheAPIkeyexactlyaspresentedhere.Ithastomatchortheserverwillrejectyourrequests.IfyourAPIkeyisnotworkingorifyouhaveanyproblemswiththerequests,checkouttheforumsatforums.bignerdranch.comforhelp.FinishimplementingflickrURL(method:parameters:)toaddthecommonqueryitemstotheURLComponents.privatestaticfuncflickrURL(method:Method,

parameters:[String:String]?)->URL{

Page 589: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

varcomponents=URLComponents(string:baseURLString)!

varqueryItems=[URLQueryItem]()

letbaseParams=[

"method":method.rawValue,

"format":"json",

"nojsoncallback":"1",

"api_key":apiKey

]

for(key,value)inbaseParams{

letitem=URLQueryItem(name:key,value:value)

queryItems.append(item)

}

ifletadditionalParams=parameters{

for(key,value)inadditionalParams{

letitem=URLQueryItem(name:key,value:value)

queryItems.append(item)

}

}

components.queryItems=queryItems

returncomponents.url!

}

Page 590: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 591: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

SendingtheRequest

AURLrequestencapsulatesinformationaboutthecommunicationfromtheapplicationtotheserver.Mostimportantly,itspecifiestheURLoftheserverfortherequest,butitalsohasatimeoutinterval,acachepolicy,andothermetadataabouttherequest.ArequestisrepresentedbytheURLRequestclass.CheckouttheFortheMoreCurioussectionattheendofthischapterformoreinformation.TheURLSessionAPIisacollectionofclassesthatusearequesttocommunicatewithaserverinanumberofways.TheURLSessionTaskclassisresponsibleforcommunicatingwithaserver.TheURLSessionclassisresponsibleforcreatingtasksthatmatchagivenconfiguration.InPhotorama,anewclass,PhotoStore,willberesponsibleforinitiatingthewebservicerequests.ItwillusetheURLSessionAPIandtheFlickrAPIstructtofetchalistofinterestingphotosanddownloadtheimagedataforeachphoto.CreateanewSwiftfilenamedPhotoStoreanddeclarethePhotoStoreclass.importFoundation

classPhotoStore{

}

URLSession

Let’slookatafewofthepropertiesonURLRequest:allHTTPHeaderFields–adictionaryofmetadataabouttheHTTPtransaction,includingcharacterencodingandhowtheservershouldhandlecachingallowsCellularAccess–aBooleanthatrepresentswhetherarequestisallowedtousecellulardatacachePolicy–thepropertythatdetermineswhetherandhowthelocalcacheshouldbeusedhttpMethod–therequestmethod;thedefaultisGET,andothervaluesarePOST,PUT,andDELETEtimeoutInterval–themaximumdurationaconnectiontotheserverwillbeattemptedfor

TheclassthatcommunicateswiththewebserviceisaninstanceofURLSessionTask.Therearethreekindsoftasks:datatasks,downloadtasks,anduploadtasks.URLSessionDataTaskretrievesdatafromtheserverandreturnsitasDatainmemory.URLSessionDownloadTaskretrievesdatafromtheserverandreturnsitasafilesavedtothefilesystem.URLSessionUploadTasksendsdatatotheserver.

Page 592: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Often,youwillhaveagroupofrequeststhathavemanypropertiesincommon.Forexample,maybesomedownloadsshouldneverhappenovercellulardata,ormaybecertainrequestsshouldbecacheddifferentlythanothers.Itcanbecometedioustoconfigurerelatedrequeststhesameway.ThisiswhereURLSessioncomesinhandy.URLSessionactsasafactoryforURLSessionTaskinstances.Thesessioniscreatedwithaconfigurationthatspecifiespropertiesthatarecommonacrossallofthetasksthatitcreates.AlthoughmanyapplicationsmightonlyneedtouseasingleinstanceofURLSession,havingthepowerandflexibilityofmultiplesessionsisagreattooltohaveatyourdisposal.InPhotoStore.swift,addapropertytoholdontoaninstanceofURLSession.classPhotoStore{

privateletsession:URLSession={

letconfig=URLSessionConfiguration.default

returnURLSession(configuration:config)

}()

}

InPhotoStore.swift,implementthefetchInterestingPhotos()methodtocreateaURLRequestthatconnectstoapi.flickr.comandasksforthelistofinterestingphotos.Then,usetheURLSessiontocreateaURLSessionDataTaskthattransfersthisrequesttotheserver.funcfetchInterestingPhotos(){

leturl=FlickrAPI.interestingPhotosURL

letrequest=URLRequest(url:url)

lettask=session.dataTask(with:request){

(data,response,error)->Voidin

ifletjsonData=data{

ifletjsonString=String(data:jsonData,

encoding:.utf8){

print(jsonString)

}

}elseifletrequestError=error{

print("Errorfetchinginterestingphotos:\(requestError)")

}else{

print("Unexpectederrorwiththerequest")

}

}

task.resume()

}

CreatingtheURLRequestisfairlystraightforward:YoucreateaURLinstanceusingtheFlickrAPIstructandinstantiatearequestobjectwithit.Bygivingthesessionarequestandacompletionclosuretocallwhentherequestfinishes,thesessionwillreturnaninstanceofURLSessionTask.BecausePhotoramaisrequestingdatafromawebservice,thetypeoftaskwillbeaninstanceofURLSessionDataTask.Tasksarealwayscreatedinthesuspendedstate,socallingresume()onthetaskwillstartthewebservicerequest.Fornow,thecompletionblockwilljustprintouttheJSONdatareturnedfrom

Page 593: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

therequest.Tomakearequest,PhotosViewControllerwillcalltheappropriatemethodsonPhotoStore.Todothis,PhotosViewControllerneedsareferencetoaninstanceofPhotoStore.AtthetopofPhotosViewController.swift,addapropertytohangontoaninstanceofPhotoStore.classPhotosViewController:UIViewController{

@IBOutletvarimageView:UIImageView!

varstore:PhotoStore!

ThestoreisadependencyofthePhotosViewController.YouwillusepropertyinjectiontogivethePhotosViewControlleritsstoredependency,justasyoudidwiththeviewcontrollersinHomepwner.OpenAppDelegate.swiftandusepropertyinjectiontogivethePhotosViewControlleraninstanceofPhotoStore.funcapplication(_application:UIApplication,didFinishLaunchingWithOptions

launchOptions:[UIApplicationLaunchOptionsKey:Any]?)->Bool{

//Overridepointforcustomizationafterapplicationlaunch.

letrootViewController=window!.rootViewControlleras!UINavigationController

letphotosViewController=

rootViewController.topViewControlleras!PhotosViewController

photosViewController.store=PhotoStore()

returntrue

}

NowthatthePhotosViewControllercaninteractwiththePhotoStore,kickoffthewebserviceexchangewhentheviewcontrolleriscomingonscreenforthefirsttime.InPhotosViewController.swift,overrideviewDidLoad()andfetchtheinterestingphotos.overridefuncviewDidLoad(){

super.viewDidLoad()

store.fetchInterestingPhotos()

}

Buildandruntheapplication.AstringrepresentationoftheJSONdatacomingbackfromthewebservicewillprinttotheconsole.(Ifyoudonotseeanythingprinttotheconsole,makesureyoutypedtheURLandAPIkeycorrectly.)TheresponsewilllooksomethinglikeFigure20.4.

Page 594: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure20.4Webserviceconsoleoutput

Page 595: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 596: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

ModelingthePhoto

Next,youwillcreateaPhotoclasstorepresenteachphotothatisreturnedfromthewebservicerequest.Therelevantpiecesofinformationthatyouwillneedforthisapplicationaretheid,thetitle,theurl_h,andthedatetaken.CreateanewSwiftfilecalledPhotoanddeclarethePhotoclasswithpropertiesforthephotoID,thetitle,andtheremoteURL.Finally,addadesignatedinitializerthatsetsuptheinstance.importFoundation

classPhoto{

lettitle:String

letremoteURL:URL

letphotoID:String

letdateTaken:Date

init(title:String,photoID:String,remoteURL:URL,dateTaken:Date){

self.title=title

self.photoID=photoID

self.remoteURL=remoteURL

self.dateTaken=dateTaken

}

}

YouwillusethisclassshortlyonceyouareparsingtheJSONdata.

Page 597: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 598: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

JSONData

JSONdata,especiallywhenitiscondensedlikeitisinyourconsole,mayseemdaunting.However,itisactuallyaverysimplesyntax.JSONcancontainthemostbasictypesusedtorepresentmodelobjects:arrays,dictionaries,strings,andnumbers.AJSONdictionarycontainsoneormorekey-valuepairs,wherethekeyisastringandthevaluecanbeanotherdictionaryorastring,number,orarray.Anarraycanconsistofstrings,numbers,dictionaries,andotherarrays.Thus,aJSONdocumentisanestedsetofthesetypesofvalues.HereisanexampleofsomereallysimpleJSON:{

"name":"Christian",

"friends":["Stacy","Mikey"],

"job":{

"company":"BigNerdRanch",

"title":"SeniorNerd"

}

}

ThisJSONdocumentbeginsandendswithcurlybraces({and}),whichinJSONdelimitadictionary.Withinthecurlybracesarethekey-valuepairsthatbelongtothedictionary.Thisdictionarycontainsthreekey-valuepairs(name,friends,andjob).Astringisrepresentedbytextwithinquotationmarks.Stringsareusedasthekeyswithinadictionaryandcanbeusedasvalues,too.Thus,thevalueassociatedwiththenamekeyinthetop-leveldictionaryisthestringChristian.Arraysarerepresentedwithsquarebrackets([and]).AnarraycancontainanyotherJSONinformation.Inthiscase,thefriendskeyholdsanarrayofstrings(StacyandMikey).Adictionarycancontainotherdictionaries,andthefinalkeyinthetop-leveldictionary,job,isassociatedwithadictionarythathastwokey-valuepairs(companyandtitle).PhotoramawillparseouttheusefulinformationfromtheJSONdataandstoreitinaPhotoinstance.

JSONSerialization

Applehasabuilt-inclassforparsingJSONdata,JSONSerialization.YoucanhandthisclassabunchofJSONdata,anditwillcreateadictionaryforeveryJSONdictionary(theJSONspecificationcallsthese“objects”),anarrayforeveryJSONarray,aStringforeveryJSONstring,andanNSNumberforeveryJSONnumber.Let’sseehowthisclasshelpsyou.OpenPhotoStore.swiftandupdatefetchInterestingPhotos()toprinttheJSONobjecttotheconsole.funcfetchInterestingPhotos(){

leturl=FlickrAPI.interestingPhotosURL

Page 599: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

letrequest=URLRequest(url:url)

lettask=session.dataTask(with:request){

(data,response,error)->Voidin

ifletjsonData=data{

ifletjsonString=String(data:jsonData,

encoding:.utf8){

print(jsonString)

}

do{

letjsonObject=tryJSONSerialization.jsonObject(with:jsonData,

options:[])

print(jsonObject)

}catchleterror{

print("ErrorcreatingJSONobject:\(error)")

}

}elseifletrequestError=error{

print("Errorfetchinginterestingphotos:\(requestError)")

}else{

print("Unexpectederrorwiththerequest")

}

}

task.resume()

}

Buildandruntheapplication,thenchecktheconsole.YouwillseetheJSONdataagain,butnowitwillbeformatteddifferentlybecauseprint()doesagoodjobformattingdictionariesandarrays.TheformatoftheJSONdataisdictatedbytheAPI,soyouwilladdthecodetoparsetheJSONtotheFlickrAPIstruct.Parsingthedatathatcomesbackfromtheservercouldgowronginanumberofways:ThedatamightnotcontainJSON.Thedatacouldbecorrupt.ThedatamightcontainJSONbutnotmatchtheformatthatyouexpect.Tomanagethepossibilityoffailure,youwilluseanenumerationwithassociatedvaluestorepresentthesuccessorfailureoftheparsing.

Enumerationsandassociatedvalues

YoulearnedaboutthebasicsofenumerationsinChapter2,andyouhavebeenusingthemthroughoutthisbook–includingtheMethodenumusedearlierinthischapter.Associatedvaluesareausefulfeatureofenumerations.Let’stakeamomenttolookatasimpleexamplebeforeyouusethisfeatureinPhotorama.Enumerationsareaconvenientwayofdefiningandrestrictingthepossiblevaluesforavariable.Forexample,let’ssayyouareworkingonahomeautomationapp.Youcoulddefineanenumerationtospecifytheovenstate,likethis:enumOvenState{

caseon

caseoff

}

Iftheovenison,youalsoneedtoknowwhattemperatureitissetto.Associatedvaluesarea

Page 600: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

perfectsolutiontothissituation.enumOvenState{

caseon(Double)

caseoff

}

varovenState=OvenState.on(450)

Eachcaseofanenumerationcanhavedataofanytypeassociatedwithit.ForOvenState,its.oncasehasanassociatedDoublethatrepresentstheoven’stemperature.Noticethatnotallcasesneedtohaveassociatedvalues.Retrievingtheassociatedvaluefromanenumisoftendoneusingaswitchstatement.switchovenState{

caselet.on(temperature):

print("Theovenisonandsetto\(temperature)degrees.")

case.off:

print("Theovenisoff.")

}

Notethatthe.oncaseusesaletkeywordtostoretheassociatedvalueinthetemperatureconstant,whichcanbeusedwithinthecaseclause.(Youcanusethevarkeywordinsteadiftemperatureneedstobeavariable.)ConsideringthevaluegiventoovenState,theswitchstatementabovewouldresultinthelineTheovenisonandsetto450degrees.printedtotheconsole.Inthenextsection,youwilluseanenumerationwithassociatedvaluestotietheresultstatusofarequesttotheFlickrwebservicewithdata.Asuccessfulresultstatuswillbetiedtothedatacontaininginterestingphotos;afailureresultstatuswillbetiedwitherrorinformation.

ParsingJSONdata

InPhotoStore.swift,addanenumerationnamedPhotosResulttothetopofthefilethathasacaseforbothsuccessandfailure.importFoundation

enumPhotosResult{

casesuccess([Photo])

casefailure(Error)

}

classPhotoStore{

IfthedataisvalidJSONandcontainsanarrayofphotos,thosephotoswillbeassociatedwiththesuccesscase.Ifthereareanyerrorsduringtheparsingprocess,therelevantErrorwillbepassedalongwiththefailurecase.Errorisaprotocolthatallerrorsconformto.NSErroristheerrorthatmanyiOSframeworksthrow,anditconformstoError.YouwillcreateyourownErrorshortly.InFlickrAPI.swift,implementamethodthattakesinaninstanceofDataandusesthe

Page 601: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

JSONSerializationclasstoconvertthedataintothebasicfoundationobjects.staticfuncphotos(fromJSONdata:Data)->PhotosResult{

do{

letjsonObject=tryJSONSerialization.jsonObject(with:data,

options:[])

varfinalPhotos=[Photo]()

return.success(finalPhotos)

}catchleterror{

return.failure(error)

}

}

(Thiscodewillgeneratesomewarnings.Youwillresolvethemshortly.)IftheincomingdataisvalidJSONdata,thenthejsonObjectinstancewillreferencetheappropriatemodelobject.Ifnot,thentherewasaproblemwiththedataandyoupassalongtheerror.YounowneedtogetthephotoinformationoutoftheJSONobjectandintoinstancesofPhoto.WhentheURLSessionDataTaskfinishes,youwilluseJSONSerializationtoconverttheJSONdataintoadictionary.Figure20.5showshowthedatawillbestructured.Figure20.5JSONobjects

Page 602: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

AtthetopleveloftheincomingJSONdataisadictionary.Thevalueassociatedwiththe“photos”keycontainstheimportantinformation,andthemostimportantisthearrayofdictionaries.Asyoucansee,youhavetodigprettydeeptogettheinformationthatyouneed.IfthestructureoftheJSONdatadoesnotmatchyourexpectations,youwillreturnacustomerror.AtthetopofFlickrAPI.swift,declareacustomenumtorepresentpossibleerrorsfortheFlickrAPI.enumFlickrError:Error{

caseinvalidJSONData

Page 603: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

}

enumMethod:String{

caseinterestingPhotos="flickr.interestingness.getList"

}

Now,inphotos(fromJSON:),digdownthroughtheJSONdatatogettothearrayofdictionariesrepresentingtheindividualphotos.staticfuncphotos(fromJSONdata:Data)->PhotosResult{

do{

letjsonObject=tryJSONSerialization.jsonObject(with:data,

options:[])

guard

letjsonDictionary=jsonObjectas?[AnyHashable:Any],

letphotos=jsonDictionary["photos"]as?[String:Any],

letphotosArray=photos["photo"]as?[[String:Any]]else{

//TheJSONstructuredoesn'tmatchourexpectations

return.failure(FlickrError.invalidJSONData)

}

varfinalPhotos=[Photo]()

return.success(finalPhotos)

}catchleterror{

return.failure(error)

}

}

ThenextstepistogetthephotoinformationoutofthedictionaryandintoPhotomodelobjects.YouwillneedaninstanceofDateFormattertoconvertthedatetakenstringintoaninstanceofDate.InFlickrAPI.swift,addaconstantinstanceofDateFormatter.privatestaticletbaseURLString="https://api.flickr.com/services/rest"

privatestaticletapiKey="a6d819499131071f158fd740860a5a88"

privatestaticletdateFormatter:DateFormatter={

letformatter=DateFormatter()

formatter.dateFormat="yyyy-MM-ddHH:mm:ss"

returnformatter

}()

StillinFlickrAPI.swift,writeanewmethodtoparseaJSONdictionaryintoaPhotoinstance.privatestaticfuncphoto(fromJSONjson:[String:Any])->Photo?{

guard

letphotoID=json["id"]as?String,

lettitle=json["title"]as?String,

letdateString=json["datetaken"]as?String,

letphotoURLString=json["url_h"]as?String,

leturl=URL(string:photoURLString),

letdateTaken=dateFormatter.date(from:dateString)else{

//Don'thaveenoughinformationtoconstructaPhoto

returnnil

Page 604: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

}

returnPhoto(title:title,photoID:photoID,remoteURL:url,dateTaken:dateTaken)

}

Nowupdatephotos(fromJSON:)toparsethedictionariesintoPhotoinstancesandthenreturntheseaspartofthesuccessenumerator.AlsohandlethepossibilitythattheJSONformathaschanged,sonophotoswereabletobefound.staticfuncphotos(fromJSONdata:Data)->PhotosResult{

do{

letjsonObject=tryJSONSerialization.jsonObject(with:data,

options:[])

guard

letjsonDictionary=jsonObjectas?[AnyHashable:Any],

letphotos=jsonDictionary["photos"]as?[String:Any],

letphotosArray=photos["photo"]as?[[String:Any]]else{

//TheJSONstructuredoesn'tmatchourexpectations

return.failure(FlickrError.invalidJSONData)

}

varfinalPhotos=[Photo]()

forphotoJSONinphotosArray{

ifletphoto=photo(fromJSON:photoJSON){

finalPhotos.append(photo)

}

}

iffinalPhotos.isEmpty&&!photosArray.isEmpty{

//Weweren'tabletoparseanyofthephotos

//MaybetheJSONformatforphotoshaschanged

return.failure(FlickrError.invalidJSONData)

}

return.success(finalPhotos)

}catchleterror{

return.failure(error)

}

}

Next,inPhotoStore.swift,writeanewmethodthatwillprocesstheJSONdatathatisreturnedfromthewebservicerequest.privatefuncprocessPhotosRequest(data:Data?,error:Error?)->PhotosResult{

guardletjsonData=dataelse{

return.failure(error!)

}

returnFlickrAPI.photos(fromJSON:jsonData)

}

Now,updatefetchInterestingPhotos()tousethemethodyoujustcreated.funcfetchInterestingPhotos(){

leturl=FlickrAPI.interestingPhotosURL

letrequest=URLRequest(url:url)

lettask=session.dataTask(with:request){

(data,response,error)->Voidin

Page 605: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

ifletjsonData=data{

do{

letjsonObject=tryJSONSerialization.jsonObject(with:jsonData,

options:[])

print(jsonObject)

}catchleterror{

print("ErrorcreatingJSONobject:\(error)")

}

}elseifletrequestError=error{

print("Errorfetchinginterestingphotos:\(requestError)")

}else{

print("Unexpectederrorwiththerequest")

}

letresult=self.processPhotosRequest(data:data,error:error)

}

task.resume()

}

Finally,updatethemethodsignatureforfetchInterestingPhotos()totakeinacompletionclosurethatwillbecalledoncethewebservicerequestiscompleted.funcfetchInterestingPhotos(completion:@escaping(PhotosResult)->Void){

leturl=FlickrAPI.interestingPhotosURL

letrequest=URLRequest(url:url)

lettask=session.dataTask(with:request){

(data,response,error)->Voidin

letresult=self.processPhotosRequest(data:data,error:error)

completion(result)

}

task.resume()

}

Fetchingdatafromawebserviceisanasynchronousprocess:Oncetherequeststarts,itmaytakeanontrivialamountoftimeforaresponsetocomebackfromtheserver.Becauseofthis,thefetchInterestingPhotos(completion:)methodcannotdirectlyreturnaninstanceofPhotosResult.Instead,thecallerofthismethodwillsupplyacompletionclosureforthePhotoStoretocalloncetherequestiscomplete.ThisfollowsthesamepatternthatURLSessionTaskuseswithitscompletionhandler:Thetaskiscreatedwithaclosureforittocalloncethewebservicerequestcompletes.Figure20.6describestheflowofdatawiththewebservicerequest.

Page 606: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure20.6Webservicerequestdataflow

Theclosureismarkedwiththe@escapingannotation.Thisannotationletsthecompilerknowthattheclosuremightnotgetcalledimmediatelywithinthemethod.Inthiscase,theclosureisgettingpassedtotheURLSessionDataTask,whichwillcallitwhenthewebservicerequestcompletes.InPhotosViewController.swift,updatetheimplementationoftheviewDidLoad()usingthetrailingclosuresyntaxtoprintouttheresultofthewebservicerequest.overridefuncviewDidLoad(){

super.viewDidLoad()

store.fetchInterestingPhotos(){

(photosResult)->Voidin

switchphotosResult{

caselet.success(photos):

print("Successfullyfound\(photos.count)photos.")

caselet.failure(error):

print("Errorfetchinginterestingphotos:\(error)")

}

}

}

Buildandruntheapplication.Oncethewebservicerequestcompletes,youshouldseethenumberofphotosfoundprintedtotheconsole.

Page 607: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 608: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

DownloadingandDisplayingtheImageData

Youhavedonealotalreadyinthischapter:YouhavesuccessfullyinteractedwiththeFlickrAPIviaawebservicerequest,andyouhaveparsedtheincomingJSONdataintoPhotomodelobjects.Unfortunately,youhavenothingtoshowforitexceptsomelogmessagesintheconsole.Inthissection,youwillusetheURLreturnedfromthewebservicerequesttodownloadtheimagedata.ThenyouwillcreateaninstanceofUIImagefromthatdata,and,finally,youwilldisplaythefirstimagereturnedfromtherequestinaUIImageView.(Inthenextchapter,youwilldisplayalloftheimagesthatarereturnedinagridlayoutdrivenbyaUICollectionView.)Thefirststepisdownloadingtheimagedata.Thisprocesswillbeverysimilartothewebservicerequesttodownloadthephotos’JSONdata.OpenPhotoStore.swift,importUIKit,andaddanenumerationtothetopofthefilethatrepresentstheresultofdownloadingtheimage.ThisenumerationwillfollowthesamepatternasthePhotosResultenumeration,takingadvantageofassociatedvalues.YouwillalsocreateanErrortorepresentphotoerrors.importFoundation

importUIKit

enumImageResult{

casesuccess(UIImage)

casefailure(Error)

}

enumPhotoError:Error{

caseimageCreationError

}

enumPhotosResult{

casesuccess([Photo])

casefailure(Error)

}

Ifthedownloadissuccessful,thesuccesscasewillhavetheUIImageassociatedwithit.Ifthereisanerror,thefailurecasewillhavetheErrorassociatedwithit.Now,inthesamefile,implementamethodtodownloadtheimagedata.LikethefetchInterestingPhotos(completion:)method,thisnewmethodwilltakeinacompletionclosurethatwillreturnaninstanceofImageResult.funcfetchImage(forphoto:Photo,completion:@escaping(ImageResult)->Void){

letphotoURL=photo.remoteURL

letrequest=URLRequest(url:photoURL)

lettask=session.dataTask(with:request){

(data,response,error)->Voidin

}

task.resume()

Page 609: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

}

Nowimplementamethodthatprocessesthedatafromthewebservicerequestintoanimage,ifpossible.privatefuncprocessImageRequest(data:Data?,error:Error?)->ImageResult{

guard

letimageData=data,

letimage=UIImage(data:imageData)else{

//Couldn'tcreateanimage

ifdata==nil{

return.failure(error!)

}else{

return.failure(PhotoError.imageCreationError)

}

}

return.success(image)

}

StillinPhotoStore.swift,updatefetchImage(for:completion:)tousethisnewmethod.funcfetchImage(forphoto:Photo,completion:@escaping(ImageResult)->Void){

letphotoURL=photo.remoteURL

letrequest=URLRequest(url:photoURL)

lettask=session.dataTask(with:request){

(data,response,error)->Voidin

letresult=self.processImageRequest(data:data,error:error)

completion(result)

}

task.resume()

}

Totestthiscode,youwilldownloadtheimagedataforthefirstphotothatisreturnedfromtheinterestingphotosrequestanddisplayitontheimageview.OpenPhotosViewController.swiftandaddanewmethodthatwillfetchtheimageanddisplayitontheimageview.funcupdateImageView(forphoto:Photo){

store.fetchImage(for:photo){

(imageResult)->Voidin

switchimageResult{

caselet.success(image):

self.imageView.image=image

caselet.failure(error):

print("Errordownloadingimage:\(error)")

}

}

}

NowupdateviewDidLoad()tousethisnewmethod.overridefuncviewDidLoad(){

super.viewDidLoad()

Page 610: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

store.fetchInterestingPhotos{

(photosResult)->Voidin

switchphotosResult{

caselet.success(photos):

print("Successfullyfound\(photos.count)photos.")

ifletfirstPhoto=photos.first{

self.updateImageView(for:firstPhoto)

}

caselet.failure(error):

print("Errorfetchinginterestingphotos:\(error)")

}

}

}

Althoughyoucouldbuildandruntheapplicationatthispoint,theimagemayormaynotappearintheimageviewwhenthewebservicerequestfinishes.Why?Thecodethatupdatestheimageviewisnotbeingrunonthemainthread.

Page 611: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 612: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

TheMainThread

ModerniOSdeviceshavemulticoreprocessorsthatenablethemtorunmultiplechunksofcodesimultaneously.Thesecomputationsproceedinparallel,sothisisreferredtoasparallelcomputing.Whendifferentcomputationsareinflightatthesametime,thisisknownasconcurrency,andthecomputationsaresaidtobehappeningconcurrently.Acommonwaytoexpressthisisbyrepresentingeachcomputationwithadifferentthreadofcontrol.Sofarinthisbook,allofyourcodehasbeenrunningonthemainthread.ThemainthreadissometimesreferredtoastheUIthread,becauseanycodethatmodifiestheUImustrunonthemainthread.Whenthewebservicecompletes,youwantittoupdatetheimageview.Butbydefault,URLSessionDataTaskrunsthecompletionhandleronabackgroundthread.Youneedawaytoforcecodetorunonthemainthreadtoupdatetheimageview.YoucandothateasilyusingtheOperationQueueclass.YouwillupdatetheasynchronousPhotoStoremethodstocalltheircompletionhandlersonthemainthread.InPhotoStore.swift,updatefetchInterestingPhotos(completion:)tocallthecompletionclosureonthemainthread.funcfetchInterestingPhotos(completion:@escaping(PhotosResult)->Void){

leturl=FlickrAPI.interestingPhotosURL

letrequest=URLRequest(url:url)

lettask=session.dataTask(with:request){

(data,response,error)->Voidin

letresult=self.processPhotosRequest(data:data,error:error)

OperationQueue.main.addOperation{

completion(result)

}

}

task.resume()

}

DothesameforfetchImage(for:completion:).funcfetchImage(forphoto:Photo,completion:@escaping(ImageResult)->Void){

letphotoURL=photo.remoteURL

letrequest=URLRequest(url:photoURL)

lettask=session.dataTask(with:request){

(data,response,error)->Voidin

letresult=self.processImageRequest(data:data,error:error)

OperationQueue.main.addOperation{

completion(result)

}

}

task.resume()

}

Page 613: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Buildandruntheapplication.Nowthattheimageviewisbeingupdatedonthemainthread,youwillhavesomethingtoshowforallyourhardwork:Animagewillappearwhenthewebservicerequestfinishes.(Itmighttakealittletimetoshowtheimageifthewebservicerequesttakesawhiletofinish.)

Page 614: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 615: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

BronzeChallenge:PrintingtheResponseInformation

ThecompletionhandlerfordataTask(with:completionHandler:)providesaninstanceofURLResponse.WhenmakingHTTPrequests,thisresponseisoftypeHTTPURLResponse(asubclassofURLResponse).PrintthestatusCodeandheaderFieldstotheconsole.Thesepropertiesareveryusefulwhendebuggingwebservicecalls.

Page 616: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 617: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

SilverChallenge:FetchRecentPhotosfromFlickr

Inthischapter,youfetchedtheinterestingphotosfromFlickrusingtheflickr.interestingness.getListendpoint.AddanewcasetoyourMethodenumerationforrecentphotos.Theendpointforthisisflickr.photos.getRecent.Extendtheapplicationsoyouareabletoswitchbetweeninterestingphotosandrecentphotos.(Hint:TheJSONformatforbothendpointsisthesame,soyourexistingparsingcodewillstillwork.)

Page 618: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 619: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

FortheMoreCurious:HTTP

WhenURLSessionTaskinteractswithawebserver,itdoessoaccordingtotherulesoutlinedintheHTTPspecification.Thespecificationisveryclearabouttheexactformatoftherequest/responseexchangebetweentheclientandtheserver.AnexampleofasimpleHTTPrequestisshowninFigure20.7.Figure20.7HTTPrequestformat

AnHTTPrequesthasthreeparts:arequestline,requestheaders,andanoptionalrequestbody.Therequestlineisthefirstlineoftherequestandtellstheserverwhattheclientistryingtodo.Inthisrequest,theclientistryingtoGETtheresourceat/index.html.(ItalsospecifiestheHTTPversionthattherequestwillbeconformingto.)ThewordGETisanHTTPmethod.WhilethereareanumberofsupportedHTTPmethods,youwillseeGETandPOSTmostoften.ThedefaultofURLRequest,GET,indicatesthattheclientwantsaresourcefromtheserver.Theresourcerequestedmightbeanactualfileonthewebserver ’sfilesystem,oritcouldbegenerateddynamicallyatthemomenttherequestisreceived.Asaclient,youshouldnotcareaboutthisdetail,butmorethanlikelytheJSONresourcesyourequestedinthischapterwerecreateddynamically.Inadditiontogettingthingsfromaserver,youcansenditinformation.Forexample,manywebserversallowyoutouploadphotos.AclientapplicationwouldpasstheimagedatatotheserverthroughanHTTPrequest.Inthissituation,youwouldusetheHTTPmethodPOST,andyouwouldincludearequestbody.Thebodyofarequestisthepayloadyouaresendingtotheserver–typicallyJSON,XML,orbinarydata.Whentherequesthasabody,itmustalsohavetheContent-Lengthheader.Handily,URLRequestwillcomputethesizeofthebodyandaddthisheaderforyou.HereisanexampleofhowtoPOSTanimagetoanimaginarysiteusingaURLRequest.ifletsomeURL=URL(string:"http://www.photos.example.com/upload"){

letimage=profileImage()

letdata=UIImagePNGRepresentation(image)

Page 620: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

varreq=URLRequest(url:someURL)

//ThisaddstheHTTPbodydataandautomaticallysetsthecontent-lengthheader

req.httpBody=data

//ThischangestheHTTPmethodintherequestline

req.httpMethod="POST"

//Ifyouwantedtosetarequestheader,suchastheAcceptheader

req.setValue("text/json",forHTTPHeaderField:"Accept")

}

Figure20.8showswhatasimpleHTTPresponsemightlooklike.WhileyouwillnotbemodifyingthecorrespondingHTTPURLResponseinstance,itisnicetounderstandwhatitismodeling.Figure20.8HTTPresponseformat

Asyoucansee,theformatoftheresponseisnottoodifferentfromtherequest.Itincludesastatusline,responseheaders,and,ofcourse,theresponsebody.Yes,thisiswherethatpesky404NotFoundcomesfrom!

Page 621: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 622: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

21CollectionViews

Inthischapter,youwillcontinueworkingonthePhotoramaapplicationbydisplayingtheinterestingFlickrphotosinagridusingtheUICollectionViewclass.Thischapterwillalsoreinforcethedatasourcedesignpatternthatyouusedinpreviouschapters.Figure21.1showsyouwhattheapplicationwilllooklikeattheendofthischapter.Figure21.1Photoramawithacollectionview

InChapter10,youworkedwithUITableView.Tableviewsareagreatwaytodisplayandeditacolumnofinformationinahierarchicallist.Likeatableview,acollectionviewalsodisplaysanorderedcollectionofitems,butinsteadofdisplayingtheinformationinahierarchicallist,thecollectionviewhasalayoutobjectthatdrivesthedisplayofinformation.Youwilluseabuilt-inlayoutobject,theUICollectionViewFlowLayout,topresenttheinterestingphotosinascrollablegrid.

Page 623: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 624: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

DisplayingtheGrid

Let’stackletheinterfacefirst.YouaregoingtochangetheUIforPhotosViewControllertodisplayacollectionviewinsteadofdisplayingtheimageview.OpenMain.storyboardandlocatethePhotoramaimageview.DeletetheimageviewfromthecanvasanddragaCollectionViewontothecanvas.Selectboththecollectionviewanditssuperview.(Theeasiestwaytodothisisusingthedocumentoutline.)OpentheAutoLayoutAlignmenu,configureitlikeFigure21.2,andclickAdd4Constraints.Figure21.2Collectionviewconstraints

BecauseyouusedtheAlignmenutopintheedges,thecollectionviewwillbepinnedtothetopoftheentireviewinsteadoftothetoplayoutguide.Thisisusefulforscrollviews(andtheirsubclasses,likeUITableViewandUICollectionView)sothatthecontentwillscrollunderneaththenavigationbar.Thescrollviewwillautomaticallyupdateitsinsetstomakethecontentvisible,asyousawinChapter10.ThecanvaswillnowlooklikeFigure21.3.

Page 625: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure21.3Storyboardcanvas

Currently,thecollectionviewcellshaveaclearbackgroundcolor.Selectthecollectionviewcell–thesmallrectangleintheupper-leftcornerofthecollectionview–andgiveitablackbackgroundcolor.Selecttheblackcollectionviewcellandopenitsattributesinspector.SettheIdentifiertoUICollectionViewCell(Figure21.4).Figure21.4Settingthereuseidentifier

Thecollectionviewisnowonthecanvas,butyouneedawaytopopulatethecellswithdata.Todothis,youwillcreateanewclasstoactasthedatasourceofthecollectionview.

Page 626: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 627: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

CollectionViewDataSource

Applicationsareconstantlychanging,sopartofbeingagoodiOSdeveloperisbuildingapplicationsinawaythatallowsthemtoadapttochangingrequirements.ThePhotoramaapplicationwilldisplayasinglecollectionviewofphotos.YoucoulddosomethingsimilartowhatyoudidinHomepwnerandmakethePhotosViewControllerbethedatasourceofthecollectionview.Theviewcontrollerwouldimplementtherequireddatasourcemethods,andeverythingwouldworkjustfine.Atleast,itwouldworkfornow.Whatif,sometimeinthefuture,youdecidedtohaveadifferentscreenthatalsodisplayedacollectionviewofphotos?Maybeinsteadofdisplayingtheinterestingphotos,itwoulduseadifferentwebservicetodisplayallthephotosmatchingasearchterm.Inthiscase,youwouldneedtoreimplementthesamedatasourcemethodswithinthenewviewcontrollerwithessentiallythesamecode.Thatwouldnotbeideal.Instead,youwillabstractoutthecollectionviewdatasourcecodeintoanewclass.Thisclasswillberesponsibleforrespondingtodatasourcequestions–anditwillbereusableasnecessary.CreateanewSwiftfilenamedPhotoDataSourceanddeclarethePhotoDataSourceclass.importFoundation

importUIKit

classPhotoDataSource:NSObject,UICollectionViewDataSource{

varphotos=[Photo]()

}

ToconformtotheUICollectionViewDataSourceprotocol,atypealsoneedstoconformtotheNSObjectProtocol.TheeasiestandmostcommonwaytoconformtothisprotocolistosubclassfromNSObject,asyoudidabove.TheUICollectionViewDataSourceprotocoldeclarestworequiredmethodstoimplement:funccollectionView(_collectionView:UICollectionView,

numberOfItemsInSectionsection:Int)->Int

funccollectionView(_collectionView:UICollectionView,

cellForItemAtindexPath:IndexPath)->UICollectionViewCell

YoumightnoticethatthesetwomethodslookverysimilartothetworequiredmethodsofUITableViewDataSourcethatyousawinChapter10.Thefirstdatasourcecallbackaskshowmanycellstodisplay,andthesecondasksfortheUICollectionViewCelltodisplayforagivenindexpath.ImplementthesetwomethodsinPhotoDataSource.swift.classPhotoDataSource:NSObject,UICollectionViewDataSource{

varphotos=[Photo]()

Page 628: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

funccollectionView(_collectionView:UICollectionView,

numberOfItemsInSectionsection:Int)->Int{

returnphotos.count

}

funccollectionView(_collectionView:UICollectionView,

cellForItemAtindexPath:IndexPath)->UICollectionViewCell{

letidentifier="UICollectionViewCell"

letcell=

collectionView.dequeueReusableCell(withReuseIdentifier:identifier,

for:indexPath)

returncell

}

}

Next,thecollectionviewneedstoknowthataninstanceofPhotoDataSourceisthedatasourceobject.InPhotosViewController.swift,addapropertytoreferenceaninstanceofPhotoDataSourceandanoutletforaUICollectionViewinstance.Also,youwillnotneedtheimageViewanymore,sodeleteit.classPhotosViewController:UIViewController{

@IBOutletvarimageView:UIImageView!

@IBOutletvarcollectionView:UICollectionView!

varstore:PhotoStore!

letphotoDataSource=PhotoDataSource()

WithouttheimageViewproperty,youwillnotneedthemethodupdateImageView(for:)anymore.Goaheadandremoveit.funcupdateImageView(forphoto:Photo){

store.fetchImage(for:photo){

(imageResult)->Voidin

switchimageResult{

caselet.success(image):

self.imageView.image=image

caselet.failure(error):

print("Errordownloadingimage:\(error)")

}

}

}

UpdateviewDidLoad()tosetthedatasourceonthecollectionview.overridefuncviewDidLoad(){

super.viewDidLoad()

collectionView.dataSource=photoDataSource

Finally,updatethephotoDataSourceobjectwiththeresultofthewebservicerequestandreloadthecollectionview.overridefuncviewDidLoad()

super.viewDidLoad()

Page 629: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

collectionView.dataSource=photoDataSource

store.fetchInterestingPhotos{

(photosResult)->Voidin

switchphotosResult{

caselet.success(photos):

print("Successfullyfound\(photos.count)photos.")

ifletfirstPhoto=photos.first{

self.updateImageView(for:firstPhoto)

}

self.photoDataSource.photos=photos

caselet.failure(error):

print("Errorfetchinginterestingphotos:\(error)")

self.photoDataSource.photos.removeAll()

}

self.collectionView.reloadSections(IndexSet(integer:0))

}

}

ThelastthingyouneedtodoismakethecollectionViewoutletconnection.OpenMain.storyboardandnavigatetothecollectionview.Control-dragfromthePhotoramaviewcontrollertothecollectionviewandconnectittothecollectionViewoutlet.Buildandruntheapplication.Afterthewebservicerequestcompletes,checktheconsoletoconfirmthatphotoswerefound.OntheiOSdevice,therewillbeagridofblacksquarescorrespondingtothenumberofphotosfound(Figure21.5).Thesecellsarearrangedinaflowlayout.Aflowlayoutfitsasmanycellsonarowaspossiblebeforeflowingdowntothenextrow.IfyourotatetheiOSdevice,youwillseethecellsfillthegivenarea.

Page 630: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure21.5Initialflowlayout

Page 631: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 632: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

CustomizingtheLayout

Thedisplayofcellsisnotdrivenbythecollectionviewitselfbutbythecollectionview’slayout.Thelayoutobjectisresponsiblefortheplacementofcellsonscreen.Layouts,inturn,aredrivenbyasubclassofUICollectionViewLayout.TheflowlayoutthatPhotoramaiscurrentlyusingisUICollectionViewFlowLayout,whichistheonlyconcreteUICollectionViewLayoutsubclassprovidedbytheUIKitframework.SomeofthepropertiesyoucancustomizeonUICollectionViewFlowLayoutare:

scrollDirection–Doyouwanttoscrollverticallyorhorizontally?minimumLineSpacing–Whatistheminimumspacingbetweenlines?minimumInteritemSpacing–Whatistheminimumspacingbetweenitemsinarow(orcolumn,ifscrollinghorizontally)?itemSize–Whatisthesizeofeachitem?sectionInset–Whatarethemarginsusedtolayoutcontentforeachsection?

Figure21.6showshowthesepropertiesaffectthepresentationofcellsusingUICollectionViewFlowLayout.Figure21.6UICollectionViewFlowLayoutproperties

Page 633: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

OpenMain.storyboardandselectthecollectionview.OpenthesizeinspectorandconfiguretheCellSize,MinSpacing,andSectionInsetsasshowninFigure21.7.

Page 634: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure21.7Collectionviewsizeinspector

Buildandruntheapplicationtoseehowthelayouthaschanged.

Page 635: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 636: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

CreatingaCustomUICollectionViewCell

NextyouaregoingtocreateacustomUICollectionViewCellsubclasstodisplaythephotos.Whiletheimagedataisdownloading,thecollectionviewcellwilldisplayaspinningactivityindicatorusingtheUIActivityIndicatorViewclass.CreateanewSwiftfilenamedPhotoCollectionViewCellanddefinePhotoCollectionViewCellasasubclassofUICollectionViewCell.Thenaddoutletstoreferencetheimageviewandtheactivityindicatorview.importFoundation

importUIKit

classPhotoCollectionViewCell:UICollectionViewCell{

@IBOutletvarimageView:UIImageView!

@IBOutletvarspinner:UIActivityIndicatorView!

}

Theactivityindicatorviewshouldonlyspinwhenthecellisnotdisplayinganimage.InsteadofalwaysupdatingthespinnerwhentheimageViewisupdated,orviceversa,youwillwriteahelpermethodtotakecareofitforyou.CreatethishelpermethodinPhotoCollectionViewCell.swift.funcupdate(withimage:UIImage?){

ifletimageToDisplay=image{

spinner.stopAnimating()

imageView.image=imageToDisplay

}else{

spinner.startAnimating()

imageView.image=nil

}

}

Itwouldbenicetoreseteachcelltothespinningstatebothwhenthecellisfirstcreatedandwhenthecellisgettingreused.ThemethodawakeFromNib()willbeusedfortheformer,andthemethodprepareForReuse()willbeusedforthelatter.RecallthatyouusedawakeFromNib()inChapter12.ThemethodprepareForReuse()iscalledwhenacellisabouttobereused.ImplementthesetwomethodsinPhotoCollectionViewCell.swifttoresetthecellbacktothespinningstate.overridefuncawakeFromNib(){

super.awakeFromNib()

update(with:nil)

}

overridefuncprepareForReuse(){

super.prepareForReuse()

update(with:nil)

}

Page 637: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Youwilluseaprototypecelltosetuptheinterfaceforthecollectionviewcellinthestoryboard,justasyoudidinChapter12forItemCell.Ifyourecall,eachprototypecellcorrespondstoavisuallyuniquecellwithauniquereuseidentifier.Mostofthetime,theprototypecellswillbeassociatedwithdifferentUICollectionViewCellsubclassestoprovidebehaviorspecifictothatkindofcell.Inthecollectionview’sattributesinspector,youcanadjustthenumberofItemsthatthecollectionviewdisplays,andeachitemcorrespondstoaprototypecellinthecanvas.ForPhotorama,youonlyneedonekindofcell:thePhotoCollectionViewCellthatdisplaysaphoto.OpenMain.storyboardandselectthecollectionviewcell.Intheidentityinspector,changetheClasstoPhotoCollectionViewCell(Figure21.8)and,intheattributesinspector,changetheIdentifiertoPhotoCollectionViewCell.Figure21.8Changingthecellclass

DraganimageviewontotheUICollectionViewCell.Addconstraintstopintheimageviewtotheedgesofthecell.OpentheattributesinspectorfortheimageviewandsettheContentModetoAspectFill.Thiswillcutoffpartsofthephotos,butitwillallowthephotostocompletelyfillinthecollectionviewcell.Next,draganactivityindicatorviewontopoftheimageview.Addconstraintstocentertheactivityindicatorviewbothhorizontallyandverticallywiththeimageview.OpenitsattributesinspectorandselectHidesWhenStopped(Figure21.9).Figure21.9Configuringtheactivityindicator

Selectthecollectionviewcellagain.Thiscanbeabittrickytodoonthecanvasbecausethenewlyaddedsubviewscompletelycoverthecellitself.AhelpfulInterfaceBuildertipisto

Page 638: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

holdControlandShifttogetherandthenclickontopoftheviewyouwanttoselect.Youwillbepresentedwithalistofalloftheviewsandcontrollersunderthepointyouclicked(Figure21.10).Figure21.10Selectingthecellonthecanvas

Withthecellselected,opentheconnectionsinspectorandconnecttheimageViewandspinnerpropertiestotheimageviewandactivityindicatorviewonthecanvas(Figure21.11).

Page 639: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure21.11ConnectingPhotoCollectionViewCelloutlets

Next,openPhotoDataSource.swiftandupdatethedatasourcemethodtousethePhotoCollectionViewCell.funccollectionView(_collectionView:UICollectionView,

cellForItemAtindexPath:IndexPath)->UICollectionViewCell{

letidentifier="UICollectionViewCell""PhotoCollectionViewCell"

letcell=

collectionView.dequeueReusableCell(withReuseIdentifier:identifier,

for:indexPath)as!PhotoCollectionViewCell

returncell

}

Buildandruntheapplication.Whentheinterestingphotosrequestcompletes,youwillseetheactivityindicatorviewsallspinning(Figure21.12).

Page 640: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure21.12Customcollectionviewsubclass

Page 641: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 642: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

DownloadingtheImageData

Nowallthatisleftisdownloadingtheimagedataforthephotosthatcomebackintherequest.Thistaskisnotverydifficult,butitrequiressomethought.Imagesarelargefiles,anddownloadingthemcouldeatupyourusers’cellulardataallowance.AsaconsiderateiOSdeveloper,youwanttomakesureyourapp’sdatausageisonlywhatitneedstobe.Consideryouroptions.YoucoulddownloadtheimagedatainviewDidLoad()whenthefetchInterestingPhotos(completion:)methodcallsitscompletionclosure.Atthatpoint,youalreadyassigntheincomingphotostothephotosproperty,soyoucoulditerateoverallofthosephotosanddownloadtheirimagedatathen.Althoughthiswouldwork,itwouldbeverycostly.Therecouldbealargenumberofphotoscomingbackintheinitialrequest,andtheusermayneverevenscrolldownintheapplicationfarenoughtoseesomeofthem.Ontopofthat,ifyouinitializetoomanyrequestssimultaneously,someoftherequestsmaytimeoutwhilewaitingforotherrequeststofinish.Sothisisprobablynotthebestsolution.Instead,itmakessensetodownloadtheimagedataforonlythecellsthattheuserisattemptingtoview.UICollectionViewhasamechanismtosupportthisthroughitsUICollectionViewDelegatemethodcollectionView(_:willDisplay:forItemAt:).Thisdelegatemethodwillbecalledeverytimeacellisgettingdisplayedonscreenandisagreatopportunitytodownloadtheimagedata.RecallthatthedataforthecollectionviewisdrivenbyaninstanceofPhotoDataSource,areusableclasswiththesingleresponsibilityofdisplayingphotosinacollectionview.Collectionviewsalsohaveadelegate,whichisresponsibleforhandlinguserinteractionwiththecollectionview.Thisincludestaskssuchasmanagingcellselectionandtrackingcellscomingintoandoutofview.Thisresponsibilityismoretightlycoupledwiththeviewcontrolleritself,sowhereasthedatasourceisaninstanceofPhotoDataSource,thecollectionview’sdelegatewillbethePhotosViewController.InPhotosViewController.swift,havetheclassconformtotheUICollectionViewDelegateprotocol.classPhotosViewController:UIViewController,UICollectionViewDelegate{

(BecausetheUICollectionViewDelegateprotocolonlydefinesoptionalmethods,Xcodedoesnotreportanyerrorswhenyouaddthisdeclaration.)UpdateviewDidLoad()tosetthePhotosViewControllerasthedelegateofthecollectionview.overridefuncviewDidLoad(){

super.viewDidLoad()

collectionView.dataSource=photoDataSource

collectionView.delegate=self

Finally,implementthedelegatemethodinPhotosViewController.swift.

Page 643: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

funccollectionView(_collectionView:UICollectionView,

willDisplaycell:UICollectionViewCell,

forItemAtindexPath:IndexPath){

letphoto=photoDataSource.photos[indexPath.row]

//Downloadtheimagedata,whichcouldtakesometime

store.fetchImage(for:photo){(result)->Voidin

//Theindexpathforthephotomighthavechangedbetweenthe

//timetherequeststartedandfinished,sofindthemost

//recentindexpath

//(Note:Youwillhaveanerroronthenextline;youwillfixitsoon)

guardletphotoIndex=self.photoDataSource.photos.index(of:photo),

caselet.success(image)=resultelse{

return

}

letphotoIndexPath=IndexPath(item:photoIndex,section:0)

//Whentherequestfinishes,onlyupdatethecellifit'sstillvisible

ifletcell=self.collectionView.cellForItem(at:photoIndexPath)

as?PhotoCollectionViewCell{

cell.update(with:image)

}

}

}

Youareusinganewformofpatternmatchingintheabovecode.TheresultthatisreturnedfromfetchImage(for:completion:)isanenumerationwithtwocases:.successand.failure.Becauseyouonlyneedtohandlethe.successcase,youuseacasestatementtocheckwhetherresulthasavalueof.success.Comparethefollowingcodetoseehowyoucouldusepatternmatchinginanifstatementversusaswitchstatement.Thiscode:ifcaselet.success(image)=result{

photo.image=image

}

behavesjustlikethiscode:switchresult{

caselet.success(image):

photo.image=image

case.failure:

break

}

Let’sfixtheerroryousawwhenfindingtheindexofphotointhephotosarray.Theindex(of:)methodworksbycomparingtheitemthatyouarelookingfortoeachoftheitemsinthecollection.Itdoesthisusingthe==operator.TypesthatconformtotheEquatableprotocolmustimplementthisoperator,andPhotodoesnotyetconformtoEquatable.InPhoto.swift,declarethatPhotoconformstotheEquatableprotocolandimplementtherequiredoverloadingofthe==operator.classPhoto:Equatable{

Page 644: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

...

staticfunc==(lhs:Photo,rhs:Photo)->Bool{

//TwoPhotosarethesameiftheyhavethesamephotoID

returnlhs.photoID==rhs.photoID

}

}

InSwift,itiscommontogrouprelatedchunksoffunctionalityintoanextension.Let’stakeashortdetourtolearnaboutextensionsandthenusethisknowledgetoseehowconformingtotheEquatableprotocolisoftendoneinpractice.

Extensions

Extensionsserveacoupleofpurposes:Theyallowyoutogroupchunksoffunctionalityintoalogicalunit,andtheyalsoallowyoutoaddfunctionalitytoyourowntypesaswellastypesprovidedbythesystemorotherframeworks.Beingabletoaddfunctionalitytoatypewhosesourcecodeyoudonothaveaccesstoisaverypowerfulandflexibletool.Extensionscanbeaddedtoclasses,structs,andenums.Let’stakealookatanexample.SayyouwantedtoaddfunctionalitytotheInttypetoprovideadoubledvalueofthatInt.Forexample:letfourteen=7.doubled//Thevalueoffourteenis'14'

YoucanaddthisfunctionalitybyextendingtheInttype:extensionInt{

vardoubled:Int{

returnself*2

}

}

Withextensions,youcanaddcomputedproperties,addmethods,andconformtoprotocols.However,youcannotaddstoredpropertiestoanextension.Extensionsprovideagreatmechanismforgroupingrelatedpiecesoffunctionality.Theycanmakethecodemorereadableandhelpwithlong-termmaintainabilityofyourcodebase.Onecommonchunkoffunctionalitythatisoftengroupedintoanextensionisconformancetoaprotocolalongwiththemethodsofthatprotocol.UpdatePhoto.swifttouseanextensiontoconformtotheEquatableprotocol.classPhoto:Equatable{

...

staticfunc==(lhs:Photo,rhs:Photo)->Bool{

//TwoPhotosarethesameiftheyhavethesamephotoID

returnlhs.photoID==rhs.photoID

}

}

extensionPhoto:Equatable{

staticfunc==(lhs:Photo,rhs:Photo)->Bool{

//TwoPhotosarethesameiftheyhavethesamephotoID

returnlhs.photoID==rhs.photoID

}

}

Page 645: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Thisisasimplifiedexample,butextensionsareverypowerfulforbothextendingexistingtypesandgroupingrelatedfunctionality.Infact,theSwiftstandardlibrarymakesextensiveuseofextensions–andyouwill,too.Buildandruntheapplication.Theimagedatawilldownloadforthecellsvisibleonscreen(Figure21.13).Scrolldowntomakemorecellsvisible.Atfirst,youwillseetheactivityindicatorviewsspinning,butsoontheimagedataforthosecellswillload.Figure21.13Imagedownloadsinprogress

Ifyouscrollbackup,youwillseeadelayinloadingtheimagedataforthepreviouslyvisiblecells.Thisisbecausewheneveracellcomesonscreen,theimagedataisredownloaded.Tofixthis,youwillimplementimagecaching,similartowhatyoudidintheHomepwner

Page 646: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

application.

Imagecaching

Fortheimagedata,youwillusethesameapproachthatyouusedinyourHomepwnerapplication.Infact,youwillusethesameImageStoreclassthatyouwroteforthatproject.OpenHomepwner.xcodeprojanddragtheImageStore.swiftfilefromtheHomepwnerapplicationtothePhotoramaapplication.MakesuretochooseCopyitemsifneeded.OncetheImageStore.swiftfilehasbeenaddedtoPhotorama,youcanclosetheHomepwnerproject.BackinPhotorama,openPhotoStore.swiftandgiveitapropertyforanImageStore.classPhotoStore{

letimageStore=ImageStore()

ThenupdatefetchImage(for:completion:)tosavetheimagesusingtheimageStore.funcfetchImage(forphoto:Photo,completion:@escaping(ImageResult)->Void){

letphotoKey=photo.photoID

ifletimage=imageStore.image(forKey:photoKey){

OperationQueue.main.addOperation{

completion(.success(image))

}

return

}

letphotoURL=photo.remoteURL

letrequest=URLRequest(url:photoURL)

lettask=session.dataTask(with:request){

(data,response,error)->Voidin

letresult=self.processImageRequest(data:data,error:error)

ifcaselet.success(image)=result{

self.imageStore.setImage(image,forKey:photoKey)

}

OperationQueue.main.addOperation{

completion(result)

}

}

task.resume()

}

Buildandruntheapplication.Nowwhentheimagedataisdownloaded,itwillbesavedtothefilesystem.Thenexttimethatphotoisrequested,itwillbeloadedfromthefilesystemifitisnotcurrentlyinmemory.

Page 647: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 648: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

NavigatingtoaPhoto

Inthissection,youaregoingtoaddfunctionalitytoallowausertonavigatetoanddisplayasinglephoto.CreateanewSwiftfilenamedPhotoInfoViewController,declarethePhotoInfoViewControllerclass,andaddanimageViewoutlet.importFoundation

importUIKit

classPhotoInfoViewController:UIViewController{

@IBOutletvarimageView:UIImageView!

}

Nowsetuptheinterfaceforthisviewcontroller.OpenMain.storyboardanddraganewViewControllerontothecanvasfromtheobjectlibrary.Withthisviewcontrollerselected,openitsidentityinspectorandchangetheClasstoPhotoInfoViewController.Whentheusertapsononeofthecollectionviewcells,theapplicationwillnavigatetothisnewviewcontroller.Control-dragfromthePhotoCollectionViewCelltothePhotoInfoViewControllerandselecttheShowsegue.Withthenewsegueselected,openitsattributesinspectorandgivethesegueanIdentifierofshowPhoto(Figure21.14).Figure21.14Navigationtoaphoto

AddanimageviewtothePhotoInfoViewController’sview.SetupitsAutoLayoutconstraintsto

Page 649: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

pintheimageviewtoallfoursides.OpentheattributesinspectorfortheimageviewandsetitsContentModetoAspectFit.Finally,connecttheimageviewtotheimageViewoutlet.Whentheusertapsacell,theshowPhotoseguewillbetriggered.Atthispoint,thePhotosViewControllerwillneedtopassboththePhotoandthePhotoStoretothePhotoInfoViewController.OpenPhotoInfoViewController.swiftandaddtwoproperties.classPhotoInfoViewController:UIViewController{

@IBOutletvarimageView:UIImageView!

varphoto:Photo!{

didSet{

navigationItem.title=photo.title

}

}

varstore:PhotoStore!

}

Whenphotoissetonthisviewcontroller,thenavigationitemwillbeupdatedtodisplaythenameofthephoto.NowoverrideviewDidLoad()tosettheimageontheimageViewwhentheviewisloaded.overridefuncviewDidLoad(){

super.viewDidLoad()

store.fetchImage(for:photo){(result)->Voidin

switchresult{

caselet.success(image):

self.imageView.image=image

caselet.failure(error):

print("Errorfetchingimageforphoto:\(error)")

}

}

}

InPhotosViewController.swift,implementprepare(for:sender:)topassalongthephotoandthestore.overridefuncprepare(forsegue:UIStoryboardSegue,sender:Any?){

switchsegue.identifier{

case"showPhoto"?:

ifletselectedIndexPath=

collectionView.indexPathsForSelectedItems?.first{

letphoto=photoDataSource.photos[selectedIndexPath.row]

letdestinationVC=segue.destinationas!PhotoInfoViewController

destinationVC.photo=photo

destinationVC.store=store

}

default:

preconditionFailure("Unexpectedsegueidentifier.")

}

Page 650: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

}

Buildandruntheapplication.Afterthewebservicerequesthasfinished,tapononeofthephotostoseeitinthenewviewcontroller(Figure21.15).Figure21.15Displayingaphoto

Collectionviewsareapowerfulwaytodisplaydatausingaflexiblelayout.Youhavejustbarelytappedintothepowerofcollectionviewsinthischapter.

Page 651: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 652: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

SilverChallenge:UpdatedItemSizes

Havethecollectionviewalwaysdisplayfouritemsperrow,takingupasmuchasthescreenwidthaspossible.Thisshouldworkinbothportraitandlandscapeorientations.

Page 653: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 654: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

GoldChallenge:CreatingaCustomLayout

Createacustomlayoutthatdisplaysthephotosinaflipbook.Youwillneedtousethetransformpropertyonthecelllayertogetanappropriate3-Deffect.YoucansubclassUICollectionViewLayoutforthischallenge,butalsoconsidersubclassingUICollectionViewFlowLayout.CheckouttheclassreferenceforUICollectionViewLayoutformoreinformation.

Page 655: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 656: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

22CoreData

WhendecidingbetweenapproachestosavingandloadingforiOSapplications,thefirstquestionis“Localorremote?”Ifyouwanttosavedatatoaremoteserver,youwilllikelyuseawebservice.Ifyouwanttostoredatalocally,youhavetoaskanotherquestion:“ArchivingorCoreData?”YourHomepwnerapplicationusedkeyedarchivingtosaveitemdatatothefilesystem.Thebiggestdrawbacktoarchivingisitsall-or-nothingnature:Toaccessanythinginthearchive,youmustunarchivetheentirefile,andtosaveanychanges,youmustrewritetheentirefile.CoreData,ontheotherhand,canfetchasubsetofthestoredobjects.Andifyouchangeanyofthoseobjects,youcanupdatejustthatpartofthefile.Thisincrementalfetching,updating,deleting,andinsertingcanradicallyimprovetheperformanceofyourapplicationwhenyouhavealotofmodelobjectsbeingshuttledbetweenthefilesystemandRAM.

Page 657: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

ObjectGraphs

CoreDataisaframeworkthatletsyouexpresswhatyourmodelobjectsareandhowtheyarerelatedtooneanother.Itthentakescontrolofthelifetimesoftheseobjects,makingsuretherelationshipsarekeptuptodate.Whenyousaveandloadtheobjects,CoreDatamakessureeverythingisconsistent.Thiscollectionofmodelobjectsisoftencalledanobjectgraph,astheobjectscanbethoughtofasnodesandtherelationshipsasverticesinamathematicalgraph.OftenyouwillhaveCoreDatasaveyourobjectgraphtoaSQLitedatabase.DeveloperswhoareusedtootherSQLtechnologiesmightexpecttotreatCoreDatalikeanobject-relationalmappingsystem,butthismindsetwillleadtoconfusion.UnlikeanORM,CoreDatatakescompletecontrolofthestorage,whichjusthappenstobearelationaldatabase.Youdonothavetodescribethingslikethedatabaseschemaandforeignkeys–CoreDatadoesthat.YoujusttellCoreDatawhatneedsstoringandletitworkouthowtostoreit.CoreDatagivesyoutheabilitytofetchandstoredatainarelationaldatabasewithouthavingtoknowthedetailsoftheunderlyingstoragemechanism.ThischapterwillgiveyouanunderstandingofCoreDataasyouaddpersistencetothePhotoramaapplication.

Page 658: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 659: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Entities

Arelationaldatabasehassomethingcalledatable.Atablerepresentsatype:Youcanhaveatableofpeople,atableofacreditcardpurchases,oratableofrealestatelistings.Eachtablehasanumberofcolumnstoholdpiecesofinformationaboutthetype.Atablethatrepresentspeoplemighthavecolumnsforlastname,dateofbirth,andheight.Everyrowinthetablerepresentsanexampleofthetype–e.g.,asingleperson.ThisorganizationtranslateswelltoSwift.EverytableislikeaSwifttype.Everycolumnisoneofthetype’sproperties.Everyrowisaninstanceofthattype.Thus,CoreData’sjobistomovedatatoandfromthesetworepresentations(Figure22.1).Figure22.1RoleofCoreData

CoreDatausesdifferentterminologytodescribetheseideas:Atable/typeiscalledanentity,andthecolumns/propertiesarecalledattributes.ACoreDatamodelfileisthedescriptionofeveryentityalongwithitsattributesinyourapplication.InPhotorama,youaregoingtodescribeaPhotoentityinamodelfileandgiveitattributesliketitle,remoteURL,anddateTaken.

Modelingentities

OpenPhotorama.xcodeproj.Createanewfile,butdonotmakeitaSwiftfileliketheonesyouhavecreatedbefore.Instead,selectiOSatthetopandscrolldowntotheCoreDatasection.CreateanewDataModel(Figure22.2).NameitPhotorama.

Page 660: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure22.2Creatingthemodelfile

ThiswillcreatethePhotorama.xcdatamodeldfileandaddittoyourproject.SelectthisfilefromtheprojectnavigatorandtheeditorareawillrevealtheUIformanipulatingaCoreDatamodelfile.FindtheAddEntitybuttonatthebottomleftofthewindowandclickit.Anewentitywillappearinthelistofentitiesinthelefthandtable.Double-clickthisentityandchangeitsnametoPhoto(Figure22.3).

Page 661: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure22.3CreatingthePhotoentity

NowyourPhotoentityneedsattributes.RememberthatthesewillbethepropertiesofthePhotoclass.Thenecessaryattributesarelistedbelow.Foreachattribute,clickthe+buttonintheAttributessectionandedittheAttributeandTypevalues.

photoIDisaString.titleisaString.dateTakenisaDate.remoteURLisaTransformable.(ItisaURL,butthatisnotoneofthepossibilities.Wewilldiscuss“transformable”next.)

Transformableattributes

CoreDataisonlyabletostorecertaindatatypesinitsstore.URLisnotoneofthesetypes,soyoudeclaredtheremoteURLattributeastransformable.Withatransformableattribute,CoreDatawillconverttheobjectintoatypethatitcanstorewhensavingandthenconvertitbackto

Page 662: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

theoriginalobjectwhenloadingfromthefilesystem.CoreDataworkswithclassesunderthehoodbecauseitisanObjective-Cframework.SoinsteadofworkingwithaninstanceofURL(whichisastruct),youwillworkwithaninstanceofNSURL(whichisaclass)whendealingwithCoreData.SwiftprovidesamechanismforconvertingaURLtoanNSURLandviceversa,whichyouwillseelateroninthischapter.AtransformableattributerequiresaValueTransformersubclasstohandletheconversionsbetweentypes.Ifyoudonotspecifyacustomsubclass,thesystemwillusethetransformernamedNSKeyedUnarchiveFromDataTransformer.ThistransformerusesarchivingtoconverttheobjecttoandfromData.BecauseNSURLconformstoNSCoding,thedefaultNSKeyedUnarchiveFromDataTransformerwillbesufficient.IfthetypeyouwantedtotransformdidnotconformtoNSCoding,youwouldneedtowriteyourowncustomValueTransformersubclass.WithPhotorama.xcdatamodeldstillopen,selecttheremoteURLattributeandopenitsDataModelinspectorontherighthandside.UndertheAttributesection,enterNSURLastheCustomClass.ThiswillallowCoreDatatodothetransformationforyou.Atthispoint,yourmodelfileissufficienttosaveandloadphotos.Inthenextsection,youwillcreateacustomsubclassforthePhotoentity.

NSManagedObjectandsubclasses

WhenanobjectisfetchedwithCoreData,itsclass,bydefault,isNSManagedObject.NSManagedObjectisasubclassofNSObjectthatknowshowtocooperatewiththerestofCoreData.AnNSManagedObjectworksabitlikeadictionary:Itholdsakey-valuepairforeveryproperty(attributeorrelationship)intheentity.AnNSManagedObjectislittlemorethanadatacontainer.Ifyouneedyourmodelobjectstodosomethinginadditiontoholdingdata,youmustsubclassNSManagedObject.Then,inyourmodelfile,youspecifythatthisentityisrepresentedbyinstancesofyoursubclass,notthestandardNSManagedObject.XcodecangenerateNSManagedObjectsubclassesforyoubasedonwhatyouhavedefinedinyourCoreDatamodelfile.Intheprojectnavigator,selectthePhoto.swiftfileanddeleteit.Whenprompted,moveittothetrashtomakesureitdoesnotstillexistintheprojectdirectory.OpenPhotorama.xcdatamodeld.SelectthePhotoentityandopentheDataModelinspector.LocatetheCodegenoptionandselectManual/None.WiththePhotoentitystillselected,opentheEditormenuandselectCreateNSManagedObjectSubclass….Onthenextscreen,checktheboxforPhotoramaandclickNext.ChecktheboxforthePhotoentityandclickNextagain.Finally,clickCreate.Therewillbeafewerrorsintheproject.Youwillfixthoseshortly.

Page 663: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Thetemplatewillcreatetwofilesforyou:Photo+CoreDataClass.swiftandPhoto+CoreDataProperties.swift.ThetemplateplacesalloftheattributesthatyoudefinedinthemodelfileintoPhoto+CoreDataProperties.swift.Ifyoueverchangeyourentityinthemodelfile,youcansimplydeletePhoto+CoreDataProperties.swiftandregeneratetheNSManagedObjectsubclass.XcodewillrecognizethatyoualreadyhavePhoto+CoreDataClass.swiftandwillonlyre-createPhoto+CoreDataProperties.swift.OpenPhoto+CoreDataProperties.swiftandtakealookatwhatthetemplatecreatedforyou.Allofthepropertiesaremarkedwiththe@NSManagedkeyword.Thiskeyword,whichisspecifictoCoreData,letsthecompilerknowthatthestorageandimplementationofthesepropertieswillbeprovidedatruntime.BecauseCoreDatawillcreatetheNSManagedObjectinstances,youcannolongeruseacustominitializer,sothepropertiesaredeclaredasvariablesinsteadofconstants.AnycustompropertiesorcodethatyouwanttoaddshouldbeaddedtoPhoto+CoreDataClass.swift.Let’sfixsomeoftheerrorsthatareintheproject.OpenPhotoStore.swiftandfindfetchImage(for:completion:).ThismethodexpectsthephotoIDandtheremoteURLtobenon-optional;however,CoreDatamodelsitsattributesasoptionals.Additionally,theURLRequestinitializerexpectsaURLinstanceasitsargumentinsteadofanNSURLinstance.Updatethemethodtoaddresstheseissues.funcfetchImage(forphoto:Photo,completion:@escaping(ImageResult)->Void){

guardletphotoKey=photo.photoIDelse{

preconditionFailure("PhotoexpectedtohaveaphotoID.")

}

ifletimage=imageStore.image(forKey:photoKey){

OperationQueue.main.addOperation{

completion(.success(image))

}

return

}

guardletphotoURL=photo.remoteURLelse{

preconditionFailure("PhotoexpectedtohavearemoteURL.")

}

letrequest=URLRequest(url:photoURLasURL)

Toaddressthefirstissue,youareusingaguardstatementtounwraptheoptionalNSURL.Toaddressthesecondissue,youbridgetheNSURLinstancetoaURLinstanceusinganascast.ThecompilerknowsthatNSURLandURLarerelated,soithandlesthebridgingconversion.YouhavecreatedyourmodelgraphanddefinedyourPhotoentity.Thenextstepistosetupthepersistentcontainer,whichwillmanagetheinteractionsbetweentheapplicationandCoreData.Therearestillsomeerrorsintheproject;youwillfixthemafteryouhaveaddedaCoreDatapersistentcontainerinstance.

Page 664: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 665: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

NSPersistentContainer

CoreDataisrepresentedbyacollectionofclassesoftenreferredtoastheCoreDatastack.ThiscollectionofclassesisabstractedawayfromyouviatheNSPersistentContainerclass.YouwilllearnmoreabouttheCoreDatastackclassesintheFortheMoreCurioussectionattheendofthischapter.TouseCoreData,youwillneedtoimporttheCoreDataframeworkinthefilesthatneedit.OpenPhotoStore.swiftandimportCoreDataatthetopofthefile.importUIKit

importCoreData

AlsoinPhotoStore.swift,addapropertytoholdontoaninstanceofNSPersistentContainer.classPhotoStore{

letimageStore=ImageStore()

letpersistentContainer:NSPersistentContainer={

letcontainer=NSPersistentContainer(name:"Photorama")

container.loadPersistentStores{(description,error)in

ifleterror=error{

print("ErrorsettingupCoreData(\(error)).")

}

}

returncontainer

}()

YouinstantiateanNSPersistentContainerwithaname.Thisnamemustmatchthenameofthedatamodelfilethatdescribesyourentities.Aftercreatingthecontainer,itneedstoloaditspersistentstores.Thestoreiswherethedataisactuallystoredondisk.Bydefault,thisisgoingtobeaSQLitedatabase.Duetothepossibilityofthisoperationtakingsometime,loadingthepersistentstoresisanasynchronousoperationthatcallsacompletionhandlerwhencomplete.

Page 666: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 667: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

UpdatingItems

Withthepersistentcontainersetup,youcannowinteractwithCoreData.Primarily,youwilldothisthroughitsviewContext.Thisishowyouwillbothcreatenewentitiesandsavechanges.TheviewContextisaninstanceofNSManagedObjectContext.Thisistheportalthroughwhichyouinteractwithyourentities.Youcanthinkofthemanagedobjectcontextasanintelligentscratchpad.Whenyouaskthecontexttofetchsomeentities,thecontextwillworkwithitspersistentstorecoordinatortobringtemporarycopiesoftheentitiesandobjectgraphintomemory.Unlessyouaskthecontexttosaveitschanges,thepersisteddataremainsthesame.

Insertingintothecontext

Whenanentityiscreated,itshouldbeinsertedintoamanagedobjectcontext.OpenFlickrAPI.swiftandimportCoreData.importFoundation

importCoreData

Next,updatethephoto(fromJSON:)methodtotakeinanadditionalargumentoftypeNSManagedObjectContextandusethiscontexttoinsertnewPhotoinstances.privatestaticfuncphoto(fromJSONjson:[String:Any],

intocontext:NSManagedObjectContext)->Photo?{

guard

letphotoID=json["id"]as?String,

lettitle=json["title"]as?String,

letdateString=json["datetaken"]as?String,

letphotoURLString=json["url_h"]as?String,

leturl=URL(string:photoURLString),

letdateTaken=dateFormatter.date(from:dateString)else{

//Don'thaveenoughinformationtoconstructaPhoto

returnnil

}

returnPhoto(title:title,photoID:photoID,remoteURL:url,dateTaken:dateTaken)

varphoto:Photo!

context.performAndWait{

photo=Photo(context:context)

photo.title=title

photo.photoID=photoID

photo.remoteURL=urlasNSURL

photo.dateTaken=dateTakenasNSDate

}

returnphoto

}

EachNSManagedObjectContextisassociatedwithaspecificconcurrencyqueue,andthe

Page 668: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

viewContextisassociatedwiththemain,orUI,queue.Youhavetointeractwithacontextonthequeuethatitisassociatedwith.NSManagedObjectContexthastwomethodsthatensurethishappens:perform(_:)andperformAndWait(_:).Thedifferencebetweenthemisthatperform(_:)isasynchronousandperformAndWait(_:)issynchronous.Becauseyouarereturningtheresultoftheinsertoperationfromthephoto(fromJSON:into:)method,youusethesynchronousmethod.

Thephoto(fromJSON:into:)methodiscalledfromthemethodphotos(fromJSON:).Updatethismethodtotakeinacontextandpassittothephoto(fromJSON:into:)method.staticfuncphotos(fromJSONdata:Data,

intocontext:NSManagedObjectContext)->PhotosResult{

do{

...

varfinalPhotos=[Photo]()

forphotoJSONinphotosArray{

ifletphoto=photo(fromJSON:photoJSON,into:context){

finalPhotos.append(photo)

}

}

Finally,youneedtopasstheviewContexttotheFlickrAPIstructoncethewebservicerequestsuccessfullycompletes.OpenPhotoStore.swiftandupdateprocessPhotosRequest(data:error:).privatefuncprocessPhotosRequest(data:Data?,error:Error?)->PhotosResult{

guardletjsonData=dataelse{

return.failure(error!)

}

returnFlickrAPI.photos(fromJSON:jsonData,

into:persistentContainer.viewContext)

}

Buildandruntheapplicationnowthatallerrorshavebeenaddressed.Althoughthebehaviorremainsunchanged,theapplicationisnowbackedbyCoreData.Inthenextsection,youwillimplementsavingforboththephotosandtheirassociatedimagedata.

Savingchanges

RecallthatNSManagedObjectchangesdonotpersistuntilyoutellthecontexttosavethesechanges.OpenPhotoStore.swiftandupdatefetchInterestingPhotos(completion:)tosavethechangestothecontextafterPhotoentitieshavebeeninsertedintothecontext.funcfetchInterestingPhotos(completion:@escaping(PhotosResult)->Void){

leturl=FlickrAPI.interestingPhotosURL

letrequest=URLRequest(url:url)

lettask=session.dataTask(with:request){

Page 669: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

(data,response,error)->Voidin

letvarresult=self.processPhotosRequest(data:data,error:error)

ifcase.success=result{

do{

tryself.persistentContainer.viewContext.save()

}catchleterror{

result=.failure(error)

}

}

OperationQueue.main.addOperation{

completion(result)

}

}

task.resume()

}

Page 670: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 671: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

UpdatingtheDataSource

OneproblemwiththeappatthemomentisthatfetchInterestingPhotos(completion:)onlyreturnsthenewlyinsertedphotos.Nowthattheapplicationsupportssaving,itshouldreturnallofthephotos–thepreviouslysavedphotosaswellasthenewlyinsertedones.YouneedtoaskCoreDataforallofthePhotoentities,andyouwillaccomplishthisusingafetchrequest.

Fetchrequestsandpredicates

TogetobjectsbackfromtheNSManagedObjectContext,youmustprepareandexecuteanNSFetchRequest.Afterafetchrequestisexecuted,youwillgetanarrayofalltheobjectsthatmatchtheparametersofthatrequest.Afetchrequestneedsanentitydescriptionthatdefineswhichentityyouwanttogetobjectsfrom.TofetchPhotoinstances,youspecifythePhotoentity.Youcanalsosettherequest’ssortdescriptorstospecifytheorderoftheobjectsinthearray.AsortdescriptorhasakeythatmapstoanattributeoftheentityandaBoolthatindicateswhethertheordershouldbeascendingordescending.ThesortDescriptorspropertyonNSFetchRequestisanarrayofNSSortDescriptorinstances.Whyanarray?Thearrayisusefulifyouthinktheremightbecollisionswhensorting.Forexample,sayyouaresortinganarrayofpeoplebytheirlastnames.Itisentirelypossiblethatmultiplepeoplehavethesamelastname,soyoucanspecifythatpeoplewiththesamelastnameshouldbesortedbytheirfirstnames.ThiswouldbeimplementedbyanarrayoftwoNSSortDescriptorinstances.Thefirstsortdescriptorwouldhaveakeythatmapstotheperson’slastname,andthesecondsortdescriptorwouldhaveakeythatmapstotheperson’sfirstname.ApredicateisrepresentedbytheNSPredicateclassandcontainsaconditionthatcanbetrueorfalse.Ifyouwantedtofindallphotoswithagivenidentifier,youwouldcreateapredicateandaddittothefetchrequestlikethis:letpredicate=NSPredicate(format:"#keyPath(Photo.photoID)==\(someIdentifier)")

request.predicate=predicate

Theformatstringforapredicatecanbeverylongandcomplex.Apple’sPredicateProgrammingGuideisacompletediscussionofwhatispossible.YouwanttosortthereturnedinstancesofPhotobydateTakenindescendingorder.Todothis,youwillinstantiateanNSFetchRequestforrequesting“Photo”entities.ThenyouwillgivethefetchrequestanarrayofNSSortDescriptorinstances.ForPhotorama,thisarraywillcontainasinglesortdescriptorthatsortsphotosbytheirdateTakenproperties.Finally,youwillaskthemanagedobjectcontexttoexecutethisfetchrequest.InPhotoStore.swift,implementamethodthatwillfetchthePhotoinstancesfromtheviewcontext.

Page 672: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

funcfetchAllPhotos(completion:@escaping(PhotosResult)->Void){

letfetchRequest:NSFetchRequest<Photo>=Photo.fetchRequest()

letsortByDateTaken=NSSortDescriptor(key:#keyPath(Photo.dateTaken),

ascending:true)

fetchRequest.sortDescriptors=[sortByDateTaken]

letviewContext=persistentContainer.viewContext

viewContext.perform{

do{

letallPhotos=tryviewContext.fetch(fetchRequest)

completion(.success(allPhotos))

}catch{

completion(.failure(error))

}

}

}

Next,openPhotosViewController.swiftandaddanewmethodthatwillupdatethedatasourcewithallofthephotos.privatefuncupdateDataSource(){

store.fetchAllPhotos{

(photosResult)in

switchphotosResult{

caselet.success(photos):

self.photoDataSource.photos=photos

case.failure:

self.photoDataSource.photos.removeAll()

}

self.collectionView.reloadSections(IndexSet(integer:0))

}

}

NowupdateviewDidLoad()tocallthismethodtofetchanddisplayallofthephotossavedtoCoreData.overridefuncviewDidLoad()

super.viewDidLoad()

collectionView.dataSource=photoDataSource

collectionView.delegate=self

store.fetchInterestingPhotos{

(photosResult)->Voidin

switchphotosResult{

caselet.success(photos):

print("Successfullyfound\(photos.count)photos.")

self.photoDataSource.photos=photos

caselet.failure(error):

print("Errorfetchinginterestingphotos:\(error)")

self.photoDataSource.photos.removeAll()

}

self.collectionView.reloadSections(IndexSet(integer:0))

self.updateDataSource()

}

}

Previouslysavedphotoswillnowbereturnedwhenthewebservicerequestfinishes.Butthere

Page 673: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

isstilloneproblem:Iftheapplicationisrunmultipletimesandthesamephotoisreturnedfromthewebservicerequest,itwillbeinsertedintothecontextmultipletimes.Thisisnotgood–youdonotwantduplicatephotos.Luckilythereisauniqueidentifierforeachphoto.Whentheinterestingphotoswebservicerequestfinishes,theidentifierforeachphotointheincomingJSONdatacanbecomparedtothephotosstoredinCoreData.Ifoneisfoundwiththesameidentifier,thatphotowillbereturned.Otherwise,anewphotowillbeinsertedintothecontext.Todothis,youneedawaytotellthefetchrequestthatitshouldnotreturnallphotosbutinsteadonlythephotosthatmatchsomespecificcriteria.Inthiscase,thespecificcriteriais“onlyphotosthathavethisspecificidentifier,”ofwhichthereshouldeitherbezerooronephoto.InCoreData,thisisdonewithapredicate.InFlickrAPI.swift,updatephoto(fromJSON:into:)tocheckwhetherthereisanexistingphotowithagivenIDbeforeinsertinganewone.privatestaticfuncphoto(fromJSONjson:[String:Any],

intocontext:NSManagedObjectContext)->Photo?{

guard

letphotoID=json["id"]as?String,

lettitle=json["title"]as?String,

letdateString=json["datetaken"]as?String,

letphotoURLString=json["url_h"]as?String,

leturl=URL(string:photoURLString),

letdateTaken=dateFormatter.date(from:dateString)else{

//Don'thaveenoughinformationtoconstructaPhoto

returnnil

}

letfetchRequest:NSFetchRequest<Photo>=Photo.fetchRequest()

letpredicate=NSPredicate(format:"\(#keyPath(Photo.photoID))==\(photoID)")

fetchRequest.predicate=predicate

varfetchedPhotos:[Photo]?

context.performAndWait{

fetchedPhotos=try?fetchRequest.execute()

}

ifletexistingPhoto=fetchedPhotos?.first{

returnexistingPhoto

}

varphoto:Photo!

context.performAndWait{

photo=Photo(context:context)

photo.title=title

photo.photoID=photoID

photo.remoteURL=urlasNSURL

photo.dateTaken=dateTakenasNSDate

}

returnphoto

}

DuplicatephotoswillnolongerbeinsertedintoCoreData.

Page 674: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Buildandruntheapplication.ThephotoswillappearjustastheydidbeforeintroducingCoreData.AsyoudidinChapter16,closetheapplicationusingtheHomebutton(orShift-Command-Hinthesimulator).LaunchtheapplicationagainandyouwillseethephotosthatCoreDatasavedinthecollectionview.Thereisonelastsmallproblemtoaddress:Theuserwillnotseeanyphotosappearinthecollectionviewunlessthewebservicerequestcompletes.Iftheuserhasslownetworkaccess,itmighttakeupto60seconds(whichisthedefaulttimeoutintervalfortherequest)toseeanyphotos.ItwouldbebesttoseethepreviouslysavedphotosimmediatelyonlaunchandthenrefreshthecollectionviewoncenewphotosarefetchedfromFlickr.Goaheadanddothis.InPhotosViewController.swift,updatethedatasourceassoonastheviewisloaded.overridefuncviewDidLoad()

super.viewDidLoad()

collectionView.dataSource=photoDataSource

collectionView.delegate=self

updateDataSource()

store.fetchInterestingPhotos{

(photosResult)->Voidin

self.updateDataSource()

}

}

ThePhotoramaapplicationisnowpersistingitsdatabetweenruns.ThephotometadataisbeingpersistedusingCoreData,andtheimagedataisbeingpersisteddirectlytothefilesystem.Asyouhaveseen,thereisnoone-size-fits-allapproachtodatapersistence.Instead,eachpersistencemechanismhasitsownsetofbenefitsanddrawbacks.Inthischapter,youhaveexploredoneofthose,CoreData,butyouhaveonlyseenthetipoftheiceberg.InChapter23,youwillexploretheCoreDataframeworkfurthertolearnaboutrelationshipsandperformance.

Page 675: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 676: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

BronzeChallenge:PhotoViewCount

AddanattributetothePhotoentitythattrackshowmanytimesaphotoisviewed.DisplaythisnumbersomewhereonthePhotoInfoViewControllerinterface.

Page 677: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 678: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

FortheMoreCurious:TheCoreDataStack

NSManagedObjectModel

Youworkedwiththemodelfileearlierinthechapter.Themodelfileiswhereyoudefinetheentitiesforyourapplicationalongwiththeirproperties.ThemodelfileisaninstanceofNSManagedObjectModel.

NSPersistentStoreCoordinator

CoreDatacanpersistdatainseveralformats:

SQLite DataissavedtodiskusingaSQLitedatabase.Thisisthemostcommonlyusedstoretype.

Atomic Dataissavedtodiskusingabinaryformat.

XML DataissavedtodiskusinganXMLformat.ThisstoretypeisnotavailableoniOS.

In-Memory Dataisnotsavedtodisk,butinsteadisstoredinmemory.

ThemappingbetweenanobjectgraphandthepersistentstoreisaccomplishedusinganinstanceofNSPersistentStoreCoordinator.Thepersistentstorecoordinatorneedstoknowtwothings:“Whataremyentities?”and,“WhereamIsavingtoandloadingdatafrom?”Toanswerthesequestions,youinstantiateanNSPersistentStoreCoordinatorwiththeNSManagedObjectModel.Thenyouaddapersistentstore,representingoneofthepersistenceformatsabove,tothecoordinator.Afterthecoordinatoriscreated,youattempttoaddaspecificstoretothecoordinator.Ataminimum,thisstoreneedstoknowitstypeandwhereitshouldpersistthedata.

NSManagedObjectContext

TheportalthroughwhichyouinteractwithyourentitiesistheNSManagedObjectContext.Themanagedobjectcontextisassociatedwithaspecificpersistentstorecoordinator.Youcanthinkofthemanagedobjectcontextasanintelligentscratchpad.Whenyouaskthecontexttofetchsomeentities,thecontextwillworkwithitspersistentstorecoordinatortobringtemporarycopiesoftheentitiesandobjectgraphintomemory.Unlessyouaskthecontexttosaveitschanges,thepersisteddataremainsthesame.

Page 679: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 680: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

23CoreDataRelationships

CoreDataisnotthatexcitingwithjustoneentity.MuchofthepowerbehindCoreDatacomestolightwhentherearemultipleentitiesthatarerelatedtooneanother,becauseCoreDatamanagesrelationshipsbetweenentities.Inthischapter,youaregoingtoaddtagstothephotosinPhotoramawithlabelssuchas“Nature,”“Electronics,”or“Selfies.”Userswillbeabletoaddoneormoretagstophotosandalsocreatetheirowncustomtags(Figure23.1).Figure23.1FinalPhotoramaapplication

Page 681: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Relationships

OneofthebenefitsofusingCoreDataisthatentitiescanberelatedtooneanotherinawaythatallowsyoutodescribecomplexmodels.Relationshipsbetweenentitiesarerepresentedbyreferencesbetweenobjects.Therearetwokindsofrelationships:to-oneandto-many.Whenanentityhasato-onerelationship,eachinstanceofthatentitywillhaveareferencetoaninstanceintheentityithasarelationshipto.Whenanentityhasato-manyrelationship,eachinstanceofthatentityhasareferencetoaSet.Thissetcontainstheinstancesoftheentitythatithasarelationshipwith.Toseethisinaction,youaregoingtoaddanewentitytothemodelfile.ReopenthePhotoramaapplication.InPhotorama.xcdatamodeld,addanotherentitycalledTag.GiveitanattributecallednameoftypeString.Tagwillallowuserstotagphotos.UnlikewiththePhotoentityinChapter22,youwillnotgenerateanNSManagedObjectsubclassfortheTagentity.Instead,youwillletXcodeautogenerateasubclassforyouthroughafeaturecalledcodegeneration.IfyoudonotneedanycustombehaviorforyourCoreDataentity,lettingXcodegenerateyoursubclassforyouisquitehelpful.TheNSManagedObjectsubclassfortheTagentityisalreadybeinggeneratedforyou.Toseethesettingthatdeterminesthis,selecttheTagentityandopenitsdatamodelinspector.IntheClasssection,noticethesettingforCodegen:ItiscurrentlysettoClassDefinition.Thissettingmeansthatanentireclassdefinitionwillbegeneratedforyou.TheothercodegenerationsettingsareCategory/Extension(whichallowsyoutodefineanNSManagedObjectsubclasswithcustombehaviorwhilestillallowingXcodetogeneratetheextensionthatdefinestheattributesandrelationships)andManual/None(whichtellsXcodenottogenerateanycodefortheentity).Aphotomighthavemultipletagsthatdescribeit,andatagmightbeassociatedwithmultiplephotos.Forexample,apictureofaniPhonemightbetagged“Electronics”and“Apple,”andapictureofaBetamaxplayermightbetagged“Electronics”and“Rare.”TheTagentitywillhaveato-manyrelationshiptothePhotoentitybecausemanyinstancesofPhotocanhavethesameTag.AndthePhotoentitywillhaveato-manyrelationshiptotheTagentitybecauseaphotocanbeassociatedwithmanyTags.AsFigure23.2shows,aPhotowillhaveareferencetoasetofTags,andaTagwillhaveareferencetoasetofPhotos.

Page 682: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure23.2EntitiesinPhotorama

Whentheserelationshipsaresetup,youwillbeabletoaskaPhotoobjectforthesetofTagobjectsthatitisassociatedwithandaskaTagobjectforthesetofPhotoobjectsthatitisassociatedwith.Toaddthesetworelationshipstothemodelfile,firstselecttheTagentityandclickthe+buttonintheRelationshipssection.ClickintheRelationshipcolumnandenterphotos.IntheDestinationcolumn,selectPhoto.Inthedatamodelinspector,changetheTypedropdownfromToOnetoToMany(Figure23.3).Figure23.3Creatingthephotosrelationship

Next,selectthePhotoentity.AddarelationshipnamedtagsandpickTagasitsdestination.Inthedatamodelinspector,changetheTypedropdowntoToManyanduncheckitsOptionalcheckbox.Nowthatyouhavetwounidirectionalrelationships,youcanmakethemintoaninverse

Page 683: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

relationship.Aninverserelationshipisabidirectionalrelationshipbetweentwoentities.WithaninverserelationshipsetupbetweenPhotoandTag,CoreDatacanensurethatyourobjectgraphremainsinaconsistentstatewhenanychangesaremade.Tocreatetheinverserelationship,clickthedropdownnexttoInverseinthedatamodelinspectorandchangeitfromNoInverseRelationshiptophotos(Figure23.4).(YoucanalsomakethischangeintheRelationshipssectionintheeditorareabyclickingNoInverseintheInversecolumnandselectingphotos.)IfyoureturntotheTagentity,youwillseethatthephotosrelationshipnowshowstagsasitsinverse.Figure23.4Creatingthetagsrelationship

NowthatthemodelhaschangedforthePhotoentity,youwillneedtoregeneratethePhoto+CoreDataProperties.swiftfile.Fromtheprojectnavigator,selectanddeletethePhoto+CoreDataProperties.swiftfile.MakesuretoselectMovetoTrashwhenprompted.OpenPhotorama.xcdatamodeldandselectthePhotoentity.FromtheEditormenu,selectCreateNSManagedObjectSubclass….Onthenextscreen,checktheboxforPhotoramaandclickNext.ChecktheboxforthePhotoentityandclickNext.MakesureyouarecreatingthefileinthesamedirectoryasthePhoto+CoreDataClass.swiftfile;thiswillensurethatXcodewillonlycreatethenecessaryPhoto+CoreDataProperties.swiftfile.Onceyouhaveconfirmedthis,clickCreate.

Page 684: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 685: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

AddingTagstotheInterface

Whenusersnavigatetoaspecificphoto,theycurrentlyseeonlythetitleofthephotoandtheimageitself.Let’supdatetheinterfacetoincludeaphoto’sassociatedtags.OpenMain.storyboardandnavigatetotheinterfaceforPhotoInfoViewController.Addatoolbartothebottomoftheview.UpdatetheAutoLayoutconstraintssothatthetoolbarisanchoredtothebottom,justasitwasinHomepwner.ThebottomconstraintfortheimageViewshouldbeanchoredtothetopofthetoolbarinsteadofthebottomofthesuperview.AddaUIBarButtonItemtothetoolbar,ifoneisnotalreadypresent,andgiveitatitleofTags.YourinterfacewilllooklikeFigure23.5.Figure23.5PhotoInfoViewControllerinterface

CreateanewSwiftfilenamedTagsViewController.OpenthisfileanddeclaretheTagsViewControllerclassasasubclassofUITableViewController.Import

Page 686: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

UIKitandCoreDatainthisfile.importFoundation

importUIKit

importCoreData

classTagsViewController:UITableViewController{

}

TheTagsViewControllerwilldisplayalistofallthetags.Theuserwillseeandbeabletoselectthetagsthatareassociatedwithaspecificphoto.Theuserwillalsobeabletoaddnewtagsfromthisscreen.ThecompletedinterfacewilllooklikeFigure23.6.Figure23.6TagsViewController

GivetheTagsViewControllerclassapropertytoreferencethePhotoStoreaswellasaspecificPhoto.Youwillalsoneedapropertytokeeptrackofthecurrentlyselectedtags,whichyouwilltrackusinganarrayofIndexPathinstances.classTagsViewController:UITableViewController{

varstore:PhotoStore!

varphoto:Photo!

varselectedIndexPaths=[IndexPath]()

}

Thedatasourceforthetableviewwillbeaseparateclass.AswediscussedwhenyoucreatedPhotoDataSourceinChapter21,anapplicationwhosetypeshaveasingleresponsibilityiseasiertoadapttofuturechanges.Thisclasswillberesponsiblefordisplayingthelistoftagsinthetableview.CreateanewSwiftfilenamedTagDataSource.swift.DeclaretheTagDataSourceclassandimplementthetableviewdatasourcemethods.YouwillneedtoimportUIKitandCoreData.

Page 687: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

importFoundation

importUIKit

importCoreData

classTagDataSource:NSObject,UITableViewDataSource{

vartags:[Tag]=[]

functableView(_tableView:UITableView,

numberOfRowsInSectionsection:Int)->Int{

returntags.count

}

functableView(_tableView:UITableView,

cellForRowAtindexPath:IndexPath)->UITableViewCell{

letcell=tableView.dequeueReusableCell(withIdentifier:"UITableViewCell",

for:indexPath)

lettag=tags[indexPath.row]

cell.textLabel?.text=tag.name

returncell

}

}

OpenPhotoStore.swiftanddefineanewresulttypeatthetopforusewhenfetchingtags.enumPhotosResult{

casesuccess([Photo])

casefailure(Error)

}

enumTagsResult{

casesuccess([Tag])

casefailure(Error)

}

classPhotoStore{

Nowdefineanewmethodthatfetchesallthetagsfromtheviewcontext.funcfetchAllTags(completion:@escaping(TagsResult)->Void){

letfetchRequest:NSFetchRequest<Tag>=Tag.fetchRequest()

letsortByName=NSSortDescriptor(key:#keyPath(Tag.name),ascending:true)

fetchRequest.sortDescriptors=[sortByName]

letviewContext=persistentContainer.viewContext

viewContext.perform{

do{

letallTags=tryfetchRequest.execute()

completion(.success(allTags))

}catch{

completion(.failure(error))

}

}

}

OpenTagsViewController.swiftandsetthedataSourceforthetableviewtobean

Page 688: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

instanceofTagDataSource.classTagsViewController:UITableViewController{

varstore:PhotoStore!

varphoto:Photo!

varselectedIndexPaths=[IndexPath]()

lettagDataSource=TagDataSource()

overridefuncviewDidLoad(){

super.viewDidLoad()

tableView.dataSource=tagDataSource

}

}

Nowfetchthetagsandassociatethemwiththetagspropertyonthedatasource.overridefuncviewDidLoad(){

super.viewDidLoad()

tableView.dataSource=tagDataSource

updateTags()

}

funcupdateTags(){

store.fetchAllTags{

(tagsResult)in

switchtagsResult{

caselet.success(tags):

self.tagDataSource.tags=tags

caselet.failure(error):

print("Errorfetchingtags:\(error).")

}

self.tableView.reloadSections(IndexSet(integer:0),

with:.automatic)

}

}

TheTagsViewControllerneedstomanagetheselectionoftagsandupdatethePhotoinstancewhentheuserselectsordeselectsatag.InTagsViewController.swift,addtheappropriateindexpathstotheselectedIndexPathsarray.overridefuncviewDidLoad(){

super.viewDidLoad()

tableView.dataSource=tagDataSource

tableView.delegate=self

updateTags()

}

funcupdateTags(){

store.fetchAllTags{

Page 689: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

(tagsResult)in

switchtagsResult{

caselet.success(tags):

self.tagDataSource.tags=tags

guardletphotoTags=self.photo.tagsas?Set<Tag>else{

return

}

fortaginphotoTags{

ifletindex=self.tagDataSource.tags.index(of:tag){

letindexPath=IndexPath(row:index,section:0)

self.selectedIndexPaths.append(indexPath)

}

}

caselet.failure(error):

print("Errorfetchingtags:\(error).")

}

self.tableView.reloadSections(IndexSet(integer:0),

with:.automatic)

}

}

NowaddtheappropriateUITableViewDelegatemethodstohandleselectinganddisplayingthecheckmarks.overridefunctableView(_tableView:UITableView,

didSelectRowAtindexPath:IndexPath){

lettag=tagDataSource.tags[indexPath.row]

ifletindex=selectedIndexPaths.index(of:indexPath){

selectedIndexPaths.remove(at:index)

photo.removeFromTags(tag)

}else{

selectedIndexPaths.append(indexPath)

photo.addToTags(tag)

}

do{

trystore.persistentContainer.viewContext.save()

}catch{

print("CoreDatasavefailed:\(error).")

}

tableView.reloadRows(at:[indexPath],with:.automatic)

}

overridefunctableView(_tableView:UITableView,

willDisplaycell:UITableViewCell,

forRowAtindexPath:IndexPath){

ifselectedIndexPaths.index(of:indexPath)!=nil{

cell.accessoryType=.checkmark

}else{

cell.accessoryType=.none

}

}

Page 690: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Let’ssetupTagsViewControllertobepresentedmodallywhentheusertapstheTagsbarbuttonitemonthePhotoInfoViewController.OpenMain.storyboardanddragaNavigationControllerontothecanvas.ThisshouldgiveyouaUINavigationControllerwitharootviewcontrollerthatisaUITableViewController.IftherootviewcontrollerisnotaUITableViewController,deletetherootviewcontroller,dragaTableViewControllerontothecanvas,andmakeittherootviewcontrolleroftheNavigationController.Control-dragfromtheTagsitemonPhotoInfoViewControllertothenewNavigationControllerandselectthePresentModallyseguetype(Figure23.7).OpentheattributesinspectorforthesegueandgiveitanIdentifiernamedshowTags.Figure23.7Addingthetagsviewcontroller

SelecttheRootViewControllerthatyoujustaddedtothecanvasandopenitsidentityinspector.ChangeitsClasstoTagsViewController.Thisnewviewcontrollerdoesnothaveanavigationitemassociatedwithit,sofindNavigationItemintheobjectlibraryanddragitontotheviewcontroller.Double-clickthenewnavigationitem’sTitlelabelandchangeittoTags.Next,theUITableViewCellontheTagsViewControllerinterfaceneedstomatchwhattheTagDataSourceexpects.Itneedstousethecorrectstyleandhavethecorrectreuseidentifier.SelecttheUITableViewCell.(Itmightbeeasiertoselectinthedocumentoutline.)Openitsattributesinspector.ChangetheStyletoBasicandsettheIdentifiertoUITableViewCell(Figure23.8).

Page 691: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure23.8ConfiguringtheUITableViewCell

Now,theTagsViewControllerneedstwobarbuttonitemsonitsnavigationbar:aDonebuttonthatdismissestheviewcontrolleranda+buttonthatallowstheusertoaddanewtag.DragabarbuttonitemtotheleftandrightbarbuttonitemslotsfortheTagsViewController.SettheleftitemtousetheDonestyleandsystemitem.SettherightitemtousetheBorderedstyleandAddsystemitem(Figure23.9).Figure23.9Barbuttonitemattributes

CreateandconnectanactionforeachoftheseitemstotheTagsViewController.TheDoneitemshouldbeconnectedtoamethodnameddone(_:),andthe+itemshouldbeconnectedtoamethodnamedaddNewTag(_:).ThetwomethodsinTagsViewController.swiftwillbe:@IBActionfuncdone(_sender:UIBarButtonItem){

}

Page 692: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

@IBActionfuncaddNewTag(_sender:UIBarButtonItem){

}

Theimplementationofdone(_:)issimple:Theviewcontrollerjustneedstobedismissed.Implementthisfunctionalityindone(_:).@IBActionfuncdone(_sender:UIBarButtonItem){

presentingViewController?.dismiss(animated:true,

completion:nil)

}

Whentheusertapsthe+item,analertwillbepresentedthatwillallowtheusertotypeinthenameforanewtag.Figure23.10Addinganewtag

SetupandpresentaninstanceofUIAlertControllerinaddNewTag(_:).@IBActionfuncaddNewTag(_sender:UIBarButtonItem){

letalertController=UIAlertController(title:"AddTag",

message:nil,

preferredStyle:.alert)

alertController.addTextField{

(textField)->Voidin

textField.placeholder="tagname"

textField.autocapitalizationType=.words

}

letokAction=UIAlertAction(title:"OK",style:.default){

(action)->Voidin

}

alertController.addAction(okAction)

letcancelAction=UIAlertAction(title:"Cancel",

style:.cancel,

handler:nil)

alertController.addAction(cancelAction)

present(alertController,

animated:true,

completion:nil)

}

UpdatethecompletionhandlerfortheokActiontoinsertanewTagintothecontext.Thensavethecontext,updatethelistoftags,andreloadthetableviewsection.letokAction=UIAlertAction(title:"OK",style:.default){

(action)->Voidin

Page 693: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

iflettagName=alertController.textFields?.first?.text{

letcontext=self.store.persistentContainer.viewContext

letnewTag=NSEntityDescription.insertNewObject(forEntityName:"Tag",

into:context)

newTag.setValue(tagName,forKey:"name")

do{

tryself.store.persistentContainer.viewContext.save()

}catchleterror{

print("CoreDatasavefailed:\(error)")

}

self.updateTags()

}

}

alertController.addAction(okAction)

Finally,whentheTagsbarbuttonitemonPhotoInfoViewControlleristapped,thePhotoInfoViewControllerneedstopassalongitsstoreandphotototheTagsViewController.OpenPhotoInfoViewController.swiftandimplementprepare(for:).overridefuncprepare(forsegue:UIStoryboardSegue,sender:Any?){

switchsegue.identifier{

case"showTags"?:

letnavController=segue.destinationas!UINavigationController

lettagController=navController.topViewControlleras!TagsViewController

tagController.store=store

tagController.photo=photo

default:

preconditionFailure("Unexpectedsegueidentifier.")

}

}

Buildandruntheapplication.NavigatetoaphotoandtaptheTagsitemonthetoolbaratthebottom.TheTagsViewControllerwillbepresentedmodally.Tapthe+item,enteranewtag,andselectthenewtagtoassociateitwiththephoto.

Page 694: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 695: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

BackgroundTasks

TheviewContextofNSPersistentContainerisassociatedwiththemainqueue.Becauseofthis,anyoperationsthattakealongtimewillblockthemainqueue,whichcanleadtoanunresponsiveapplication.Toaddressthis,itisoftenagoodideatodoexpensiveoperationsonabackgroundtask.Theinsertionofphotosfromthewebserviceisagoodcandidateforabackgroundtask.YouaregoingtoupdateprocessPhotosRequest(data:error:)touseabackgroundtask.Backgroundtasksareanasynchronousoperation,soyouwillneedtoupdatethemethodsignaturetouseacompletionhandler.OpenPhotoStore.swiftandupdateprocessPhotosRequest(data:error:)totakeinacompletionhandler.Youwillhavesomeerrorsinthecodeduetothesignaturechange;youwillfixtheseshortly.privatefuncprocessPhotosRequest(data:Data?,error:Error?)->PhotosResult{

privatefuncprocessPhotosRequest(data:Data?,

error:Error?,

completion:@escaping(PhotosResult)->Void){

guardletjsonData=dataelse{

return.failure(error!)

}

returnFlickrAPI.photos(fromJSON:jsonData,

into:persistentContainer.viewContext)

}

Ifthereisnodata,youwillneedtocallthecompletionhandler,passinginthefailureerrorinsteadofdirectlyreturning.Updatetheguardstatementtopassalongthefailure.privatefuncprocessPhotosRequest(data:Data?,

error:Error?,

completion:@escaping(PhotosResult)->Void){

guardletjsonData=dataelse{

return.failure(error!)

completion(.failure(error!))

return

}

returnFlickrAPI.photos(fromJSON:jsonData,

into:persistentContainer.viewContext)

}

Noticetheuseofreturnwithintheguardstatement.Recallthatwithaguardstatement,youmustexitscope.Thescopeoftheguardstatementisthefunctionitself,soyoumustexitthescopeofthefunctionsomehow.Thisisafantasticbenefittousingaguardstatement.Thecompilerwillenforcethisrequirement,soyoucanbecertainthatnocodebelowtheguardstatementwillbeexecuted.Nowyoucanaddinthecodeforthebackgroundtask.NSPersistentContainerhasamethodtoperformabackgroundtask.Thismethodtakesinaclosuretocall,andthisclosurevendsanewNSManagedObjectContexttouse.UpdateprocessPhotosRequest(data:error:completion:)tokickoffanew

Page 696: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

backgroundtask.privatefuncprocessPhotosRequest(data:Data?,

error:Error?,

completion:@escaping(PhotosResult)->Void){

guardletjsonData=dataelse{

completion(.failure(error!))

return

}

returnFlickrAPI.photos(fromJSON:jsonData,

into:persistentContainer.viewContext)

persistentContainer.performBackgroundTask{

(context)in

}

}

Withinthebackgroundtask,youwilldoessentiallythesamethingyoudidbefore.TheFlickrAPIstructwillingesttheJSONdataandconvertittoPhotoinstances.Thenyouwillsavethecontextsothattheinsertionspersist.UpdatethebackgroundtaskinprocessPhotosRequest(data:error:completion:)todothis.persistentContainer.performBackgroundTask{

(context)in

letresult=FlickrAPI.photos(fromJSON:jsonData,into:context)

do{

trycontext.save()

}catch{

print("ErrorsavingtoCoreData:\(error).")

completion(.failure(error))

return

}

}

Hereiswherethingschangeabit.AnNSManagedObjectshouldonlybeaccessedfromthequeuethatitisassociatedwith.AftertheexpensiveoperationofinsertingthePhotoinstancesandsavingthecontext,youwillwanttofetchthesamephotos,butonlythosethatareassociatedwiththeviewContext(i.e.,thephotosassociatedwiththemainqueue).EachNSManagedObjecthasanobjectIDthatisthesameacrossdifferentcontexts.YouwillusethisobjectIDtofetchthecorrespondingPhotoinstancesassociatedwiththeviewContext.UpdateprocessPhotosRequest(data:error:completion:)togetthePhotoinstancesassociatedwiththeviewContextandpassthembacktothecallerviathecompletionhandler.persistentContainer.performBackgroundTask{

(context)in

letresult=FlickrAPI.photos(fromJSON:jsonData,into:context)

Page 697: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

do{

trycontext.save()

}catch{

print("ErrorsavingtoCoreData:\(error).")

completion(.failure(error))

return

}

switchresult{

caselet.success(photos):

letphotoIDs=photos.map{return$0.objectID}

letviewContext=self.persistentContainer.viewContext

letviewContextPhotos=

photoIDs.map{returnviewContext.object(with:$0)}as![Photo]

completion(.success(viewContextPhotos))

case.failure:

completion(result)

}

}

HereyouareusingthemapmethodonArraytotransformonearrayintoanotherarray.Thiscode:letphotoIDs=photos.map{return$0.objectID}

hasthesameresultasthiscode:varphotoIDs=[String]()

forphotoinphotos{

photoIDs.append(photo.objectID)

}

The$0intheclosureisashorthandwayofaccessingtheargumentsoftheclosure.Iftherearetwoparameters,forexample,theirargumentscanbeaccessedby$0and$1.Sothiscode:letphotosIDs=photos.map{return$0.objectID}

alsohasthesameresultasthiscode:letphotoIDs=photos.map{

(photo:Photo)in

returnphoto.objectID

}

Let’stakealookatthecodebeingusinginthebackgroundtaskagain.letphotoIDs=photos.map{return$0.objectID}

letviewContext=self.persistentContainer.viewContext

letviewContextPhotos=

photoIDs.map{returnviewContext.object(with:$0)}as![Photo]

ThefirstthingthatyouaredoingisgettinganarrayofalloftheobjectIDsassociatedwiththePhotoinstances.ThiswillbeanarrayofStringinstances.Withintheclosure,$0isoftypePhoto.ThenyoucreatealocalvariabletoreferencetheviewContext.Finally,youmapoverthephotoIDs.Withintheclosure,$0isoftypeString.YouusethisstringtoasktheviewContextfortheobjectassociatedwithaspecificobjectidentifier.Themethodobject(with:)returnsanNSManagedObject,sotheresultoftheentiremapoperationwillbeanarrayofNSManagedObjectinstances.YouknowthattheinstancesbeingreturnedwillbeoftypePhoto,soyoudowncastthearrayofNSManagedObjectinstances

Page 698: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

intoanarrayofPhotoinstances.Themapmethodisausefulabstractionforthecommonoperationofconvertingonearrayintoanotherarray.ThefinalchangeyouneedtomakeistoupdatefetchInterestingPhotos(completion:)tousetheupdatedprocessPhotosRequest(data:error:completion:)method.funcfetchInterestingPhotos(completion:@escaping(PhotosResult)->Void){

leturl=FlickrAPI.interestingPhotosURL

letrequest=URLRequest(url:url)

lettask=session.dataTask(with:request){

(data,response,error)->Voidin

varresult=self.processPhotosRequest(data:data,error:error)

ifcase.success=result{

do{

tryself.persistentContainer.viewContext.save()

}catchleterror{

result=.failure(error)

}

}

OperationQueue.main.addOperation{

completion(result)

}

self.processPhotosRequest(data:data,error:error){

(result)in

OperationQueue.main.addOperation{

completion(result)

}

}

}

task.resume()

}

Buildandruntheapplication.Althoughthebehaviorhasnotchanged,theapplicationisnolongerindangerofbecomingunresponsivewhilenewphotosarebeingadded.Asthescaleofyourapplicationsincreases,handlingCoreDataentitiessomewhereotherthanthemainqueueasyouhavedoneherecanresultinhugeperformancewins.Congratulations!Overthepastfourchapters,youhaveworkedonarathercomplexapp.Photoramaisabletomakemultiplewebservicecalls,displayphotosinagrid,cacheimagedatatothefilesystem,andpersistphotodatausingCoreData.Toaccomplishthis,youusedknowledgethatyouhavegainedthroughoutthisbook,andyouappliedthatknowledgetocreateanawesomeappthatisalsorobustandmaintainable.Itwashardwork,andyoushouldbeproudofyourself.

Page 699: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 700: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

SilverChallenge:Favorites

Allowtheusertofavoritephotos.Becreativeinhowyoupresentthefavoritephotostotheuser.TwopossibilitiesincludeviewingthemusingaUITabBarControlleroraddingaUISegmentedControltothePhotosViewControllerthatswitchesbetweenallphotosandfavoritephotos.(Hint:YouwillneedtoaddanewattributetothePhotoentity.)

Page 701: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 702: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

24Accessibility

iOSisthemostaccessiblemobileplatformintheworld.Whetherauserneedssupportforvision,hearing,motorskills,orlearningchallenges,iOSprovideswaystohelp.Mostaccessibilityfeaturesarebuiltintothesystem,soyou,thedeveloper,donotneedtodoanything.Someallowthedevelopertoprovideanevenricherexperiencefortheuser,oftenwithverylittleworkonthedeveloper ’spart.Let’stakealookatsomeoftheaccessibilityoptionsthatiOSprovides.

Page 703: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

VoiceOver

VoiceOverisanaccessibilityfeaturethathelpsuserswithvisualimpairmentsnavigateyourapplication’sinterface.Appleprovideshooksintothesystemthatallowyoutodescribeaspectsofyourinterfacetotheuser.MostUIKitviewsandcontrolsautomaticallyprovideusefulinformationtotheuser,butitisoftenbeneficialtoprovideadditionalinformationthatcannotbeinferred.Andyouwillalwaysneedtoprovidetheinformationyourselfforcustomviewsorcontrolsyoucreate.ThesehintstotheuserarelargelyprovidedthroughtheUIAccessibilityprotocol.Let’stakealookatthisprotocolandtheinformationthatitprovides.TheUIAccessibilityprotocolisaninformalprotocolthatisimplementedonallofthestandardUIKitviewsandcontrols.Aninformalprotocolisalooser“contract”thantheformalprotocolsthatyouhavebeenintroducedtobefore.Aformalprotocolisdeclaredusingtheprotocolkeywordanddeclaresalistofmethodsandpropertiesthatmustbeimplementedbysomethingthatconformstothatprotocol.AninformalprotocolisimplementedasanextensiononNSObject;therefore,allsubclassesofNSObjectimplicitlyconformtotheprotocol.YoumightbewonderingwhyUIAccessibilityisnotaregular,formalprotocolliketheothersyouhaveseenthroughoutthisbook.InformalprotocolsarealegacyofthedayswhenObjective-Cdidnothaveoptionalmethodsinformalprotocols.Informalprotocolswereaworkaroundtosolvethisissue.Essentially,theyrequiredeveryNSObjecttodeclareamethodwithnocorrespondingimplementation.Then,subclassescouldimplementthemethodsthattheywereinterestedin.Atruntime,anobjectwouldbeaskedifithadanimplementationforthosemethods.SomeoftheusefulpropertiesprovidedbytheUIAccessibilityprotocolare:accessibilityLabel

Ashortdescriptionofanelement.Forviewswithtext,thisisoftenthetextthattheviewisdisplaying.accessibilityHint

Ashortdescriptionoftheresultofinteractingwiththeassociatedelement.Forexample,theaccessibilityhintforabuttonthatstopsvideorecordingmightbe“Stoprecording.”accessibilityFrame

Theframeoftheaccessibilityelement.ForUIViewobjects,thisisequaltotheframeoftheview.accessibilityTraits

Descriptionsofthecharacteristicsoftheelement.Therearealotoftraits,andmultipletraitscanbeusedtodescribetheelement.Toseealistofallofthepossibletraits,lookatthedocumentationforUIAccessibilityTraits.accessibilityValue

Page 704: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Adescriptionofthevalueofanelement,independentofitslabeldescription.Forexample,aUITextFieldwillhaveanaccessibilityvaluethatisthecontentsofthetextfield,andaUISliderwillhaveanaccessibilityvaluethatisthepercentagethatthesliderhasbeensetto.Let’stakealookathowtoimplementaccessibilityviathePhotoramaapplication.ReopenPhotorama.xcodeproj.YouaregoingtoimplementVoiceOveraccessibilityfeatures.Currently,Photoramaisnotveryaccessibleatall.Let’sstartbyconsideringhowtheapplicationwouldlooktosomeonewithvisualimpairments.

TestingVoiceOver

ThebestwaytotestVoiceOveriswithanactualdevice,sowestronglyrecommendusingadeviceifyouhaveoneavailable.Ifyoudonothaveadeviceavailable,youcanusethesimulator.BeginbyclickingontheXcodemenuandchoosingOpenDeveloperTool→AccessibilityInspector.Buildandruntheapplication;oncethesimulatorisrunningtheapp,switchtotheAccessibilityInspectorandselectthesimulatorfromthetargetdropdownlist(Figure24.1).Figure24.1ChangingtargetsintheAccessibilityInspector

Page 705: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Oncethetargethasbeensettothesimulator,clicktheStartinspectionfollowspointbuttonontheAccessibilityInspector’stoolbar.Asyoumouseoverandnavigateinthesimulator,theAccessibilityInspectorwillprovideinformationaboutwhateverelementhasfocusonthesimulator ’sscreen.VoiceOverisnotincludedonthesimulator,buttheinformationshownintheAccessibilityInspectorissimilar.Ifyouhaveadevice,openSettings,chooseGeneral→Accessibility→VoiceOver,andfinallyturnonVoiceOver(Figure24.2).

Page 706: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure24.2EnablingVoiceOver

ThereareacoupleofwaystonavigatewithVoiceOveron.Tostart,slideyourfingeraroundthescreen.Noticethatthesystemspeaksadescriptionofwhateverelementyourfingeriscurrentlyover.NowtaptheBackbuttoninthetopleftcornerofthescreenthatsaysAccessibility.Thesystemwilltellyouthatthiselementisthe“Accessibility-Backbutton.”ThesystemisreadingyouboththeaccessibilityLabelaswellaswhatisessentiallytheaccessibilityTraits.NoticethattappingtheAccessibilityBackbuttondoesnottakeyoubacktothepreviousscreen.Toactivatetheselecteditem,double-tapanywhereonthescreen.Thiscorrespondstoasingle-tapwithVoiceOverdisabled.ThiswilltakeyoutothepreviousscreenforAccessibility.Anotherwaytonavigateistoswipeleftandrightonthescreen.Thiswillselectthepreviousandnextaccessibleelementsonthescreen,respectively.TheVoiceOverrowshouldbeselected.Playaroundwithswipingleftandrighttomovethefocusaroundthescreen.Swipewiththreefingerstoscroll.Notethattoscroll,thescrollvieworoneofitssubviews

Page 707: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

mustbethecurrentlyfocusedelement.Playaroundwithsingle-anddouble-tapstoselectandactivateitemsaswellasusingthreefingerstoscroll.ThisishowyouwillnavigatewithVoiceOverenabled.OnefinalusefulgesturetoknowishowtoenableScreenCurtain.Usingthreefingers,triple-tapanywhereonthescreen.Theentirescreenwillgoblack,allowingyoutotrulytestandexperiencehowyourappwillfeeltosomeonewithavisualimpairment.Three-fingertriple-tapanywhereagaintoturnScreenCurtainoff.

AccessibilityinPhotorama

WithVoiceOverstillenabled,buildandrunPhotoramaonyourdevicetotestitsaccessibility.Oncetheapplicationisrunning,dragyourfingeraroundthescreen.Noticethatthesystemisplayingadulledbeepingsoundasyoudragoverthephotos.Thisisthesystem’swayofinformingyouthatitisnotabletofindanaccessibilityelementunderyourfinger.Currently,thePhotoCollectionViewCellsarenotaccessibilityelements.Thisiseasytofix.OpenPhotoCollectionViewCell.swiftandoverridetheisAccessibilityElementpropertytoletthesystemknowthateachcellisaccessible.overridevarisAccessibilityElement:Bool{

get{

returntrue

}

set{

super.isAccessibilityElement=newValue

}

}

Nowbuildandruntheapplication.Asyoudragyourfingeracrossthephotos,youwillhearamoreaffirmingbeepandseeeachcelloutlinedwiththefocusrectangle(Figure24.3).Nodescriptionisspoken,butyouaremakingprogress.

Page 708: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Figure24.3Accessiblecells

GobacktoPhotoCollectionViewCell.swift.YouaregoingtoaddanaccessibilitylabelforVoiceOvertoreadwhenanitemisselected.Currently,acellknowsnothingaboutthePhotothatitisdisplaying,soaddanewpropertytoholdontothisinformation.classPhotoCollectionViewCell:UICollectionViewCell{

@IBOutletvarimageView:UIImageView!

@IBOutletvarspinner:UIActivityIndicatorView!

varphotoDescription:String?

Inthesamefile,overridetheaccessibilityLabeltoreturnthisstring.overridevaraccessibilityLabel:String?{

get{

returnphotoDescription

}

set{

//Ignoreattemptstoset

Page 709: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

}

}

OpenPhotoDataSource.swiftandupdatecollectionView(_:cellForItemAt:)tosetthephotoDescriptiononthecell.funccollectionView(_collectionView:UICollectionView,

cellForItemAtindexPath:IndexPath)->UICollectionViewCell{

letidentifier="PhotoCollectionViewCell"

letcell=

collectionView.dequeueReusableCell(withReuseIdentifier:identifier,

for:indexPath)as!PhotoCollectionViewCell

letphoto=photos[indexPath.row]

cell.photoDescription=photo.title

returncell

}

Buildandruntheapplication.Dragyourfingeroverthescreenandyouwillhearthetitlesforeachphoto.Currentlythereisnoindicationtousersthattheycandouble-taptodrilldowntoaspecificphoto.Thisisbecausethecellsdonothaveanyaccessibilitytraitsset.InPhotoCollectionViewCell.swift,overridetheaccessibilityTraitspropertytoletthesystemknowthatacellholdsanimage.overridevaraccessibilityTraits:UIAccessibilityTraits{

get{

returnsuper.accessibilityTraits|UIAccessibilityTraitImage

}

set{

//Ignoreattemptstoset

}

}

YouarecombininganytraitsinheritedfromthesuperclasswiththeUIAccessibilityTraitImage.Thisisdoneusingthe|(or)operatortocombinethetwo.Likemanyotherthingsrelatedtoaccessibility,thisisalegacyofthepast.Incurrent,idiomaticSwift,thiswouldbedoneusinganOptionSetbypassingtheoptionsasanarray.ButUIAccessibilitydoesnotsupportthissyntax,soinsteadyouareusing|togrouptheoptions,whichishowthisisdoneinCandObjective-C.Buildandruntheapplication.Noticethatthenewtraityouaddedisspokenwhenyouselectacell.Theremainingpartsoftheapplicationaremostlyaccessiblebecausetheyusestandardviewsandcontrols.TheonlythingyouneedtoupdateistheimageviewwhendrillingdowntoaspecificPhoto.Youcancustomizemanyviews’accessibilityinformationfromwithinstoryboards,andyouwillbeabletodothatfortheimageview.OpenMain.storyboardandnavigatetothesceneassociatedwiththePhotoInfoViewController.Selecttheimageviewandopenitsidentityinspector.ScrolltothebottomtothesectionlabeledAccessibility.Checktheboxatthetopofthissectionto

Page 710: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

enableaccessibilityforthisimageviewandunchecktheboxnexttoUserInteractionEnabled(Figure24.4).Figure24.4Updatingtheaccessibilityoptions

OpenPhotoInfoViewController.swiftandupdateviewDidLoad()togivetheimageviewamoremeaningfulaccessibilitylabel.overridefuncviewDidLoad(){

super.viewDidLoad()

imageView.accessibilityLabel=photo.title

Buildandruntheapplicationandnavigatetoaspecificphoto.Youwillnoticethatwiththissmalladdition,thisentirescreenisaccessible.Finally,let’sturnourattentiontotheTagsViewController.Whilestillrunningtheapplication,drilldowntotheTagsViewController.Addatagtothetableviewifoneisnotalreadypresent.SelectarowinthetableandnoticethatVoiceOverreadsthenameofthistag;however,thereisnoindicationtousersthattheycantogglethe

Page 711: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

checkmarkforeachrow,noristhepresenceorabsenceofthatcheckmarkcommunicated.OpenTagDataSource.swiftandupdatethecell’saccessibilityhintintableView(_:cellForRowAt:).functableView(_tableView:UITableView,

cellForRowAtindexPath:IndexPath)->UITableViewCell{

letcell=tableView.dequeueReusableCell(withIdentifier:"UITableViewCell",

for:indexPath)

lettag=tags[indexPath.row]

cell.textLabel?.text=tag.name

cell.accessibilityHint="Doubletaptotoggleselected"

returncell

}

Buildandruntheapplicationandmarvelatitsaccessibility.

Page 712: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 713: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

25Afterword

Welcometotheendofthebook!Youshouldbeveryproudofallyourworkandallthatyouhavelearned.Nowthereisgoodnewsandbadnews:

Thegoodnews:ThestuffthatleavesprogrammersbefuddledwhentheycometotheiOSplatformisbehindyounow.YouareaniOSdeveloper.Thebadnews:YouareprobablynotaverygoodiOSdeveloper.

Page 714: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

WhattoDoNext

Itisnowtimetomakesomemistakes,readsomereallytediousdocumentation,andbehumbledbytheheartlessexpertswhowillridiculeyourquestions.Hereiswhatwerecommend:Writeappsnow.Ifyoudonotimmediatelyusewhatyouhavelearned,itwillfade.Exerciseandextendyourknowledge.Now.Godeep.Thisbookhasconsistentlyfavoredbreadthoverdepth;anychaptercouldhavebeenexpandedintoanentirebook.Findatopicthatyoufindinterestingandreallywallowinit–dosomeexperiments,readApple’sdocsonthetopic,andreadpostingsonblogsandStackOverflow.Connect.ThereareiOSDeveloperMeetupsinmostcities,andthetalksaresurprisinglygood.ThereareCocoaHeadschaptersaroundtheworld.Therearediscussiongroupsonline.Ifyouaredoingaproject,findpeopletohelpyou:designers,testers(AKAguineapigs),andotherdevelopers.Makemistakesandfixthem.Youwilllearnalotonthedayswhenyousay,“Thisapplicationhasbecomeaballofcrap!I’mgoingtothrowitawayandwriteitagainwithanarchitecturethatmakessense.”Politeprogrammerscallthisrefactoring.Giveback.Sharetheknowledge.Answeradumbquestionwithgrace.Giveawaysomecode.

Page 715: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 716: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

ShamelessPlugs

YoucanfindusonTwitter,wherewekeepyouinformedaboutprogrammingandentertainedaboutlife:@cbkeurand@aaronhillegass.KeepaneyeoutforotherguidesfromBigNerdRanch.Wealsoofferweek-longcoursesfordevelopers.Andifyoujustneedsomecodewritten,wedocontractprogramming.Formoreinformation,visitourwebsiteatwww.bignerdranch.com.You,dearreader,makeourlivesofwriting,coding,andteachingpossible.Sothankyouforbuyingourbook.

Page 717: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 718: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

AtBigNerdRanch,wecreateelegant,authenticallyusefulsolutionsthroughbest-in-classdevelopmentandtraining.CLIENTSOLUTIONSBigNerdRanchdesigns,developsanddeploysapplicationsforclientsofallsizes—fromsmallstart-upstolargecorporations.Ourin-houseengineeringanddesignteamspossessexpertiseiniOS,Androidandfull-stackwebapplicationdevelopment.

TEAMTRAININGForcompanieswithcapableengineeringteams,BigNerdRanchcanprovideon-sitecorporatetraininginiOS,Android,Front-EndWeb,Back-EndWeb,macOSandDesign.Ofthetop25appsintheU.S.,19arebuiltbycompaniesthatbroughtinBigNerdRanchtotraintheirdevelopers.

CODINGBOOTCAMPSBigNerdRanchoffersintensiveappdevelopmentanddesignretreatsforindividuals.Lodging,foodandcoursematerialsareincluded,andwe’llevenpickyouupattheairport!Thesecoursesarenotforthefaintofheart.YouwilllearnnewskillsiniOS,Android,Front-EndWeb,Back-EndWeb,macOSorDesignindays—notweeks.

www.bignerdranch.com

Page 719: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More
Page 720: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Index

ABCDEFGHIJKLMNOPQRSTUVWX

Symbols

#columnexpression,Cavemandebugging#fileexpression,Cavemandebugging#functionexpression,Cavemandebugging,FortheMoreCurious:ApplicationStateTransitions#lineexpression,Cavemandebugging$0,$1...(shorthandargumentnames),BackgroundTasks.xcassets(AssetCatalog),ApplicationIcons.xcdatamodeld(datamodelfile),Modelingentities//MARK:,//MARK:@discardableResult,UITableView’sDataSource@escapingannotation,ParsingJSONdata@IBAction,Definingactionmethods@IBInspectable,@IBInspectable@IBOutlet,Declaringoutlets,HookingUptheContent@NSManagedkeyword,NSManagedObjectandsubclasses

A

accesscontrol,URLComponentsaccessibilityaccessibilityelements,AccessibilityinPhotoramaaddingaccessibilityhints,AccessibilityinPhotoramaaddingaccessibilitylabels,AccessibilityinPhotoramasettingaccessibilityinformationinstoryboards,AccessibilityinPhotoramasettingaccessibilitytraits,AccessibilityinPhotoramaUIAccessibilityprotocol,VoiceOverVoiceOver,VoiceOver,TestingVoiceOver

AccessibilityInspector,TestingVoiceOveraccessoryview(UITableViewCell),UITableViewCellsactionmethodsabout,Definingactionmethodsimplementing,ImplementingactionmethodsUIControlclassand,FortheMoreCurious:UIControl

activestate,ApplicationStatesandTransitionsaddSubview(_:)method,ViewsandFramesalerts,displaying,DisplayingUserAlerts

Page 721: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

alignmentrectangle,Thealignmentrectangleandlayoutattributesanchors,Anchorsanimate(withDuration:animations:)method,BasicAnimationsanimationsbasic,BasicAnimationsforconstraints,AnimatingConstraintsmarkingcompletionof,AnimationCompletionspring,BronzeChallenge:SpringAnimationstimingfunctions,TimingFunctions

anti-aliasing,FortheMoreCurious:RetinaDisplayappend(_:)method,Instancemethodsapplicationbundleabout,FortheMoreCurious:TheApplicationBundleinternationalizationand,Baseinternationalization,FortheMoreCurious:Bundle’sRoleinInternationalization

applicationsandbox,ApplicationSandbox,FortheMoreCurious:TheApplicationBundleapplicationstates,ApplicationStatesandTransitions,FortheMoreCurious:ApplicationStateTransitionsapplicationDidBecomeActive(_:)method,ApplicationStatesandTransitions,FortheMoreCurious:ApplicationStateTransitionsapplicationDidEnterBackground(_:)method,NSKeyedArchiverandNSKeyedUnarchiver,ApplicationStatesandTransitionsapplications(seealsoapplicationbundle,debugging,projects)building,Runningonthesimulator,Localizationcleaning,Localizationdatastorage,ApplicationSandboxdirectoriesin,ApplicationSandboxiconsfor,ApplicationIconslaunchimagesfor,LaunchScreenmultiplethreadsin,TheMainThreadrunningonsimulator,Runningonthesimulator

applicationWillEnterForeground(_:)method,ApplicationStatesandTransitions,FortheMoreCurious:ApplicationStateTransitionsapplicationWillResignActive(_:)method,ApplicationStatesandTransitions,FortheMoreCurious:ApplicationStateTransitionsarchiveRootObject(_:toFile:)method,NSKeyedArchiverandNSKeyedUnarchiverarchivingabout,ArchivingCoreDatavs,CoreDataimplementing,ArchivingwithNSKeyedArchiver,NSKeyedArchiverandNSKeyedUnarchiverunarchiving,Loadingfiles

arraysabout,Collectiontypescountproperty,Propertiesliteral,Literalsandsubscripting

Page 722: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

subscripting,LiteralsandsubscriptingAssetCatalog(Xcode),ApplicationIconsassistanteditor,HookingUptheContentattributes(CoreData),EntitiesAutoLayout(seealsoconstraints(AutoLayout),views)about,AbriefintroductiontoAutoLayoutalignmentrectangle,Thealignmentrectangleandlayoutattributesautoresizingmasksand,FortheMoreCurious:NSAutoresizingMaskLayoutConstraintconstraints,AbriefintroductiontoAutoLayoutdynamiccellheights,DynamicCellHeightshorizontalambiguity,AddingconstraintsinInterfaceBuilderlayoutattributes,Thealignmentrectangleandlayoutattributesnearestneighborand,Constraintspurposeof,TheAutoLayoutSystem

autoresizingmasks,ProgrammaticConstraints,FortheMoreCurious:NSAutoresizingMaskLayoutConstraintawakeFromNib()method,Respondingtouserchanges

B

backgroundstate,ApplicationStatesandTransitions,FortheMoreCurious:ApplicationStateTransitionsbaseinternationalization,Baseinternationalizationbaselines,ThealignmentrectangleandlayoutattributesbecomeFirstResponder()method,DismissingthekeyboardBooltype,NumberandBooleantypesbreakpointsaddingactionsto,Steppingthroughcodeadvancingthroughcode,Steppingthroughcodedeleting,Steppingthroughcodeexception,Steppingthroughcodesetting,Settingbreakpointssymbolic,Steppingthroughcodeusingtologtotheconsole,Steppingthroughcode

Bundleclass,FortheMoreCurious:Bundle’sRoleinInternationalizationbundles(seealsoapplicationbundle)application,FortheMoreCurious:TheApplicationBundleBundleclass,FortheMoreCurious:Bundle’sRoleinInternationalization

buttonsaddingtonavigationbars,Addingbuttonstothenavigationbarcamera,Addingacamerabutton

C

Page 723: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

callbacks,Delegation(seealsodelegation,target-actionpairs)

camera(seealsoimages)takingpictures,Addingacamerabutton

canBecomeFirstResponderproperty,UIMenuControllercancelsTouchesInViewproperty,UIPanGestureRecognizerandsimultaneousrecognizerscanPerformAction(_:withSender:)method,FortheMoreCurious:UIMenuControllerandUIResponderStandardEditActionscells(seealsoUITableViewCellclass)addingpaddingto,ContentInsetschangingcellclass,CreatingItemCellcustomizinglayout,CustomizingtheLayoutdynamiccellheights,DynamicCellHeightsprototype,ReusingUITableViewCells

CGPointtype,ViewsandFramesCGRecttype,ViewsandFramesCGSizetype,ViewsandFramesclassmethods,TypesinSwiftclassesBundle,FortheMoreCurious:Bundle’sRoleinInternationalizationData,WritingtotheFilesystemwithDataDateFormatter,HookingUptheContentIndexPath,CreatingandretrievingUITableViewCells,DeletingRowsJSONSerialization,JSONSerializationLocale,FormattersNSCoder,ArchivingNSFetchRequest,FetchrequestsandpredicatesNSKeyedArchiver,NSKeyedArchiverandNSKeyedUnarchiverNSKeyedUnarchiver,LoadingfilesNSManagedObject,NSManagedObjectandsubclassesNSUserDefaults,ApplicationSandboxNSUUID,CreatingandUsingKeysNSValueTransformer,TransformableattributesNumberFormatter,HookingUptheContentOperationQueue,TheMainThreadUIActivityIndicatorView,CreatingaCustomUICollectionViewCellUIAlertController,DisplayingUserAlertsUIApplication(seeUIApplicationclass)UIBarButtonItem(seeUIBarButtonItemclass)UICollectionViewCell,CreatingaCustomUICollectionViewCellUICollectionViewFlowLayout,CollectionViewsUICollectionViewLayout,CustomizingtheLayout

Page 724: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

UIColor,ViewsandFramesUIControl,FortheMoreCurious:UIControlUIGestureRecognizer(seeUIGestureRecognizerclass)UIImagePickerController(seeUIImagePickerControllerclass)UIImageView,DisplayingImagesandUIImageViewUILongPressGestureRecognizer,UILongPressGestureRecognizerUIMenuController,UIMenuController,FortheMoreCurious:UIMenuControllerandUIResponderStandardEditActionsUINavigationBar,UINavigationController,NavigatingwithUINavigationControllerUINavigationController(seeUINavigationControllerclass)UINavigationItem,UINavigationBarUIPanGestureRecognizer,UIPanGestureRecognizerandsimultaneousrecognizersUIResponder(seeUIResponderclass)UIStackView,UsingUIStackViewUIStoryboardSegue,SeguesUITabBarController(seeUITabBarControllerclass)UITabBarItem,TabbaritemsUITableView(seeUITableViewclass)UITableViewCell,SubclassingUITableViewCell(seeUITableViewCellclass)UITableViewController(seeUITableViewControllerclass)UITapGestureRecognizer,Dismissingthekeyboard,DetectingTapswithUITapGestureRecognizerUITextField(seeUITextFieldclass)UIToolbar,UINavigationBar(seealsotoolbars)

UITouch,TouchEvents,TurningTouchesintoLines,HandlingmultipletouchesUIView(seeUIViewclass)UIViewController(seeUIViewControllerclass)UIWindow(seeUIWindowclass)URLComponents,URLComponentsURLRequest,SendingtheRequest,FortheMoreCurious:HTTPURLSession,SendingtheRequestURLSessionDataTask,URLSession,TheMainThreadURLSessionTask,SendingtheRequest,FortheMoreCurious:HTTP

closures,Closures,ConstructingafileURLcollectionviewscustomizinglayout,CustomizingtheLayoutdisplaying,DisplayingtheGriddownloadingimagedata,DownloadingtheImageDatalayoutobject,CollectionViewssettingdatasource,CollectionViewDataSource

colorsbackground,ViewsandFramescustomizing,Customizingthelabels

#columnexpression,Cavemandebugging

Page 725: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

commonancestor,Activatingconstraintsconcurrency,TheMainThreadconditionalsif-let,Optionalsswitch,EnumerationsandtheSwitchStatement

connections(inInterfaceBuilder),Makingconnectionsconnectionsinspector(Xcode),Summaryofconnectionsconsoleinterpretingmessages,Interpretingconsolemessagesliteralexpressionsfordebugging,Cavemandebuggingprintingto,Usingadelegateviewinginplayground,Optionals

constants,UsingStandardTypesconstraint(equalTo:)method,Anchorsconstraints(AutoLayout)about,Constraintsactivatingprogrammatically,Activatingconstraintsactivepropertyforprogrammaticconstraints,Activatingconstraintsaddingnewconstraints,AddingconstraintsinInterfaceBuilderalign,AddingconstraintsinInterfaceBuilderanimating,AnimatingConstraintsclearing,AbriefintroductiontoAutoLayout,Addingmoreconstraintscollectionviews,DisplayingtheGridcreatingexplicitconstraints,ExplicitconstraintscreatinginInterfaceBuilder,AddingconstraintsinInterfaceBuilder,Preparingforlocalizationcreatingprogrammatically,ProgrammaticConstraintsimplicit,Implicitconstraintsresolvingunsatisfiable,FortheMoreCurious:NSAutoresizingMaskLayoutConstraintspecifying,AbriefintroductiontoAutoLayout

contentcompression,ContentcompressionresistanceprioritiescontentModeproperty(UIImageView),DisplayingImagesandUIImageViewcontentView(UITableViewCell),UITableViewCellscontrolevents,FortheMoreCurious:UIControlcontrollers,inModel-View-Controller,Model-View-Controllercontrols,Cavemandebuggingcontrols,programmatic,ProgrammaticControlsCoreData@NSManagedkeyword,NSManagedObjectandsubclassesarchivingvs,CoreDataattributes,Entitiescreatingapersistentcontainer,NSPersistentContainerentities(seeentities(CoreData))fetchrequests,Fetchrequestsandpredicatespersistentstoreformats,NSPersistentStoreCoordinator

Page 726: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

relationshipmanagementwith,CoreDataRelationshipsroleof,EntitiessubclassingNSManagedObject,NSManagedObjectandsubclassestransformingvalues,Transformableattributes

CoreGraphics,FortheMoreCurious:RetinaDisplaycountproperty(arrays),PropertiescurrentLocalemethod,Formatters

D

Dataclass,WritingtotheFilesystemwithDatadatasourcemethods,Implementingdatasourcemethods,CollectionViewDataSource,UpdatingtheDataSourcedatasources,DesignPatternsdatastorage(seealsoarchiving,CoreData)forapplicationdata,ApplicationSandboxbinary,FortheMoreCurious:ReadingandWritingtotheFilesystemwithData,WritingtotheFilesystemwithData

dataSource(UITableView),UITableViewController,UITableView’sDataSource,ImplementingdatasourcemethodsDateFormatterclass,HookingUptheContentdebugging(seealsodebuggingtools,exceptions)breakpoints(seebreakpoints)cavemandebugging,Cavemandebuggingliteralexpressionsfor,CavemandebuggingLLDBconsolecommands,TheLLDBconsolestacktraces,Interpretingconsolemessagesusingtheconsole,Interpretingconsolemessages

debuggingtoolsissuenavigator,BuildingtheFinishedApplicationinplaygrounds,Optionals

default:(switchstatement),EnumerationsandtheSwitchStatementdelegationabout,Delegationasadesignpattern,DesignPatternsforUIImagePickerController,Settingtheimagepicker’sdelegateforUITableView,UITableViewControllerprotocolsfor,ConformingtoaprotocolforUICollectionView,DownloadingtheImageData

deleteRows(at:with:)method,DeletingRowsdependencyinjection,Givingthecontrolleraccesstothestoredependencyinversionprinciple,GivingthecontrolleraccesstothestoredequeueReusableCell(withIdentifier:for:)method,ReusingUITableViewCells

Page 727: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

designpatterns,DesignPatternsdevicescheckingforcamera,Settingtheimagepicker’ssourceTypedisplayresolution,ViewsandFrames,FortheMoreCurious:RetinaDisplayenablingVoiceOver,TestingVoiceOverRetinadisplay,FortheMoreCurious:RetinaDisplayscreensizes,SizeClasses

dictionaries(seealsoJSONdata)about,Collectiontypesaccessing,Subscriptingdictionariesliteral,Literalsandsubscriptingsubscripting,Subscriptingdictionariesusing,CreatingandUsingKeys

directoriesapplication,ApplicationSandboxDocuments,ApplicationSandboxLibrary/Caches,ApplicationSandboxLibrary/Preferences,ApplicationSandboxlproj,Baseinternationalization,FortheMoreCurious:Bundle’sRoleinInternationalizationtmp,ApplicationSandbox

@discardableResult,UITableView’sDataSourcedisplayresolution,ViewsandFramesdo-catchstatements,ErrorHandlingdocumentoutline(InterfaceBuilder),InterfaceBuilderdocumentationopening,ControllingAnimationsforSwift,ExploringApple’sSwiftDocumentation

Documentsdirectory,ApplicationSandboxDoubletype,NumberandBooleantypesdrawing(seeviews)drill-downinterface,UINavigationControllerDynamicType,DynamicType

E

editButtonItem,Addingbuttonstothenavigationbareditingproperty(UITableView,UITableViewController),EditingModeemptyinitializers,Structsencode(with:)method,Archiving,NSKeyedArchiverandNSKeyedUnarchiverendEditing(_:)method,Dismissingbytappingelsewhereentities(CoreData)about,Entitiesmodeling,Modelingentities

Page 728: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

relationshipsbetween,Relationshipssavingchangesto,Savingchanges

enumerated()function,LoopsandStringInterpolationenums(enumerations)about,EnumerationsandtheSwitchStatementassociatedvaluesand,Enumerationsandassociatedvaluesrawvaluesand,Enumerationsandrawvaluesswitchstatementsand,EnumerationsandtheSwitchStatement

errorhandling,ErrorHandlingErrorprotocol,ParsingJSONdataerrorsinplaygrounds,UsingStandardTypestraps,Literalsandsubscripting

@escapingannotation,ParsingJSONdataeventscontrol,ProgrammaticControls,FortheMoreCurious:UIControleventhandling,Eventhandlingbasicstouch,Eventhandlingbasics,TouchEvents(seealsotouchevents)

exceptionbreakpoints,Steppingthroughcodeexceptionserrorhandlingvs,FortheMoreCurious:ReadingandWritingtotheFilesysteminternalinconsistency,AddingRowsSwiftvsotherlanguages,FortheMoreCurious:ReadingandWritingtotheFilesystem

expressions,stringinterpolationand,LoopsandStringInterpolationextensions,Extensions

F

fallthrough(switchstatement),EnumerationsandtheSwitchStatementfetchrequests,Fetchrequestsandpredicates#fileexpression,Cavemandebuggingfileinspector,LocalizationfileURLs,constructing,ConstructingafileURLfilesystem,writingto,WritingtotheFilesystemwithData,FortheMoreCurious:ReadingandWritingtotheFilesystemfirstrespondersabout,Eventhandlingbasicsbecoming,DismissingthekeyboardcanBecomeFirstResponderproperty,UIMenuControllernil-targetedactionsand,FortheMoreCurious:UIControlresigning,Dismissingthekeyboard,DismissingbypressingtheReturnkey,Dismissingbytappingelsewhereresponderchainand,FortheMoreCurious:TheResponderChainUIMenuControllerand,UIMenuController

Page 729: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Floattype,NumberandBooleantypesFloat80type,NumberandBooleantypesfor-inloops,LoopsandStringInterpolationforcedunwrapping(ofoptionals),Optionalsframeproperty(UIView),ViewsandFramesframeworksabout,ViewsandFramesCoreData(seeCoreData)linkingmanually,SettingtheInitialViewControllerUIKit,ViewsandFrames

#functionexpression,Cavemandebugging,FortheMoreCurious:ApplicationStateTransitionsfunctionscallback,Delegationenumerated(),LoopsandStringInterpolationNSLocalizedString(_:comment:),NSLocalizedStringandstringstablesswap(_:_:),AnimationCompletionUIImageJPEGRepresentation,WritingtotheFilesystemwithData

G

genstrings,NSLocalizedStringandstringstablesgesturerecognizers(seeUIGestureRecognizerclass)gestures(seealsoUIGestureRecognizerclass)discretevscontinuous,UILongPressGestureRecognizerlongpress,UILongPressGestureRecognizerpan,UIPanGestureRecognizerandsimultaneousrecognizerstap,DetectingTapswithUITapGestureRecognizer

globallyuniqueidentifiers(GUIDs),CreatingandUsingKeys

H

headerview(UITableView),EditingModeHTTPmethods,FortheMoreCurious:HTTPrequestspecifications,FortheMoreCurious:HTTP

I

@IBAction,Definingactionmethods@IBInspectable,@IBInspectable@IBOutlet,Declaringoutlets,HookingUptheContenticons(seealsoimages)

Page 730: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

application,ApplicationIconsinAssetCatalog,ApplicationIcons

if-letstatements,Optionalsimagepicker(seeUIImagePickerControllerclass)imagePickerController(_:didFinishPickingMediaWithInfo:)method,Settingtheimagepicker’sdelegate,SavingtheimageimagePickerControllerDidCancel(_:)method,Settingtheimagepicker’sdelegateimages(seealsocamera,icons)accessingfromthecache,CreatingandUsingKeyscaching,WritingtotheFilesystemwithDatadisplayinginUIImageView,DisplayingImagesandUIImageViewdownloadingimagedata,DownloadingandDisplayingtheImageData,DownloadingtheImageDatafetching,GivingViewControllersAccesstotheImageStoremodelobjectstorepresent,ModelingthePhotoforRetinadisplay,FortheMoreCurious:RetinaDisplaysaving,Savingtheimagestoring,CreatingImageStore

implementationfiles,navigating,FortheMoreCurious:NavigatingImplementationFilesimplicitconstraints,Implicitconstraintsinactivestate,ApplicationStatesandTransitionsIndexPathclass,CreatingandretrievingUITableViewCells,DeletingRowsinequalityconstraints,Preparingforlocalizationinit(coder:)method,InteractingwithViewControllersandTheirViews,Archivinginit(contentsOf:encoding:)method,FortheMoreCurious:ReadingandWritingtotheFilesysteminit(contentsOfFile:)method,WritingtotheFilesystemwithDatainit(frame:)initializer,ViewsandFramesinit(nibName:bundle:)method,InteractingwithViewControllersandTheirViewsinitialviewcontroller,SettingtheInitialViewControllerinitializersabout,Initializersforclassesvsstructs,Custominitializersconvenience,Custominitializerscustom,Custominitializersdesignated,Custominitializersempty,Structsfree,Custominitializersmember-wise,Structsreturningemptyliterals,Initializers

instancevariables(seeoutlets,properties)instances,InitializersInttype,NumberandBooleantypesInterfaceBuilder(seealsoXcode)

Page 731: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

addingconstraints,AddingconstraintsinInterfaceBuilderAutoLayout(seeAutoLayout)canvas,InterfaceBuilderconnectingobjects,Makingconnectionsconnectingwithsourcefiles,ExposingthePropertiesofItemCelldocumentoutline,InterfaceBuildermodifyingviewattributes,@IBInspectablepropertiesand,ExposingthePropertiesofItemCellscene,InterfaceBuildersettingoutletsin,Settingoutlets,HookingUptheContentsettingtarget-actionin,Settingtargetsandactionssizeinspector,ViewsandFrames

interfacefilesbadconnectionsin,HookingUptheContentbaseinternationalizationand,Baseinternationalization

internalinconsistencyexception,AddingRowsinternationalization,Localization,FortheMoreCurious:Bundle’sRoleinInternationalization(seealsolocalization)

intrinsicvsexplicitcontentsize,Intrinsiccontentsizeinverserelationships,RelationshipsiOSsimulatorrunningapplicationson,Runningonthesimulatorsandboxlocation,NSKeyedArchiverandNSKeyedUnarchiversavingimagesto,Permissionsviewingapplicationbundlein,FortheMoreCurious:TheApplicationBundle

iPad(seealsodevices)applicationiconsfor,ApplicationIcons

isEmptyproperty(strings),PropertiesisSourceTypeAvailable(_:)method,Settingtheimagepicker’ssourceTypeissuenavigator(Xcode),BuildingtheFinishedApplication

J

JSONdata,JSONDataJSONSerializationclass,JSONSerialization

K

key-valuepairsindictionaries,CollectiontypesinJSONdata,JSONDatainwebservices,FormattingURLsandrequests

keyboards

Page 732: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

attributes,Keyboardattributesdismissing,Dismissingthekeyboard,DismissingtheKeyboard

keys,creating/using,CreatingandUsingKeys

L

labelsadding,ViewsandFramesaddingtotabbar,Tabbaritemscustomizing,Customizingthelabelsupdatingpreferredtextsize,Respondingtouserchanges

languagesettings,Localization(seealsolocalization)

launchimages,LaunchScreenlayoutattributes,Thealignmentrectangleandlayoutattributeslayoutguides,Layoutguides,SilverChallenge:LayoutGuideslayoutIfNeeded()method,AnimatingConstraintslazyloading,TheViewofaViewController,LoadedandAppearingViewsletkeyword,UsingStandardTypeslibraries(seeframeworks)Library/Cachesdirectory,ApplicationSandboxLibrary/Preferencesdirectory,ApplicationSandbox#lineexpression,Cavemandebuggingliteralvalues,LiteralsandsubscriptingloadView()method,TheViewofaViewController,InteractingwithViewControllersandTheirViews,CreatingaViewProgrammaticallyLocaleclass,Formatterslocalizationbaseinternationalizationand,BaseinternationalizationBundleclass,FortheMoreCurious:Bundle’sRoleinInternationalizationinternationalization,Localization,FortheMoreCurious:Bundle’sRoleinInternationalizationlprojdirectories,Baseinternationalization,FortheMoreCurious:Bundle’sRoleinInternationalizationstringstables,NSLocalizedStringandstringstablesusersettingsfor,LocalizationXLIFFdatatype,FortheMoreCurious:ImportingandExportingasXLIFF

location(in:)method,MultipleGestureRecognizersloopsexamininginValueHistory,LoopsandStringInterpolationfor-in,LoopsandStringInterpolationinSwift,LoopsandStringInterpolation

low-memorywarnings,Savingtheimagelprojdirectories,Baseinternationalization,FortheMoreCurious:Bundle’sRoleinInternationalization

M

Page 733: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

mainbundle,Baseinternationalization,FortheMoreCurious:Bundle’sRoleinInternationalization(seealsoapplicationbundle)

maininterface,SettingtheInitialViewControllermainthread,TheMainThreadmargins,Margins,Explicitconstraints//MARK:,//MARK:member-wiseinitializers,Structsmemorymanagementmemorywarnings,SavingtheimageUITableViewCellclass,ReusingUITableViewCells

menus(UIMenuController),UIMenuController,FortheMoreCurious:UIMenuControllerandUIResponderStandardEditActionsmessages(seealsomethods)action,UIGestureRecognizerSubclasses,UIMenuControllerlog,Handlingmultipletouches

methodsabout,Instancemethodsaction,Definingactionmethods,FortheMoreCurious:UIControladdSubview(_:),ViewsandFramesanimate(withDuration:animations:),BasicAnimationsappend(_:),InstancemethodsapplicationDidBecomeActive(_:),ApplicationStatesandTransitions,FortheMoreCurious:ApplicationStateTransitionsapplicationDidEnterBackground(_:),NSKeyedArchiverandNSKeyedUnarchiver,ApplicationStatesandTransitionsapplicationWillEnterForeground(_:),ApplicationStatesandTransitions,FortheMoreCurious:ApplicationStateTransitionsapplicationWillResignActive(_:),ApplicationStatesandTransitions,FortheMoreCurious:ApplicationStateTransitionsarchiveRootObject(_:toFile:),NSKeyedArchiverandNSKeyedUnarchiverawakeFromNib(),RespondingtouserchangesbecomeFirstResponder(),DismissingthekeyboardcanPerformAction(_:withSender:),FortheMoreCurious:UIMenuControllerandUIResponderStandardEditActionsclass,TypesinSwiftconstraint(equalTo:),AnchorscurrentLocale,Formattersdatasource,Implementingdatasourcemethods,CollectionViewDataSource,UpdatingtheDataSourcedeleteRows(at:with:),DeletingRowsdequeueReusableCell(withIdentifier:for:),ReusingUITableViewCellsencode(with:),Archiving,NSKeyedArchiverandNSKeyedUnarchiverendEditing(_:),DismissingbytappingelsewhereHTTP,FortheMoreCurious:HTTPimagePickerController(_:didFinishPickingMediaWithInfo:),Settingtheimagepicker’sdelegate,Savingtheimage

Page 734: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

imagePickerControllerDidCancel(_:),Settingtheimagepicker’sdelegateinit(coder:),InteractingwithViewControllersandTheirViews,Archivinginit(contentsOf:encoding:),FortheMoreCurious:ReadingandWritingtotheFilesysteminit(contentsOfFile:),WritingtotheFilesystemwithDatainit(nibName:bundle:),InteractingwithViewControllersandTheirViewsinstance,TypesinSwift,InstancemethodsisSourceTypeAvailable(_:),Settingtheimagepicker’ssourceTypelayoutIfNeeded(),AnimatingConstraintsloadView(),TheViewofaViewController,InteractingwithViewControllersandTheirViews,CreatingaViewProgrammaticallylocation(in:),MultipleGestureRecognizersoverriding,Loadingthefirstquestionprepare(for:sender:),PassingDataAroundprepareForReuse(),CreatingaCustomUICollectionViewCellpresent(_:animated:completion:),DisplayingUserAlertsprotocol,Moreonprotocolsrequire(toFail:),MoreonUIGestureRecognizerresignFirstResponder(),Dismissingthekeyboard,DismissingbypressingtheReturnkeyreverse(),Instancemethodsselectors,InterpretingconsolemessagessendActions(for:),FortheMoreCurious:UIControlsetEditing(_:animated:),EditingModesetNeedsDisplay(),TurningTouchesintoLinesstatic,TypesinSwifttableView(_:cellForRowAt:),Implementingdatasourcemethods,CreatingandretrievingUITableViewCellstableView(_:commit:forRow:),DeletingRowstableView(_:moveRowAtIndexPath:toIndexPath:),MovingRowstableView(_:numberOfRowsInSection:),ImplementingdatasourcemethodstextFieldShouldReturn(_:),DismissingbypressingtheReturnkeytouchesBegan(_:with:),TouchEventstouchesCancelled(_:with:),TouchEventstouchesEnded(_:with:),TouchEventstouchesMoved(_:with:),TouchEventstranslationInView(_:),UIPanGestureRecognizerandsimultaneousrecognizersunarchiveObject(withFile:),Loadingfilesurl(forResource:withExtension:),FortheMoreCurious:Bundle’sRoleinInternationalizationurls(for:in:),ConstructingafileURLviewDidLoad(),ViewsandFrames,AccessingsubviewsviewWillAppear(_:),Accessingsubviews,AppearingandDisappearingViewsviewWillDisappear(_:),AppearingandDisappearingViewswrite(to:atomically:encoding:),FortheMoreCurious:ReadingandWritingtotheFilesystemwrite(to:options:),WritingtotheFilesystemwithData

minimumPressDurationproperty,UILongPressGestureRecognizermodalviewcontrollers,DisplayingUserAlerts,Presentingtheimagepickermodally

Page 735: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Model-View-Controller(MVC),Model-View-Controller,UITableViewController,DesignPatternsmodels,inModel-View-Controller,Model-View-ControllermultipleTouchEnabledproperty(UIView),Handlingmultipletouchesmultithreading,TheMainThreadmultitouch,enabling,HandlingmultipletouchesMVC(Model-View-Controller),Model-View-Controller,UITableViewController,DesignPatterns

N

namingconventionscellreuseidentifiers,ReusingUITableViewCellsdelegateprotocols,Conformingtoaprotocolencodingkeysforarchiving,Archiving

navigationcontrollers(seeUINavigationControllerclass)navigationItem(UIViewController),UINavigationBarnearestneighbor,Constraintsnextproperty,FortheMoreCurious:TheResponderChainnil-targetedactions,FortheMoreCurious:UIControlNSCoderclass,ArchivingNSCodingprotocol,ArchivingNSFetchRequestclass,FetchrequestsandpredicatesNSKeyedArchiverclass,NSKeyedArchiverandNSKeyedUnarchiverNSKeyedUnarchiverclass,LoadingfilesNSLocalizedString(_:comment:)function,NSLocalizedStringandstringstables@NSManagedkeyword,NSManagedObjectandsubclassesNSManagedObjectclass,NSManagedObjectandsubclassesNSUserDefaultsclass,ApplicationSandboxNSUUIDclass,CreatingandUsingKeysNSValueTransformerclass,Transformableattributesnumberformatters,Numberformatters,FormattersNumberFormatterclass,HookingUptheContent

O

objectgraphs,ObjectGraphsobjectlibrary(Xcode),Creatingviewobjectsobjects(seememorymanagement)OperationQueueclass,TheMainThreadoptionalkeyword,Moreonprotocolsoptionalmethods(protocols),Moreonprotocolsoptionalsabout,Optionalsdictionarysubscriptingand,Subscriptingdictionariesforcedunwrapping,Optionals

Page 736: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

if-letstatements,Optionalsoptionalbinding,Optionalsunwrapping,Optionals

outletsabout,Makingconnectionsautogenerating/connecting,HookingUptheContentconnectingconstraintsto,AnimatingConstraintsconnectingwithsourcefiles,ExposingthePropertiesofItemCellsetting,MakingconnectionssettinginInterfaceBuilder,HookingUptheContent

overridekeyword,Loadingthefirstquestion

P

padding,ContentInsetsparallelcomputing,TheMainThreadphotos(seecamera,images)pixels(vspoints),ViewsandFramesplaygrounds(Xcode)about,UsingStandardTypeserrorsin,UsingStandardTypesValueHistory,LoopsandStringInterpolationviewingconsolein,Optionals

pointers,inInterfaceBuilder(seeoutlets)points(vspixels),ViewsandFramespredicates,Fetchrequestsandpredicatespreferences,ApplicationSandbox(seealsoDynamicType,localization)

prepare(for:sender:)method,PassingDataAroundprepareForReuse()method,CreatingaCustomUICollectionViewCellpresent(_:animated:completion:)method,DisplayingUserAlertspreviewassistant,Preparingforlocalizationprogrammaticviewsactivatingconstraints,Activatingconstraintsactivepropertyonconstraints,Activatingconstraintsanchors,Anchorsconstraint(equalTo:)method,Anchorscontrols,ProgrammaticControlscreatingconstraints,ProgrammaticConstraintscreatingexplicitconstraints,Explicitconstraintscreatingmargins,Marginslayoutguides,LayoutguidesloadViewmethod,CreatingaViewProgrammatically

projectnavigator(Xcode),CreatinganXcodeProject

Page 737: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

projectscleaningandbuilding,Localizationcreating,CreatinganXcodeProjecttargetsettingsin,FortheMoreCurious:TheApplicationBundle

propertiesabout,PropertiescreatinginInterfaceBuilder,ExposingthePropertiesofItemCell

propertylistserializabletypes,FortheMoreCurious:ReadingandWritingtotheFilesystempropertyobservers,ImplementingtheTemperatureConversionprotocolkeyword,Conformingtoaprotocolprotocolsconformingto,Conformingtoaprotocoldeclaring,Conformingtoaprotocoldelegate,ConformingtoaprotocolError,ParsingJSONdataNSCoding,Archivingoptionalmethodsin,Moreonprotocolsrequiredmethodsin,Moreonprotocolsstructureof,ConformingtoaprotocolUIAccessibility,VoiceOverUIApplicationDelegate,ApplicationStatesandTransitionsUICollectionViewDataSource,CollectionViewDataSourceUICollectionViewDelegate,DownloadingtheImageDataUIGestureRecognizerDelegate,UIPanGestureRecognizerandsimultaneousrecognizersUIImagePickerControllerDelegate,Settingtheimagepicker’sdelegate,SavingtheimageUINavigationControllerDelegate,SavingtheimageUIResponderStandardEditActions,FortheMoreCurious:UIMenuControllerandUIResponderStandardEditActionsUITableViewDataSource,UITableViewController,Implementingdatasourcemethods,CreatingandretrievingUITableViewCells,DeletingRows,MovingRowsUITableViewDelegate,UITableViewControllerUITextFieldDelegate,Conformingtoaprotocol

pseudolanguage,Preparingforlocalization

Q

Quartz,FortheMoreCurious:RetinaDisplay(seeCoreGraphics)queryitems,FormattingURLsandrequestsQuickHelp(Xcode),Inferringtypes

R

Rangetype,LoopsandStringInterpolationrawValue(enums),Enumerationsandrawvalues

Page 738: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

referencetypes,vsvaluetypes,Valuetypesvsreferencetypesregionsettings,Localizationreorderingcontrols,MovingRowsrequire(toFail:)method,MoreonUIGestureRecognizerrequiredmethods(protocols),MoreonprotocolsresignFirstResponder()method,Dismissingthekeyboard,DismissingbypressingtheReturnkeyresourcesabout,ApplicationIcons,FortheMoreCurious:TheApplicationBundleAssetCatalog,ApplicationIcons

responderchain,FortheMoreCurious:TheResponderChainresponders(seefirstresponders,UIResponderclass)Retinadisplay,FortheMoreCurious:RetinaDisplayreuseIdentifier(UITableViewCell),ReusingUITableViewCellsreverse()method,Instancemethodsrootviewcontroller(UINavigationController),UINavigationControllerrows(UITableView)adding,AddingRowsdeleting,DeletingRowsmoving,MovingRows

S

sandbox,application,ApplicationSandbox,FortheMoreCurious:TheApplicationBundlesections(UITableView),Implementingdatasourcemethodssegues,Seguesselectorsabout,Interpretingconsolemessagesunrecognized,Interpretingconsolemessages

sendActions(for:)method,FortheMoreCurious:UIControlsenderargument,CavemandebuggingSettype,CollectiontypessetEditing(_:animated:)method,EditingModesetNeedsDisplay()method,TurningTouchesintoLinessettings(seepreferences)simulatorAccessibilityInspector,TestingVoiceOverrunningapplicationson,Runningonthesimulatorsandboxlocation,NSKeyedArchiverandNSKeyedUnarchiversavingimagesto,Permissionsviewingapplicationbundlein,FortheMoreCurious:TheApplicationBundle

sizeclasses,SizeClassessortdescriptors(NSFetchRequest),FetchrequestsandpredicatessourceTypeproperty(UIImagePickerController),TakingPicturesandUIImagePickerControllerstacktraces,Interpretingconsolemessages

Page 739: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

stackviewsabout,StackViewsdistributingcontents,Implicitconstraintsnested,Nestedstackviews

states,application,ApplicationStatesandTransitions,FortheMoreCurious:ApplicationStateTransitionsstaticmethods,TypesinSwiftstringsinternationalizing,NSLocalizedStringandstringstablesinterpolation,LoopsandStringInterpolationisEmptyproperty,Propertiesliteral,Literalsandsubscriptingstringstables,NSLocalizedStringandstringstables

structs,vsclasses,Structssubscriptingarrays,Literalsandsubscriptingdictionaries,Subscriptingdictionaries

subviews,TheViewHierarchy,Accessingsubviewssuperviewproperty,ViewsandFramessuspendedstate,ApplicationStatesandTransitionsswap(_:_:)function,AnimationCompletionSwiftabout,TheSwiftLanguagedocumentationfor,ExploringApple’sSwiftDocumentationenumerations,EnumerationsandtheSwitchStatementextensionsin,Extensionsloops,LoopsandStringInterpolationoptionaltypesin,Optionals,ErrorHandlingreferencetypesvsvaluetypes,Valuetypesvsreferencetypesstringinterpolation,LoopsandStringInterpolationswitchstatements,EnumerationsandtheSwitchStatementtypes,TypesinSwift,UsingStandardTypes

switchstatements,EnumerationsandtheSwitchStatementsymbolicbreakpoints,Steppingthroughcode

T

tabbarcontrollers(seeUITabBarControllerclass)tabbaritems,Tabbaritemstableviewcells(seeUITableViewCellclass)tableviewcontrollers(seeUITableViewControllerclass)tableviews(seeUITableViewclass)tables(database),EntitiestableView(_:cellForRowAt:)method,Implementingdatasourcemethods,CreatingandretrievingUITableViewCells

Page 740: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

tableView(_:commit:forRow:)method,DeletingRowstableView(_:moveRowAtIndexPath:toIndexPath:)method,MovingRowstableView(_:numberOfRowsInSection:)method,Implementingdatasourcemethodstarget-actionpairsabout,Definingactionmethods,DesignPatternsUIControlclassand,FortheMoreCurious:UIControlUIGestureRecognizerand,UIGestureRecognizerSubclasses

targets,buildsettingsfor,FortheMoreCurious:TheApplicationBundletext(seealsoAutoLayout)changingpreferredsize,DynamicTypecustomizingappearance,Customizingthelabels,TextEditingcustomizingsize,Customizingthelabelsdynamicstylingof,DynamicTypeinput,TextInputandDelegation

textFieldShouldReturn(_:)method,DismissingbypressingtheReturnkeythreads,TheMainThreadtimingfunctions,TimingFunctionstmpdirectory,ApplicationSandboxto-manyrelationships,Relationshipsto-onerelationships,Relationshipstoolbarsadding,Addingacamerabuttonaddingbuttonsto,Addingacamerabutton

topViewControllerproperty(UINavigationController),UINavigationControllertoucheventsabout,Eventhandlingbasics,TouchEventsenablingmultitouch,Handlingmultipletouchesresponderchainand,FortheMoreCurious:TheResponderChaintarget-actionpairsand,FortheMoreCurious:UIControlUIControlclassand,FortheMoreCurious:UIControl

touchesBegan(_:with:)method,TouchEventstouchesCancelled(_:with:)method,TouchEventstouchesEnded(_:with:)method,TouchEventstouchesMoved(_:with:)method,TouchEventstransformableattributes(CoreData),TransformableattributestranslationInView(_:)method,UIPanGestureRecognizerandsimultaneousrecognizerstraps,Literalsandsubscriptingtuples,LoopsandStringInterpolationtypesBool,NumberandBooleantypesCGPoint,ViewsandFramesCGRect,ViewsandFramesCGSize,ViewsandFrames

Page 741: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

Double,NumberandBooleantypesextending,ExtensionsFloat,NumberandBooleantypesFloat80,NumberandBooleantypeshashable,Collectiontypesinitializers,Initializersinstancesof,InitializersInt,NumberandBooleantypespropertylistserializable,FortheMoreCurious:ReadingandWritingtotheFilesystemRange,LoopsandStringInterpolationreferencetypesvsvaluetypes,ValuetypesvsreferencetypesSet,Collectiontypesspecifying,Specifyingtypestypeinference,InferringtypesUIControlEvents,ProgrammaticControlsUITableViewAutomaticDimension,DynamicCellHeightsUITableViewCellStyle,UITableViewCells

U

UIthread,TheMainThreadUIAccessibilityprotocol,VoiceOverUIActivityIndicatorViewclass,CreatingaCustomUICollectionViewCellUIAlertControllerclass,DisplayingUserAlertsUIApplicationclasseventsand,TouchEventsresponderchainand,FortheMoreCurious:TheResponderChain,FortheMoreCurious:UIControl

UIApplicationDelegateprotocol,ApplicationStatesandTransitionsUIBarButtonItemclass,UINavigationBar,AddingacamerabuttonUICollectionViewCellclass,CreatingaCustomUICollectionViewCellUICollectionViewDataSourceprotocol,CollectionViewDataSourceUICollectionViewDelegateprotocol,DownloadingtheImageDataUICollectionViewFlowLayoutclass,CollectionViewsUICollectionViewLayoutclass,CustomizingtheLayoutUIColorclass,ViewsandFramesUIControlclass,FortheMoreCurious:UIControlUIControlEvent.touchUpInside,FortheMoreCurious:UIControlUIControlEvent.touchUpOutside,FortheMoreCurious:UIControlUIControlEventstype,ProgrammaticControlsUIGestureRecognizerclassabout,UIGestureRecognizerandUIMenuControlleractionmessages,UIGestureRecognizerSubclasses,UILongPressGestureRecognizercancelsTouchesInViewproperty,UIPanGestureRecognizerandsimultaneousrecognizerschainingrecognizers,MoreonUIGestureRecognizer

Page 742: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

delayingtouches,MoreonUIGestureRecognizerdetectingtaps,DetectingTapswithUITapGestureRecognizerenablingsimultaneousrecognizers,UIPanGestureRecognizerandsimultaneousrecognizersimplementingmultiple,MultipleGestureRecognizers,UIPanGestureRecognizerandsimultaneousrecognizersinterceptingtouchesfromview,UIGestureRecognizerSubclasses,UIPanGestureRecognizerandsimultaneousrecognizerslocation(in:),MultipleGestureRecognizerslongpress,UILongPressGestureRecognizerpan,UIPanGestureRecognizerandsimultaneousrecognizersstateproperty,UILongPressGestureRecognizer,UIPanGestureRecognizerandsimultaneousrecognizers,MoreonUIGestureRecognizersubclasses,UIGestureRecognizerSubclasses,MoreonUIGestureRecognizersubclassing,MoreonUIGestureRecognizertranslationInView(_:),UIPanGestureRecognizerandsimultaneousrecognizerstypesof,DismissingthekeyboardUIRespondermethodsand,UIPanGestureRecognizerandsimultaneousrecognizers

UIGestureRecognizerDelegateprotocol,UIPanGestureRecognizerandsimultaneousrecognizersUIImageclass(seeimages,UIImageViewclass)UIImageJPEGRepresentationfunction,WritingtotheFilesystemwithDataUIImagePickerControllerclassinstantiating,TakingPicturesandUIImagePickerControllerpresenting,Presentingtheimagepickermodally

UIImagePickerControllerDelegateprotocol,Settingtheimagepicker’sdelegate,SavingtheimageUIImageViewclass,DisplayingImagesandUIImageViewUIKitframework,ViewsandFramesUILongPressGestureRecognizerclass,UILongPressGestureRecognizerUIMenuControllerclass,UIMenuController,FortheMoreCurious:UIMenuControllerandUIResponderStandardEditActionsUINavigationBarclass,UINavigationController,NavigatingwithUINavigationControllerUINavigationControllerclass(seealsoviewcontrollers)about,UINavigationControlleraddingviewcontrollersto,AppearingandDisappearingViewsinstantiating,UINavigationControllermanagingviewcontrollerstack,UINavigationControllerrootviewcontroller,UINavigationControllerinstoryboards,SeguestopViewControllerproperty,UINavigationControllerUINavigationBarclassand,UINavigationBarUITabBarControllervs,UINavigationControllerview,UINavigationControllerviewControllersproperty,UINavigationControllerviewWillAppear(_:)method,AppearingandDisappearingViewsviewWillDisappear(_:)method,AppearingandDisappearingViews

UINavigationControllerDelegateprotocol,Savingtheimage

Page 743: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

UINavigationItemclass,UINavigationBarUIPanGestureRecognizerclass,UIPanGestureRecognizerandsimultaneousrecognizersUIResponderclassmenuactions,FortheMoreCurious:UIMenuControllerandUIResponderStandardEditActionsresponderchainand,FortheMoreCurious:TheResponderChaintoucheventsand,TouchEvents

UIResponderStandardEditActionsprotocol,FortheMoreCurious:UIMenuControllerandUIResponderStandardEditActionsUIStackViewclass,UsingUIStackViewUIStoryboardSegueclass,SeguesUITabBarControllerclassimplementing,UITabBarControllerUINavigationControllervs,UINavigationControllerview,UITabBarController

UITabBarItemclass,TabbaritemsUITableViewclass(seealsoUITableViewCellclass,UITableViewControllerclass)about,UITableViewandUITableViewControlleraddingrows,AddingRowscontentInsetproperty,ContentInsetsdataSourceproperty,UITableViewControllerdelegation,UITableViewControllerdeletingrows,DeletingRowseditingmode,EditingMode,SubclassingUITableViewCell,Addingbuttonstothenavigationbareditingproperty,EditingModefooterview,EditingModeheaderview,EditingModemovingrows,MovingRowspopulating,UITableView’sDataSourcesections,Implementingdatasourcemethodsview,SubclassingUITableViewController

UITableViewAutomaticDimensiontype,DynamicCellHeightsUITableViewCellclass(seealsocells)about,UITableViewCells,SubclassingUITableViewCellaccessoryview,UITableViewCellscellstyles,UITableViewCellscontentView,UITableViewCellsdetailTextLabelproperty,UITableViewCellsimageView,UITableViewCellsretrievinginstancesof,CreatingandretrievingUITableViewCellsreuseIdentifierproperty,ReusingUITableViewCellsreusinginstancesof,ReusingUITableViewCellssubclassing,SubclassingUITableViewCell

Page 744: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

textLabelproperty,UITableViewCellsUITableViewCellStyletype,UITableViewCells

UITableViewCellEditingStyle.delete,DeletingRowsUITableViewControllerclass(seealsoUITableViewclass)about,UITableViewControlleraddingrows,AddingRowsdatasourcemethods,ImplementingdatasourcemethodsdataSourceproperty,UITableView’sDataSourcedeletingrows,DeletingRowseditingproperty,EditingModemovingrows,MovingRowsreturningcells,CreatingandretrievingUITableViewCellssubclassing,SubclassingUITableViewControllertableViewproperty,ContentInsets

UITableViewDataSourceprotocol,UITableViewController,Implementingdatasourcemethods,CreatingandretrievingUITableViewCells,DeletingRows,MovingRowsUITableViewDelegateprotocol,UITableViewControllerUITapGestureRecognizerclass,Dismissingthekeyboard,DetectingTapswithUITapGestureRecognizerUITextFieldclassconfiguring,TextEditingasfirstresponder,Eventhandlingbasicskeyboardand,DismissingtheKeyboard

UITextFieldDelegateprotocol,ConformingtoaprotocolUIToolbarclass,UINavigationBar(seealsotoolbars)

UITouchclass,TouchEvents,TurningTouchesintoLines,HandlingmultipletouchesUIViewclass(seealsoUIViewControllerclass,views)about,ViewBasicsanimationdocumentation,ControllingAnimationsframeproperty,ViewsandFramessuperview,ViewsandFrames

UIViewControllerclass(seealsoUIViewclass,viewcontrollers)loadViewmethod,CreatingaViewProgrammaticallyloadView()method,TheViewofaViewControllernavigationItemproperty,UINavigationBartabBarItemproperty,Tabbaritemsview,TheViewofaViewController,FortheMoreCurious:TheResponderChainviewDidLoad()method,AccessingsubviewsviewWillAppear(_:)method,Accessingsubviews

UIWindowclassabout,TheViewHierarchy

Page 745: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

responderchainand,FortheMoreCurious:TheResponderChainunarchiveObject(withFile:)method,Loadingfilesuniversallyuniqueidentifiers(UUIDs),CreatingandUsingKeysunrecognizedselectorerror,Interpretingconsolemessagesurl(forResource:withExtension:)method,FortheMoreCurious:Bundle’sRoleinInternationalizationURLComponentsclass,URLComponentsURLRequestclass,SendingtheRequest,FortheMoreCurious:HTTPURLs,FormattingURLsandrequestsurls(for:in:)method,ConstructingafileURLURLSessionclass,SendingtheRequestURLSessionDataTaskclass,URLSession,TheMainThreadURLSessionTaskclass,SendingtheRequest,FortheMoreCurious:HTTPuseralerts,displaying,DisplayingUserAlertsuserinterface(seealsoAutoLayout,views)drill-down,UINavigationControllerkeyboard,DismissingtheKeyboard

usersettings(seepreferences)

V

valuetypes,vsreferencetypes,Valuetypesvsreferencetypesvarkeyword,UsingStandardTypesvariables,UsingStandardTypes(seealsoinstancevariables(seeoutlets,properties),properties)

viewcontrollers(seealsoUIViewControllerclass,views)allowingaccesstoimagestore,GivingViewControllersAccesstotheImageStoreinitial,SettingtheInitialViewControllerinteractingwith,InteractingwithViewControllersandTheirViewslazyloadingofviews,TheViewofaViewController,LoadedandAppearingViewsmodal,DisplayingUserAlerts,Presentingtheimagepickermodallynavigatingbetween,Seguespresenting,UITabBarControllerroot,UINavigationControllerviewhierarchyand,TheViewofaViewController

viewhierarchy,TheViewHierarchyviewproperty(UIViewController),TheViewofaViewControllerviewControllers(UINavigationController),UINavigationControllerviewDidLoad()method,ViewsandFrames,Accessingsubviewsviews(seealsoAutoLayout,touchevents,UIViewclass,viewcontrollers)about,ViewBasicsanimating,ControllingAnimations

Page 746: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

appearing/disappearing,AppearingandDisappearingViewscontentcompressionresistancepriorities,Contentcompressionresistanceprioritiescontenthuggingpriorities,Contenthuggingprioritiescreatingprogrammatically(seeprogrammaticviews)drawingtoscreen,TheViewHierarchyhierarchy,TheViewHierarchylayersand,TheViewHierarchylazyloading,TheViewofaViewController,LoadedandAppearingViewsmisplaced,MisplacedviewsinModel-View-Controller,Model-View-Controllerpresentingmodally,Presentingtheimagepickermodallyremovingfromstoryboard,ProgrammaticViewsrendering,TheViewHierarchyresizing,DisplayingImagesandUIImageViewscroll,DisplayingtheGridsizeandpositionof,ViewsandFramesstackviews(seestackviews)subviews,TheViewHierarchy

viewWillAppear(_:)method,Accessingsubviews,AppearingandDisappearingViewsviewWillDisappear(_:)method,AppearingandDisappearingViewsVoiceOver,VoiceOver,TestingVoiceOver

W

webservicesabout,WebServicesHTTPrequestspecificationsand,FortheMoreCurious:HTTPwithJSONdata,JSONDatarequestingdatafrom,BuildingtheURLURLSessionclassand,SendingtheRequest

write(to:atomically:encoding:)method,FortheMoreCurious:ReadingandWritingtotheFilesystemwrite(to:options:)method,WritingtotheFilesystemwithData

X

.xcassets(AssetCatalog),ApplicationIcons

.xcdatamodeld(datamodelfile),ModelingentitiesXcode(seealsodebuggingtools,InterfaceBuilder,projects,iOSsimulator)AssetCatalog,ApplicationIconsassistanteditor,HookingUptheContentAutoLayout(seeAutoLayout)breakpointnavigator,Settingbreakpointsconnectionsinspector,Summaryofconnections

Page 747: iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch …englishonlineclub.com/pdf/iOS Programming - The Big Nerd... · 2019-09-21 · Passing Data Around Bronze Challenge: More

creatingprojects,CreatinganXcodeProjectdebugarea,Steppingthroughcodedebugbar,Steppingthroughcodedocumentation,ControllingAnimationseditorarea,CreatinganXcodeProject,InterfaceBuilderfileinspector,Localizationissuenavigator,BuildingtheFinishedApplicationnavigatorarea,CreatinganXcodeProjectnavigators,CreatinganXcodeProjectobjectlibrary,Creatingviewobjectsorganizingfileswith//MARK:,//MARK:playgrounds,UsingStandardTypesprojectnavigator,CreatinganXcodeProjectQuickHelp,Inferringtypesschemes,Runningonthesimulatorsourceeditorjumpbar,FortheMoreCurious:NavigatingImplementationFilesutilityarea,Creatingviewobjectsversions,CreatinganXcodeProjectworkspace,CreatinganXcodeProject

XLIFFdatatype,FortheMoreCurious:ImportingandExportingasXLIFFXMLpropertylists,FortheMoreCurious:ReadingandWritingtotheFilesystem