1 00:00:00,580 --> 00:00:04,790 With our current implementation, we display a fact when we start the app and 2 00:00:04,790 --> 00:00:08,630 then another one when we need to tap the showFact button. 3 00:00:08,630 --> 00:00:11,270 Nothing happens when we tap the button again, and 4 00:00:11,270 --> 00:00:13,570 this is because of the way we've implemented to the method. 5 00:00:14,630 --> 00:00:19,870 The code inside the showFact method is run from top to bottom all at once. 6 00:00:19,870 --> 00:00:23,540 So even if we added a second line of code after the first one 7 00:00:23,540 --> 00:00:27,100 to grab the third fact from the array, it won't work, 8 00:00:27,100 --> 00:00:30,230 because every time we tap the button, all the code would be run. 9 00:00:30,230 --> 00:00:33,900 And it happens really quick, so we only see the third fact. 10 00:00:33,900 --> 00:00:35,020 Give it a try to see what I mean. 11 00:00:36,910 --> 00:00:41,040 The goal we want to achieve is getting the app to display a random fact 12 00:00:41,040 --> 00:00:44,100 from our list every time we tap the button. 13 00:00:44,100 --> 00:00:45,820 How do we achieve this? 14 00:00:45,820 --> 00:00:46,770 Okay let's think. 15 00:00:46,770 --> 00:00:49,070 How do we pull a fact out of the array? 16 00:00:49,070 --> 00:00:51,700 Well we supply the index of the array element. 17 00:00:52,770 --> 00:00:56,350 Right now, we're hard coding this index value to 1. 18 00:00:56,350 --> 00:00:58,030 So every time we press the button, 19 00:00:58,030 --> 00:01:01,260 the index value 1 is used to pull a fact out of the array. 20 00:01:02,440 --> 00:01:06,892 What we need is for a different index number, something between zero and nine, 21 00:01:06,892 --> 00:01:07,829 to be passed in. 22 00:01:07,829 --> 00:01:10,080 But we want to do it without hard coding the number. 23 00:01:11,380 --> 00:01:15,971 Essentially, we need to pick a random number between zero and nine, 24 00:01:15,971 --> 00:01:18,819 because we have ten facts in our array, and 25 00:01:18,819 --> 00:01:22,397 use that random number to get a fact from the arrange. 26 00:01:22,397 --> 00:01:26,557 That doesn't seem too hard, but how do we get a random number? 27 00:01:26,557 --> 00:01:30,637 Remember, when you don't know how to proceed first step is check 28 00:01:30,637 --> 00:01:31,980 the documentation. 29 00:01:33,160 --> 00:01:38,510 So, I'm going to go up to Help, Documentation and API Reference, and 30 00:01:38,510 --> 00:01:43,690 we'll start typing random numbers. 31 00:01:43,690 --> 00:01:46,930 And you'll see under the guides, there's a section that says generating 32 00:01:46,930 --> 00:01:50,770 random numbers in iOS, convenient, let's check it out. 33 00:01:50,770 --> 00:01:52,560 So over here at the bottom it says, 34 00:01:52,560 --> 00:01:57,710 in iOS you can use randomization services to generate these numbers. 35 00:01:57,710 --> 00:01:59,660 So for more information read here. 36 00:01:59,660 --> 00:02:00,160 Let's go there. 37 00:02:01,780 --> 00:02:04,400 Okay, this seems overly complicated. 38 00:02:04,400 --> 00:02:08,730 I think this is more about cryptography and 39 00:02:08,730 --> 00:02:12,210 generating secure random numbers in that context. 40 00:02:12,210 --> 00:02:14,640 That's too advanced for users. 41 00:02:14,640 --> 00:02:19,140 Now you could dive around in the documentation more, but if you can't find 42 00:02:19,140 --> 00:02:23,040 information in the docs easily, the next best place to check out is the Internet. 43 00:02:23,040 --> 00:02:28,563 So I'm gonna close this out and head over to trusty old Google. 44 00:02:28,563 --> 00:02:34,480 So let's Google for swift random number generator. 45 00:02:36,870 --> 00:02:38,960 If you think I'm messing around with you by Googling for 46 00:02:38,960 --> 00:02:41,610 answers, that's not the case at all. 47 00:02:41,610 --> 00:02:46,350 This is a very common step in my workflow, and really every developer's workflow. 48 00:02:46,350 --> 00:02:51,280 There are over 20,000 methods and properties across several thousands of 49 00:02:51,280 --> 00:02:55,950 classes in the iOS SDK, and it's just impossible to remember everything. 50 00:02:56,980 --> 00:03:01,950 Part of being a good developer is knowing how to find the right answers efficiently. 51 00:03:01,950 --> 00:03:06,340 If I can't figure something out, I always read the documentation first. 52 00:03:06,340 --> 00:03:10,210 And then Google second before asking anyone for help. 53 00:03:11,240 --> 00:03:14,440 Most of the answers to our questions have already been asked and 54 00:03:14,440 --> 00:03:19,100 answered online, but we also Google because Google is simply a very 55 00:03:19,100 --> 00:03:22,530 efficient way of checking the documentation at itself. 56 00:03:22,530 --> 00:03:26,970 You may not know what specific term you need to look for in the documentation. 57 00:03:26,970 --> 00:03:30,280 But if you type it into Google, it knows what you're looking for 58 00:03:30,280 --> 00:03:32,760 because thousands of people before have done that. 59 00:03:32,760 --> 00:03:36,760 So it should point you to the right place in the documentation as well. 60 00:03:36,760 --> 00:03:40,470 Okay, so let's check out this first result here. 61 00:03:41,620 --> 00:03:45,250 It says, how does one generate a random number in Apple's swift language? 62 00:03:46,350 --> 00:03:48,849 And the first answer here is the chosen answer, 63 00:03:48,849 --> 00:03:51,547 and a while back this was the answer I recommended. 64 00:03:51,547 --> 00:03:57,425 This way uses an Objective-C function called arc for random uniform. 65 00:03:57,425 --> 00:04:01,460 Objective-C being the other language that we do IOS development. 66 00:04:01,460 --> 00:04:04,700 And this works, but it's kind of messy because we have 67 00:04:04,700 --> 00:04:08,180 to do some conversion of our swift code to an Objective-C class and back. 68 00:04:09,630 --> 00:04:11,860 Fortunately, there's a new wing, 69 00:04:11,860 --> 00:04:16,395 Included in the iOS SDK is a framework called GameKit. 70 00:04:17,580 --> 00:04:18,935 As is evident from the name, 71 00:04:18,935 --> 00:04:22,860 GameKit is a collection of classes that help in building iOS games. 72 00:04:24,220 --> 00:04:27,836 There are many instances in a game where you want a random number, so 73 00:04:27,836 --> 00:04:31,440 GameKit comes built in with a way to generate one. 74 00:04:31,440 --> 00:04:33,890 This makes our work a lot easier. 75 00:04:33,890 --> 00:04:37,080 So let's go back to the fact provider struct. 76 00:04:38,780 --> 00:04:40,270 And let's add a new method. 77 00:04:41,300 --> 00:04:43,170 We've learned about instance methods before. 78 00:04:43,170 --> 00:04:46,780 And we're going to implement an instance method here that returns a random fact 79 00:04:46,780 --> 00:04:48,070 for us. 80 00:04:48,070 --> 00:04:51,577 Remember that the syntax for writing a method, 81 00:04:51,577 --> 00:04:57,461 which is a function that is part of an object, is to start with the func keyword. 82 00:04:57,461 --> 00:05:03,110 We'll call our method randomFact. 83 00:05:03,110 --> 00:05:05,360 The method won't take any parameters. 84 00:05:05,360 --> 00:05:07,280 So empty set of parentheses. 85 00:05:08,570 --> 00:05:12,400 And then since we're returning a fact, our return type is a string. 86 00:05:14,660 --> 00:05:18,620 Now the first thing we need to do in here is we need to get a random number. 87 00:05:18,620 --> 00:05:22,720 And since this code that we want to use to get a random number 88 00:05:22,720 --> 00:05:26,770 is part of the GameKit framework, we need to import it. 89 00:05:26,770 --> 00:05:30,750 Now we just talked about this, to import a framework we can actually do 90 00:05:30,750 --> 00:05:33,791 this anywhere in the file but I like to do it at the top. 91 00:05:33,791 --> 00:05:38,089 And we can use the code that's part of this framework in 92 00:05:38,089 --> 00:05:40,910 the swift file by importing it. 93 00:05:40,910 --> 00:05:43,140 So we'll say import GameKit. 94 00:05:44,720 --> 00:05:49,710 Okay, now if we go back in the method body, we can generate a random number. 95 00:05:50,780 --> 00:05:52,610 So we're going to generate a random number and 96 00:05:52,610 --> 00:05:54,980 assign it to a constant named random number. 97 00:05:54,980 --> 00:05:59,540 So first we'll start with add constant let randomNumber =. 98 00:06:00,970 --> 00:06:05,033 And the class that we're getting a random number from is called GKRandomSource. 99 00:06:05,033 --> 00:06:06,855 Let's just type that out. 100 00:06:06,855 --> 00:06:11,132 GKRandomSource. 101 00:06:11,132 --> 00:06:14,570 Typically, we create an instance of a class to work with, that's what we know. 102 00:06:14,570 --> 00:06:16,610 But we're not going to do that here. 103 00:06:16,610 --> 00:06:18,880 We're going to call a method on it directly. 104 00:06:20,200 --> 00:06:22,668 We're gonna say .sharedRandom. 105 00:06:22,668 --> 00:06:27,341 Now this is a class method or a type method, and all you need to know for 106 00:06:27,341 --> 00:06:32,255 now is that this is a method that you call on a class, not an instance, but 107 00:06:32,255 --> 00:06:35,340 it returns an instance of this class. 108 00:06:35,340 --> 00:06:38,870 We'll talk more about type methods in a future course. 109 00:06:38,870 --> 00:06:41,400 Now another thing we haven't really touched upon 110 00:06:41,400 --> 00:06:43,296 is that you can also chain methods. 111 00:06:43,296 --> 00:06:49,310 So now GKRandomSource.sharedRandom returns an instance, and we could assign 112 00:06:49,310 --> 00:06:54,190 this instance to a constant and then call the instance method using that constant. 113 00:06:54,190 --> 00:06:58,620 But sometimes it's just easier to call the method directly because at this point 114 00:06:58,620 --> 00:07:00,990 after here we have an instance. 115 00:07:00,990 --> 00:07:07,865 I can do ., and I can see nextInt (upperBound, and we get rid of this. 116 00:07:07,865 --> 00:07:11,427 Okay, so this method nextInt 117 00:07:11,427 --> 00:07:16,120 (upperBound is the method that we're looking for that returns a random number. 118 00:07:16,120 --> 00:07:20,720 It takes a single parameter, an upperBound that is a limit and 119 00:07:20,720 --> 00:07:24,295 it returns a random number between zero and the upperBound. 120 00:07:25,420 --> 00:07:29,590 Now since array has 10 items we can pass in 10 as an argument. 121 00:07:29,590 --> 00:07:32,830 And now the random number will never exceed 10. 122 00:07:32,830 --> 00:07:37,730 This works, but it's also what we call a magic number. 123 00:07:37,730 --> 00:07:41,900 Any developer who jumps into this project, or even if you come back to this file 124 00:07:41,900 --> 00:07:46,260 after months or years, you have to figure out why 10 is the upperBound. 125 00:07:46,260 --> 00:07:49,600 Which means you to read the rest of the code and get into that mental space. 126 00:07:50,850 --> 00:07:54,130 There's another reason that this isn't the best way to do it. 127 00:07:54,130 --> 00:07:57,800 If I were to add another fact or several to our array, 128 00:07:57,800 --> 00:08:02,390 10 is no longer the right upperBound and we have to remember to update that value. 129 00:08:03,580 --> 00:08:08,533 All of this can be resolved quite simply by dynamically determining the number 130 00:08:08,533 --> 00:08:11,771 of items in the array every time we call the method. 131 00:08:11,771 --> 00:08:13,594 When we learned about arrays, 132 00:08:13,594 --> 00:08:18,090 we learned about a count method that tells us how many items are in the array. 133 00:08:18,090 --> 00:08:23,000 For the upperBound, we can simply specify facts.count. 134 00:08:24,620 --> 00:08:27,510 Now regardless of the number of the facts in the array, 135 00:08:27,510 --> 00:08:31,330 we ensure that the random number generator never returns a number 136 00:08:31,330 --> 00:08:35,400 that is higher than the highest index value, this way our app 137 00:08:35,400 --> 00:08:39,570 won't crash when we try to access a value using an index that is out of bounds. 138 00:08:41,410 --> 00:08:43,489 Now that we have a random number, 139 00:08:43,489 --> 00:08:47,662 we can use it as an index value to return a random fact from the rain. 140 00:08:47,662 --> 00:08:51,449 It will say return fax [randomNumber]. 141 00:08:53,100 --> 00:08:53,840 Pretty cool, right? 142 00:08:54,900 --> 00:08:58,850 Now let's make changes back in our ViewController to accommodate this. 143 00:08:58,850 --> 00:09:03,600 So in the viewDidLoad method, instead of getting a fact 144 00:09:03,600 --> 00:09:08,280 directly using array subscripting, we have an instance so we can say randomFact. 145 00:09:09,430 --> 00:09:12,930 And then let's do the same thing at the bottom in our showFact method. 146 00:09:14,170 --> 00:09:19,420 Now if we run the app, you'll notice that we start with a different fact. 147 00:09:19,420 --> 00:09:24,770 And we can keep clicking the button and we get different facts every single time. 148 00:09:24,770 --> 00:09:25,570 Great job everyone. 149 00:09:25,570 --> 00:09:26,180 We're almost there.