Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials - iOS Programming

64 Articles
article-image-fake-swift-enums-user-friendly-frameworks
Daniel Leping
28 Sep 2016
7 min read
Save for later

Fake Swift Enums and User-Friendly Frameworks

Daniel Leping
28 Sep 2016
7 min read
Swift Enums are a great and useful hybrid of classic enums with tuples. One of the most attractive points of consideration here is their short .something API when you want to pass one as an argument to a function. Still, they are quite limited in certain situations. OK, enough about enums themselves, because this post is about fake enums (don't take my word literally here). Why? Everybody is talking about usability, UX, and how to make the app user-friendly. This all makes sense, because at the end of the day we all are humans and perceive things with feelings. So the app just leaves the impression footprint. There are a lot of users who would prefer a more friendly app to the one providing a richer functionality. All these talks are proven by Apple and their products. But what about a developer, and what tools and bricks are we using? Right now I'm not talking about the IDEs, but rather about the frameworks and the APIs. Being an open source framework developer myself (right now I'm working on Swift Express, a web application framework in Swift, and the foundation around it), I'm concerned about the looks of the APIs we are providing. It matches one-to-one to the looks of the app, so it has the same importance. Call it Framework's UX if you would like. If the developer is pleased with the API the framework provides, he is 90% already your user. This post was particularly inspired by the Event sub-micro-framework, a part of the Reactive Swift foundation I'm creating right now to make Express solid. We took the basic idea from node.js EvenEmitter, which is very easy to use in my opinion. Though, instead of using the String Event ID approach provided by node, we wanted to use the .something approach (read above about what I think of nice APIs) and we are hoping that enums would work great, we encountered limitations with it. The hardest thing was to create a possibility to use different arguments for closures of different event types. It's all very simple with dynamic languages like JavaScript, but well, here we are type-safe. You know... The problem Usually, when creating a new framework, I try to first write an ideal API, or the one I would like to see at the very end. And here is what I had: eventEmitter.on(.stringevent) { string in print("string:", string) } eventEmitter.on(.intevent) { i in print("int:", i) } eventEmitter.on(.complexevent) { (s, i) in print("complex: string:", s, "int:", i) } This seems easy enough for the final user. What I like the most here is that different EventEmitters can have different sets of events with specific data payloads and still provide the .something enum style notation. This is easier to say than to do. With enums, you cannot have an associated type bound to a specific case. It must be bound to the entire enum, or nothing. So there is no possibility to provide a specific data payload for a particular case. But I was very clear that I want everything type-safe, so there can be no dynamic arguments. The research First of all, I began investigating if there is a possibility to use the .something notation without using enums. The first thing I recalled was the OptionSetType that is mainly used to combine the flags for C APIs. And it allows the .somthing notation. You might want to investigate this protocol as it's just cool and useful in many situations where enums are not enough. After a bit of experimenting, I found out that any class or struct having a static member of Self type can mimic an enum. Pretty much like this: struct TestFakeEnum { private init() { } static let one:TestFakeEnum = TestFakeEnum() static let two:TestFakeEnum = TestFakeEnum() static let three:TestFakeEnum = TestFakeEnum() } func funWithEnum(arg:TestFakeEnum) { } func testFakeEnum() { funWithEnum(.one) funWithEnum(.two) funWithEnum(.three) } This code will compile and run correctly. These are the basics of any fake enum. Even though the example above does not provide any particular benefit over built-in enums, it demonstrates the fundamental possibility. Getting generic Let's move on. First of all, to make our events have a specific data payload, we've added an EventProtocol (just keep in mind; it will be important later): //do not pay attention to Hashable, it's used for internal event routing mechanism. Not a subject here public protocol EventProtocol : Hashable { associatedtype Payload } To make our emitter even better we should not limit it to a restricted set of events, but rather allow the user to extend it. To achieve this, I've added a notion of EventGroup. It's not a particular type but rather an informal concept, so every event group should follow. Here is an example of an EventGroup: struct TestEventGroup<E : EventProtocol> { internal let event:E private init(_ event:E) { self.event = event } static var string:TestEventGroup<TestEventString> { return TestEventGroup<TestEventString>(.event) } static var int:TestEventGroup<TestEventInt> { return TestEventGroup<TestEventInt>(.event) } static var complex:TestEventGroup<TestEventComplex> { return TestEventGroup<TestEventComplex>(.event) } } Here is what TestEventString, TestEventInt and TestEventComplex are (real enums are used here only to have conformance with Hashable and to be a case singleton, so don't bother): //Notice, that every event here has its own Payload type enum TestEventString : EventProtocol { typealias Payload = String case event } enum TestEventInt : EventProtocol { typealias Payload = Int case event } enum TestEventComplex : EventProtocol { typealias Payload = (String, Int) case event } So to get a generic with .something notation, you have to create a generic class or struct having static members of the owner type with a particular generic param applied. Now, how can you use it? How can you discover what generic type is associated with a specific option? For that, I used the following generic function: // notice, that Payload is type-safety extracted from the associated event here with E.Payload func on<E : EventProtocol>(groupedEvent: TestEventGroup<E>, handler:E.Payload->Void) -> Listener { //implementation here is not of the subject of the article } Does this thing work? Yes. You can use the API exactly like it was outlined in the very beginning of this post: let eventEmitter = EventEmitterTest() eventEmitter.on(.string) { s in print("string:", s) } eventEmitter.on(.int) { i in print("int:", i) } eventEmitter.on(.complex) { (s, i) in print("complex: string:", s, "int:", i) } All the type inferences work. It's type safe. It's user friendly. And it is all thanks to a possibility to associate the type with the .something enum-like member. Conclusion Pity that this functionality is not available out of the box with built-in enums. For all the experiments to make this happen, I had to spend several hours. Maybe in one of the upcoming versions of Swift (3? 4.0?), Apple will let us get the type of associated values of an enum or something. But… okay. Those are dreams and out of the scope of this post. For now, we have what we have, and I'm really glad that are abele to have an associatedtype with enum-like entity, even if it's not straightforward. The examples were taken from the Event project. The complete code can be found here and it was tested with Swift 2.2 (Xcode 7.3), which is the latest at the time of writing. Thanks for reading. Use user-friendly frameworks only and enjoy your day! About the Author Daniel Leping is the CEO of Crossroad Labs. He has been working with Swift since the early beta releases and continues to do so at the Swift Express project. His main interests are reactive and functional programming with Swift, Swift-based web technologies, and bringing the best of modern techniques to the Swift world. He can be found on GitHub.
Read more
  • 0
  • 0
  • 22708

article-image-concurrency-and-parallelism-swift-2
Packt
22 Feb 2016
35 min read
Save for later

Concurrency and Parallelism with Swift 2

Packt
22 Feb 2016
35 min read
When I first started learning Objective-C, I already had a good understanding of concurrency and multitasking with my background in other languages such as C and Java. This background made it very easy for me to create multithreaded applications using threads in Objective-C. Then, Apple changed everything for me when they released Grand Central Dispatch (GCD) with OS X 10.6 and iOS 4. At first, I went into denial; there was no way GCD could manage my application's threads better than I could. Then I entered the anger phase, GCD was hard to use and understand. Next was the bargaining phase, maybe I can use GCD with my threading code, so I could still control how the threading worked. Then there was the depression phase, maybe GCD does handle the threading better than I can. Finally, I entered the wow phase; this GCD thing is really easy to use and works amazingly well. After using Grand Central Dispatch and Operation Queues with Objective-C, I do not see a reason for using manual threads with Swift. In this artcle, we will learn the following topics: Basics of concurrency and parallelism How to use GCD to create and manage concurrent dispatch queues How to use GCD to create and manage serial dispatch queues How to use various GCD functions to add tasks to the dispatch queues How to use NSOperation and NSOperationQueues to add concurrency to our applications (For more resources related to this topic, see here.) Concurrency and parallelism Concurrency is the concept of multiple tasks starting, running, and completing within the same time period. This does not necessarily mean that the tasks are executing simultaneously. In order for tasks to be run simultaneously, our application needs to be running on a multicore or multiprocessor system. Concurrency allows us to share the processor or cores with multiple tasks; however, a single core can only execute one task at a given time. Parallelism is the concept of two or more tasks running simultaneously. Since each core of our processor can only execute one task at a time, the number of tasks executing simultaneously is limited to the number of cores within our processors. Therefore, if we have, for example, a four-core processor, then we are limited to only four tasks running simultaneously. Today's processors can execute tasks so quickly that it may appear that larger tasks are executing simultaneously. However, within the system, the larger tasks are actually taking turns executing subtasks on the cores. In order to understand the difference between concurrency and parallelism, let's look at how a juggler juggles balls. If you watch a juggler, it seems they are catching and throwing multiple balls at any given time; however, a closer look reveals that they are, in fact, only catching and throwing one ball at a time. The other balls are in the air waiting to be caught and thrown. If we want to be able to catch and throw multiple balls simultaneously, we need to add multiple jugglers. This example is really good because we can think of jugglers as the cores of a processer. A system with a single core processor (one juggler), regardless of how it seems, can only execute one task (catch and throw one ball) at a time. If we want to execute more than one task at a time, we need to use a multicore processor (more than one juggler). Back in the old days when all the processors were single core, the only way to have a system that executed tasks simultaneously was to have multiple processors in the system. This also required specialized software to take advantage of the multiple processors. In today's world, just about every device has a processor that has multiple cores, and both the iOS and OS X operating systems are designed to take advantage of the multiple cores to run tasks simultaneously. Traditionally, the way applications added concurrency was to create multiple threads; however, this model does not scale well to an arbitrary number of cores. The biggest problem with using threads was that our applications ran on a variety of systems (and processors), and in order to optimize our code, we needed to know how many cores/processors could be efficiently used at a given time, which is sometimes not known at the time of development. In order to solve this problem, many operating systems, including iOS and OS X, started relying on asynchronous functions. These functions are often used to initiate tasks that could possibly take a long time to complete, such as making an HTTP request or writing data to disk. An asynchronous function typically starts the long running task and then returns prior to the task completion. Usually, this task runs in the background and uses a callback function (such as closure in Swift) when the task completes. These asynchronous functions work great for the tasks that the OS provides them for, but what if we needed to create our own asynchronous functions and do not want to manage the threads ourselves? For this, Apple provides a couple of technologies. In this artcle, we will be covering two of these technologies. These are GCD and operation queues. GCD is a low-level C-based API that allows specific tasks to be queued up for execution and schedules the execution on any of the available processor cores. Operation queues are similar to GCD; however, they are Cocoa objects and are internally implemented using GCD. Let's begin by looking at GCD. Grand Central Dispatch Grand Central Dispatch provides what is known as dispatch queues to manage submitted tasks. The queues manage these submitted tasks and execute them in a first-in, first- out (FIFO) order. This ensures that the tasks are started in the order they were submitted. A task is simply some work that our application needs to perform. As examples, we can create tasks that perform simple calculations, read/write data to disk, make an HTTP request, or anything else that our application needs to do. We define these tasks by placing the code inside either a function or a closure and adding it to a dispatch queue. GCD provides three types of queues: Serial queues: Tasks in a serial queue (also known as a private queue) are executed one at a time in the order they were submitted. Each task is started only after the preceding task is completed. Serial queues are often used to synchronize access to specific resources because we are guaranteed that no two tasks in a serial queue will ever run simultaneously. Therefore, if the only way to access the specific resource is through the tasks in the serial queue, then no two tasks will attempt to access the resource at the same time or be out of order. Concurrent queues: Tasks in a concurrent queue (also known as a global dispatch queue) execute concurrently; however, the tasks are still started in the order that they were added to the queue. The exact number of tasks that can be executing at any given instance is variable and is dependent on the system's current conditions and resources. The decision on when to start a task is up to GCD and is not something that we can control within our application. Main dispatch queue: The main dispatch queue is a globally available serial queue that executes tasks on the application's main thread. Since tasks put into the main dispatch queue run on the main thread, it is usually called from a background queue when some background processing has finished and the user interface needs to be updated. Dispatch queues offer a number of advantages over traditional threads. The first and foremost advantage is, with dispatch queues, the system handles the creation and management of threads rather than the application itself. The system can scale the number of threads, dynamically based on the overall available resources of the system and the current system conditions. This means that dispatch queues can manage the threads with greater efficiency than we could. Another advantage of dispatch queues is we are able to control the order that our tasks are started. With serial queues, not only do we control the order in which tasks are started, but also ensure that one task does not start before the preceding one is complete. With traditional threads, this can be very cumbersome and brittle to implement, but with dispatch queues, as we will see later in this artcle, it is quite easy. Creating and managing dispatch queues Let's look at how to create and use a dispatch queue. The following three functions are used to create or retrieve queues. These functions are as follows: dispatch_queue_create: This creates a dispatch queue of either the concurrent or serial type dispatch_get_global_queue: This returns a system-defined global concurrent queue with a specified quality of service dispatch_get_main_queue: This returns the serial dispatch queue associated with the application's main thread We will also be looking at several functions that submit tasks to a queue for execution. These functions are as follows: dispatch_async: This submits a task for asynchronous execution and returns immediately. dispatch_sync: This submits a task for synchronous execution and waits until it is complete before it returns. dispatch_after: This submits a task for execution at a specified time. dispatch_once: This submits a task to be executed once and only once while this application is running. It will execute the task again if the application restarts. Before we look at how to use the dispatch queues, we need to create a class that will help us demonstrate how the various types of queues work. This class will contain two basic functions. The first function will simply perform some basic calculations and then return a value. Here is the code for this function, which is named doCalc(): func doCalc() { var x=100 var y = x*x _ = y/x } The other function, which is named performCalculation(), accepts two parameters. One is an integer named iterations, and the other is a string named tag. The performCalculation () function calls the doCalc() function repeatedly until it calls the function the same number of times as defined by the iterations parameter. We also use the CFAbsoluteTimeGetCurrent() function to calculate the elapsed time it took to perform all of the iterations and then print the elapse time with the tag string to the console. This will let us know when the function completes and how long it took to complete it. The code for this function looks similar to this: func performCalculation(iterations: Int, tag: String) { let start = CFAbsoluteTimeGetCurrent() for var i=0; i<iterations; i++ { self.doCalc() } let end = CFAbsoluteTimeGetCurrent() print("time for (tag): (end-start)") } These functions will be used together to keep our queues busy, so we can see how they work. Let's begin by looking at the GCD functions by using the dispatch_queue_create() function to create both concurrent and serial queues. Creating queues with the dispatch_queue_create() function The dispatch_queue_create() function is used to create both concurrent and serial queues. The syntax of the dispatch_queue_create() function looks similar to this: func dispatch_queue_t dispatch_queue_create (label:   UnsafePointer<Int8>, attr: dispatch_queue_attr_t!) - >     dispatch_queue_t! It takes the following parameters: label: This is a string label that is attached to the queue to uniquely identify it in debugging tools, such as Instruments and crash reports. It is recommended that we use a reverse DNS naming convention. This parameter is optional and can be nil. attr: This specifies the type of queue to make. This can be DISPATCH_QUEUE_SERIAL, DISPATCH_QUEUE_CONCURRENT or nil. If this parameter is nil, a serial queue is created. The return value for this function is the newly created dispatch queue. Let's see how to use the dispatch_queue_create() function by creating a concurrent queue and seeing how it works. Some programming languages use the reverse DNS naming convention to name certain components. This convention is based on a registered domain name that is reversed. As an example, if we worked for company that had a domain name mycompany.com with a product called widget, the reverse DNS name will be com.mycompany.widget. Creating concurrent dispatch queues with the dispatch_queue_create() function The following line creates a concurrent dispatch queue with the label of cqueue.hoffman.jon: let queue = dispatch_queue_create("cqueue.hoffman.jon", DIS-PATCH_QUEUE_CONCURRENT) As we saw in the beginning of this section, there are several functions that we can use to submit tasks to a dispatch queue. When we work with queues, we generally want to use the dispatch_async() function to submit tasks because when we submit a task to a queue, we usually do not want to wait for a response. The dispatch_async() function has the following signature: func dispatch_async (queue: dispatch_queue_t!, block: dis- patch_queue_block!) The following example shows how to use the dispatch_async() function with the concurrent queue we just created: let c = { performCalculation(1000, tag: "async0") } dispatch_async(queue, c) In the preceding code, we created a closure, which represents our task, that simply calls the performCalculation() function of the DoCalculation instance requesting that it runs through 1000 iterations of the doCalc() function. Finally, we use the dispatch_async() function to submit the task to the concurrent dispatch queue. This code will execute the task in a concurrent dispatch queue, which is separate from the main thread. While the preceding example works perfectly, we can actually shorten the code a little bit. The next example shows that we do not need to create a separate closure as we did in the preceding example; we can also submit the task to execute like this: dispatch_async (queue) { calculation.performCalculation(10000000, tag: "async1") } This shorthand version is how we usually submit small code blocks to our queues. If we have larger tasks, or tasks that we need to submit multiple times, we will generally want to create a closure and submit the closure to the queue as we showed originally. Let's see how the concurrent queue actually works by adding several items to the queue and looking at the order and time that they return. The following code will add three tasks to the queue. Each task will call the performCalculation() function with various iteration counts. Remember that the performCalculation() function will execute the calculation routine continuously until it is executed the number of times as defined by the iteration count passed in. Therefore, the larger the iteration count we pass into the performCalculation() function, the longer it should take to execute. Let's take a look at the following code: dispatch_async (queue) { calculation.performCalculation(10000000, tag: "async1") } dispatch_async(queue) { calculation.performCalculation(1000, tag: "async2") } dispatch_async(queue) { calculation.performCalculation(100000, tag: "async3") } Notice that each of the functions is called with a different value in the tag parameter. Since the performCalculation() function prints out the tag variable with the elapsed time, we can see the order in which the tasks complete and the time it took to execute. If we execute the preceding code, we should see the following results: time for async2: 0.000200986862182617 time for async3: 0.00800204277038574 time for async1: 0.461670994758606 The elapse time will vary from one run to the next and from system to system. Since the queues function in a FIFO order, the task that had the tag of async1 was executed first. However, as we can see from the results, it was the last task to finish. Since this is a concurrent queue, if it is possible (if the system has available resources), the blocks of code will execute concurrently. This is why the tasks with the tags of async2 and async3 completed prior to the task that had the async1 tag, even though the execution of the async1 task began before the other two. Now, let's see how a serial queue executes tasks. Creating a serial dispatch queue with the dispatch_queue_create() function A serial queue functions is a little different than a concurrent queue. A serial queue will only execute one task at a time and will wait for one task to complete before starting the next task. This queue, like the concurrent dispatch queue, follows a first-in first-out order. The following line of code will create a serial queue with the label of squeue.hoffman.jon: let queue2 = dispatch_queue_create("squeue.hoffman.jon", DIS-PATCH_QUEUE_SERIAL) Notice that we create the serial queue with the DISPATCH_QUEUE_SERIAL attribute. If you recall, when we created the concurrent queue, we created it with the DISPATCH_QUEUE_CONCURRENT attribute. We can also set this attribute to nil, which will create a serial queue by default. However, it is recommended to always set the attribute to either DISPATCH_QUEUE_SERIAL or DISPATCH_QUEUE_CONCURRENT to make it easier to identify which type of queue we are creating. As we saw with the concurrent dispatch queues, we generally want to use the dispatch_async() function to submit tasks because when we submit a task to a queue, we usually do not want to wait for a response. If, however, we did want to wait for a response, we would use the dispatch_synch() function. var calculation = DoCalculations() let c = { calculation.performCalculation(1000, tag: "sync0") } dispatch_async(queue2, c) Just like with the concurrent queues, we do not need to create a closure to submit a task to the queue. We can also submit the task like this: dispatch_async (queue2) { calculation.performCalculation(100000, tag: "sync1") } Let's see how the serial queues works by adding several items to the queue and looking at the order and time that they complete. The following code will add three tasks, which will call the performCalculation() function with various iteration counts, to the queue: dispatch_async (queue2) { calculation.performCalculation(100000, tag: "sync1") } dispatch_async(queue2) { calculation.performCalculation(1000, tag: "sync2") } dispatch_async(queue2) { calculation.performCalculation(100000, tag: "sync3") } Just like with the concurrent queue example, we call the performCalculation() function with various iteration counts and different values in the tag parameter. Since the performCalculation() function prints out the tag string with the elapsed time, we can see the order that the tasks complete in and the time it takes to execute. If we execute this code, we should see the following results: time for sync1: 0.00648999214172363 time for sync2: 0.00009602308273315 time for sync3: 0.00515800714492798 The elapse time will vary from one run to the next and from system to system.  Unlike the concurrent queues, we can see that the tasks completed in the same order that they were submitted, even though the sync2 and sync3 tasks took considerably less time to complete. This demonstrates that a serial queue only executes one task at a time and that the queue waits for each task to complete before starting the next one. Now that we have seen how to use the dispatch_queue_create() function to create both concurrent and serial queues, let's look at how we can get one of the four system- defined, global concurrent queues using the dispatch_get_global_queue() function. Requesting concurrent queues with the dispatch_get_global_queue() function The system provides each application with four concurrent global dispatch queues of different priority levels. The different priority levels are what distinguish these queues. The four priorities are: DISPATCH_QUEUE_PRIORITY_HIGH: The items in this queue run with the highest priority and are scheduled before items in the default and low priority queues DISPATCH_QUEUE_PRIORITY_DEFAULT: The items in this queue run at the default priority and are scheduled before items in the low priority queue but after items in the high priority queue DISPATCH_QUEUE_PRIORITY_LOW: The items in this queue run with a low priority and are schedule only after items in the high and default queues DISPATCH_QUEUE_PRIORITY_BACKGROUND: The items in this queue run with a background priority, which has the lowest priority Since these are global queues, we do not need to actually create them; instead, we ask for a reference to the queue with the priority level needed. To request a global queue, we use the dispatch_get_global_queue() function. This function has the following syntax: func dispatch_get_global_queue(identifier: Int, flags: UInt) -> ? dispatch_queue_t! Here, the following parameters are defined: identifier: This is the priority of the queue we are requesting flags: This is reserved for future expansion and should be set to zero at this time We request a queue using the dispatch_get_global_queue() function, as shown in the following example: let queue = dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) In this example, we are requesting the global queue with the default priority. We can then use this queue exactly as we used the concurrent queues that we created with the dispatch_queue_create() function. The difference between the queues returned with the dispatch_get_global_queue() function and the ones created with the dispatch_create_queue() function is that with the dispatch_create_queue() function, we are actually creating a new queue. The queues that are returned with the dispatch_get_global_queue() function are global queues that are created when our application first starts; therefore, we are requesting a queue rather than creating a new one. When we use the dispatch_get_global_queue() function, we avoid the overhead of creating the queue; therefore, I recommend using the dispatch_get_global_queue() function unless you have a specific reason to create a queue. Requesting the main queue with the dispatch_get_main_queue() function The dispatch_get_main_queue() function returns the main queue for our application. The main queue is automatically created for the main thread when the application starts. This main queue is a serial queue; therefore, items in this queue are executed one at a time, in the order that they were submitted. We will generally want to avoid using this queue unless we have a need to update the user interface from a background thread. The dispatch_get_main_queue() function has the following syntax: func dispatch_get_main_queue() -> dispatch_queue_t! The following code example shows how to request the main queue: let mainQueue = dispatch_get_main_queue(); We will then submit tasks to the main queue exactly as we would any other serial queue. Just remember that anything submitted to this queue will run on the main thread, which is the thread that all the user interface updates run on; therefore, if we submitted a long running task, the user interface will freeze until that task is completed. In the previous sections, we saw how the dispatch_async() functions submit tasks to concurrent and serial queues. Now, let's look at two additional functions that we can use to submit tasks to our queues. The first function we will look at is the dispatch_after() function. Using the dispatch_after() function There will be times that we need to execute tasks after a delay. If we were using a threading model, we would need to create a new thread, perform some sort of delay or sleep function, and execute our task. With GCD, we can use the dispatch_after() function. The dispatch_after() function takes the following syntax: func dispatch_after(when: dispatch_time_t, queue:   dispatch_queue_t, block: dispatch_block_t) Here, the dispatch_after() function takes the following parameters: when: This is the time that we wish the queue to execute our task in queue: This is the queue that we want to execute our task in block: This is the task to execute As with the dispatch_async() and dispatch_synch() functions, we do not need to include our task as a parameter. We can include our task to execute between two curly brackets exactly as we did previously with the dispatch_async() and dispatch_synch() functions. As we can see from the dispatch_after() function, we use the dispatch_time_t type to define the time to execute the task. We use the dispatch_time() function to create the dispatch_time_t type. The dispatch_time() function has the following syntax: func dispatch_time(when: dispatch_time_t, delta:Int64) ->   dispatch_time_t Here, the dispatch_time() function takes the following parameter: when: This value is used as the basis for the time to execute the task. We generally pass the DISPATCH_TIME_NOW value to create the time, based on the current time. delta: This is the number of nanoseconds to add to the when parameter to get our time. We will use the dispatch_time() and dispatch_after() functions like this: var delayInSeconds = 2.0 let eTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delayInSeconds * Double(NSEC_PER_SEC))) dispatch_after(eTime, queue2) { print("Times Up") } The preceding code will execute the task after a two-second delay. In the dispatch_ time() function, we create a dispatch_time_t type that is two seconds in the future. The NSEC_PER_SEC constant is use to calculate the nanoseconds from seconds. After the two-second delay, we print the message, Times Up, to the console. There is one thing to watch out for with the dispatch_after() function. Let's take a look at the following code: let queue2 = dispatch_queue_create("squeue.hoffman.jon", DIS-PATCH_QUEUE_SERIAL) var delayInSeconds = 2.0 let pTime = dispatch_time (DISPATCH_TIME_NOW,Int64(delayInSeconds * Double(NSEC_PER_SEC))) dispatch_after(pTime, queue2) { print("Times Up") } dispatch_sync(queue2) { calculation.performCalculation(100000, tag: "sync1") } In this code, we begin by creating a serial queue and then adding two tasks to the queue. The first task uses the dispatch_after() function, and the second task uses the dispatch_sync() function. Our initial thought would be that when we executed this code within the serial queue, the first task would execute after a two-second delay and then the second task would execute; however, this would not be correct. The first task is submitted to the queue and executed immediately. It also returns immediately, which lets the queue execute the next task while it waits for the correct time to execute the first task. Therefore, even though we are running the tasks in a serial queue, the second task completes before the first task. The following is an example of the output if we run the preceding code: time for sync1: 0.00407701730728149 Times Up The final GCD function that we are going to look at is dispatch_once(). Using the dispatch_once() function The dispatch_once() function will execute a task once, and only once, for the lifetime of the application. What this means is that the task will be executed and marked as executed, then that task will not be executed again unless the application restarts. While the dispatch_once() function can be and has been used to implement the singleton pattern, there are other easier ways to do this. The dispatch_once() function is great for executing initialization tasks that need to run when our application initially starts. These initialization tasks can consist of initializing our data store or variables and objects. The following code shows the syntax for the dispatch_once() function: func dispatch_once (predicate: UnsafeMutablePoin- ter<dispatch_once_t>,block: dispatch_block_t!) Let's look at how to use the dispatch_once() function: var token: dispatch_once_t = 0 func example() { dispatch_once(&token) { print("Printed only on the first call") } print("Printed for each call") } In this example, the line that prints the message, Printed only on the first call, will be executed only once, no matter how many times the function is called. However, the line that prints the Printed for each call message will be executed each time the function is called. Let's see this in action by calling this function four times, like this: for i in 0..<4 { example() } If we execute this example, we should see the following output: Printed only on the first call Printed for each call Printed for each call Printed for each call Printed for each call Notice, in this example, that we only see the Printed only on the first call message once whereas we see the Printed for each call message all the four times that we call the function. Now that we have looked at GCD, let's take a look at operation queues. Using NSOperation and NSOperationQueue types The NSOperation and NSOperationQueues types, working together, provide us with an alternative to GCD for adding concurrency to our applications. Operation queues are Cocoa objects that function like dispatch queues and internally, operation queues are implemented using GCD. We define the tasks (NSOperations) that we wish to execute and then add the task to the operation queue (NSOperationQueue). The operation queue will then handle the scheduling and execution of tasks. Operation queues are instances of the NSOperationQueue class and operations are instances of the NSOperation class. The operation represents a single unit of work or task. The NSOperation type is an abstract class that provides a thread-safe structure for modeling the state, priority, and dependencies. This class must be subclassed in order to perform any useful work. Apple does provide two concrete implementations of the NSOperation type that we can use as-is for situations where it does not make sense to build a custom subclass. These subclasses are NSBlockOperation and NSInvocationOperation. More than one operation queue can exist at the same time, and actually, there is always at least one operation queue running. This operation queue is known as the main queue. The main queue is automatically created for the main thread when the application starts and is where all the UI operations are performed. There are several ways that we can use the NSOperation and NSOperationQueues classes to add concurrency to our application. In this artcle, we will look at three different ways. The first one we will look at is using the NSBlockOperation implementation of the NSOperation abstract class. Using the NSBlockOperation implementation of NSOperation In this section, we will be using the same DoCalculation class that we used in the Grand Central Dispatch section to keep our queues busy with work so that we can see how the NSOpererationQueues class work. The NSBlockOperation class is a concrete implementation of the NSOperation type that can manage the execution of one or more blocks. This class can be used to execute several tasks at once without the need to create separate operations for each task. Let's see how to use the NSBlockOperation class to add concurrency to our application. The following code shows how to add three tasks to an operation queue using a single NSBlockOperation instance: let calculation = DoCalculations() let operationQueue = NSOperationQueue() let blockOperation1: NSBlockOperation = NSBlockOpera-tion.init(block: { calculation.performCalculation(10000000, tag: "Operation 1") }) blockOperation1.addExecutionBlock( { calculation.performCalculation(10000, tag: "Operation 2") } ) blockOperation1.addExecutionBlock( { calculation.performCalculation(1000000, tag: "Operation 3") } ) operationQueue.addOperation(blockOperation1) In this code, we begin by creating an instance of the DoCalculation class and an instance of the NSOperationQueue class. Next, we created an instance of the NSBlockOperation class using the init constructor. This constructor takes a single parameter, which is a block of code that represents one of the tasks we want to execute in the queue. Next, we add two additional tasks to the NSBlockOperation instance using the addExecutionBlock() method. This is one of the differences between dispatch queues and operations. With dispatch queues, if resources are available, the tasks are executed as they are added to the queue. With operations, the individual tasks are not executed until the operation itself is submitted to an operation queue. Once we add all of the tasks to the NSBlockOperation instance, we then add the operation to the NSOperationQueue instance that we created at the beginning of the code. At this point, the individual tasks within the operation start to execute. This example shows how to use NSBlockOperation to queue up multiple tasks and then pass the tasks to the operation queue. The tasks are executed in a FIFO order; therefore, the first task that is added to the NSBlockOperation instance will be the first task executed. However, since the tasks can be executed concurrently if we have the available resources, the output from this code should look similar to this: time for Operation 2: 0.00546294450759888 time for Operation 3: 0.0800899863243103 time for Operation 1: 0.484337985515594 What if we do not want our tasks to run concurrently? What if we wanted them to run serially like the serial dispatch queue? We can set a property in our operation queue that defines the number of tasks that can be run concurrently in the queue. The property is called maxConcurrentOperationCount and is used like this: operationQueue.maxConcurrentOperatio nCount = 1 However, if we added this line to our previous example, it will not work as expected. To see why this is, we need to understand what the property actually defines. If we look at Apple's NSOperationQueue class reference, the definition of the property says, "The maximum number of queued operations that can execute at the same time." What this tells us is that the maxConcurrentOperationCount property defines the number of operations (this is the key word) that can be executed at the same time. The NSBlockOperation instance, which we added all of our tasks to, represents a single operation; therefore, no other NSBlockOperation added to the queue will execute until the first one is complete, but the individual tasks within the operation will execute concurrently. To run the tasks serially, we would need to create a separate instance of the NSBlockOperations for each task. Using an instance of the NSBlockOperation class good if we have a number of tasks that we want to execute concurrently, but they will not start executing until we add the operation to an operation queue. Let's look at a simpler way of adding tasks to an operation queue using the queues addOperationWithBlock() methods. Using the addOperationWithBlock() method of the operation queue The NSOperationQueue class has a method named addOperationWithBlock() that makes it easy to add a block of code to the queue. This method automatically wraps the block of code in an operation object and then passes that operation to the queue itself. Let's see how to use this method to add tasks to a queue: let operationQueue = NSOperationQueue() let calculation = DoCalculations() operationQueue.addOperationWithBlock() { calculation.performCalculation(10000000, tag: "Operation1") } operationQueue.addOperationWithBlock() { calculation.performCalculation(10000, tag: "Operation2") } operationQueue.addOperationWithBlock() { calculation.performCalculation(1000000, tag: "Operation3") } In the NSBlockOperation example, earlier in this artcle, we added the tasks that we wished to execute into an NSBlockOperation instance. In this example, we are adding the tasks directly to the operation queue, and each task represents one complete operation. Once we create the instance of the operation queue, we then use the addOperationWithBlock() method to add the tasks to the queue. Also, in the NSBlockOperation example, the individual tasks did not execute until all of the tasks were added to the NSBlockOperation object and then that operation was added to the queue. This addOperationWithBlock() example is similar to the GCD example where the tasks begin executing as soon as they are added to the operation queue. If we run the preceding code, the output should be similar to this: time for Operation2: 0.0115870237350464 time for Operation3: 0.0790849924087524 time for Operation1: 0.520610988140106 You will notice that the operations are executed concurrently. With this example, we can execute the tasks serially by using the maxConcurrentOperationCount property that we mentioned earlier. Let's try this by initializing the NSOperationQueue instance like this: var operationQueue = NSOperationQueue() operationQueue.maxConcurrentOperationCount = 1 Now, if we run the example, the output should be similar to this: time for Operation1: 0.418763995170593 time for Operation2: 0.000427007675170898 time for Operation3: 0.0441589951515198 In this example, we can see that each task waited for the previous task to complete prior to starting. Using the addOperationWithBlock() method to add tasks, the operation queue is generally easier than using the NSBlockOperation method; however, the tasks will begin as soon as they are added to the queue, which is usually the desired behavior. Now, let's look at how we can subclass the NSOperation class to create an operation that we can add directly to an operation queue. Subclassing the NSOperation class The previous two examples showed how to add small blocks of code to our operation queues. In these examples, we called the performCalculations method in the DoCalculation class to perform our tasks. These examples illustrate two really good ways to add concurrency for functionally that is already written, but what if, at design time, we want to design our DoCalculation class for concurrency? For this, we can subclass the NSOperation class. The NSOperation abstract class provides a significant amount of infrastructure. This allows us to very easily create a subclass without a lot of work. We should at least provide an initialization method and a main method. The main method will be called when the queue begins executing the operation: Let's see how to implement the DoCalculation class as a subclass of the NSOperation class; we will call this new class MyOperation: class MyOperation: NSOperation { let iterations: Int let tag: String init(iterations: Int, tag: String) { self.iterations = iterations self.tag = tag } override func main() { performCalculation() } func performCalculation() { let start = CFAbsoluteTimeGetCurrent() for var i=0; i<iterations; i++ { self.doCalc() } let end = CFAbsoluteTimeGetCurrent() print("time for (tag): (end-start)") } func doCalc() { let x=100 let y = x*x _ = y/x } } We begin by defining that the MyOperation class is a subclass of the NSOperation class. Within the implementation of the class, we define two class constants, which represent the iteration count and the tag that the performCalculations() method uses. Keep in mind that when the operation queue begins executing the operation, it will call the main() method with no parameters; therefore, any parameters that we need to pass in must be passed in through the initializer. In this example, our initializer takes two parameters that are used to set the iterations and tag classes constants. Then the main() method, that the operation queue is going to call to begin execution of the operation, simply calls the performCalculation() method. We can now very easily add instances of our MyOperation class to an operation queue, like this: var operationQueue = NSOperationQueue() operationQueue.addOperation(MyOperation (iterations: 10000000, tag: "Operation 1")) operationQueue.addOperation(MyOperation (iterations: 10000, tag: "Operation 2")) operationQueue.addOperation(MyOperation (iterations: 1000000, tag: "Operation 3")) If we run this code, we will see the following results: time for Operation 2: 0.00187397003173828 time for Operation 3: 0.104826986789703 time for Operation 1: 0.866684019565582 As we saw earlier, we can also execute the tasks serially by adding the following line, which sets the maxConcurrentOperationCount property of the operation queue: operationQueue.maxConcurrentOperationCount = 1 If we know that we need to execute some functionality concurrently prior to writing the code, I will recommend subclassing the NSOperation class, as shown in this example, rather than using the previous examples. This gives us the cleanest implementation; however, there is nothing wrong with using the NSBlockOperation class or the addOperationWithBlock() methods described earlier in this section. Summary Before we consider adding concurrency to our application, we should make sure that we understand why we are adding it and ask ourselves whether it is necessary. While concurrency can make our application more responsive by offloading work from our main application thread to a background thread, it also adds extra complexity to our code and overhead to our application. I have even seen numerous applications, in various languages, which actually run better after we pulled out some of the concurrency code. This is because the concurrency was not well thought out or planned. With this in mind, it is always a good idea to think and talk about concurrency while we are discussing the application's expected behavior. At the start of this artcle, we had a discussion about running tasks concurrently compared to running tasks in parallel. We also discussed the hardware limitation that limits how many tasks can run in parallel on a given device. Having a good understanding of those concepts is very important to understanding how and when to add concurrency to our projects. While GCD is not limited to system-level applications, before we use it in our application, we should consider whether operation queues would be easier and more appropriate for our needs. In general, we should use the highest level of abstraction that meets our needs. This will usually point us to using operation queues; however, there really is nothing preventing us from using GCD, and it may be more appropriate for our needs. One thing to keep in mind with operation queues is that they do add additional overhead because they are Cocoa objects. For the large majority of applications, this little extra overhead should not be an issue or even noticed; however, for some projects, such as games that need every last resource that they can get, this extra overhead might very well be an issue. Resources for Article: Further resources on this subject: Swift for Open Source Developers [article] Your First Swift 2 Project [article] Exploring Swift [article]
Read more
  • 0
  • 0
  • 20135

article-image-swift-open-source-developers
Packt
16 Feb 2016
43 min read
Save for later

Swift for Open Source Developers

Packt
16 Feb 2016
43 min read
Apple announced Swift at WWDC 2014 as a new programming language that combines experience with the Objective-C platform and advances in dynamic and statically typed languages over the last few decades. Before Swift, most code written for iOS and OS X applications was in Objective-C, a set of object-oriented extensions to the C programming language. Swift aims to build upon patterns and frameworks of Objective-C but with a more modern runtime and automatic memory management. In December 2015, Apple open sourced Swift at https://swift.org and made binaries available for Linux as well as OS X. The content in this article can be run on either Linux or OS X. Developing iOS applications requires Xcode and OS X. In this article, we will present the following topics: How to use the Swift REPL to evaluate Swift code The different types of Swift literals How to use arrays and dictionaries Functions and the different types of function arguments Compiling and running Swift from the command line (For more resources related to this topic, see here.) Open source Swift Apple released Swift as an open source project in December 2015, hosted at https://github.com/apple/swift/ and related repositories. Information about the open source version of Swift is available from the https://swift.org site. The open-source version of Swift is similar from a runtime perspective on both Linux and OS X; however, the set of libraries available differ between the two platforms. For example, the Objective-C runtime was not present in the initial release of Swift for Linux; as a result, several methods that are delegated to Objective-C implementations are not available. "hello".hasPrefix("he") compiles and runs successfully on OS X and iOS but is a compile error in the first Swift release for Linux. In addition to missing functions, there is also a different set of modules (frameworks) between the two platforms. The base functionality on OS X and iOS is provided by the Darwin module, but on Linux, the base functionality is provided by the Glibc module. The Foundation module, which provides many of the data types that are outside of the base-collections library, is implemented in Objective-C on OS X and iOS, but on Linux, it is a clean-room reimplementation in Swift. As Swift on Linux evolves, more of this functionality will be filled in, but it is worth testing on both OS X and Linux specifically if cross platform functionality is required. Finally, although the Swift language and core libraries have been open sourced, this does not apply to the iOS libraries or other functionality in Xcode. As a result, it is not possible to compile iOS or OS X applications from Linux, and building iOS applications and editing user interfaces is something that must be done in Xcode on OS X. Getting started with Swift Swift provides a runtime interpreter that executes statements and expressions. Swift is open source, and precompiled binaries can be downloaded from https://swift.org/download/ for both OS X and Linux platforms. Ports are in progress to other platforms and operating systems but are not supported by the Swift development team. The Swift interpreter is called swift and on OS X can be launched using the xcrun command in a Terminal.app shell: $ xcrun swift Welcome to Swift version 2.2!  Type :help for assistance. >  The xcrun command allows a toolchain command to be executed; in this case, it finds /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift. The swift command sits alongside other compilation tools, such as clang and ld, and permits multiple versions of the commands and libraries on the same machine without conflicting. On Linux, the swift binary can be executed provided that it and the dependent libraries are in a suitable location. The Swift prompt displays > for new statements and . for a continuation. Statements and expressions that are typed into the interpreter are evaluated and displayed. Anonymous values are given references so that they can be used subsequently: > "Hello World" $R0: String = "Hello World" > 3 + 4 $R1: Int = 7 > $R0 $R2: String = "Hello World" > $R1 $R3: Int = 7 Numeric literals Numeric types in Swift can represent both signed and unsigned integral values with sizes of 8, 16, 32, or 64 bits, as well as signed 32 or 64 bit floating point values. Numbers can include underscores to provide better readability; so, 68_040 is the same as 68040: > 3.141 $R0: Double = 3.141 > 299_792_458 $R1: Int = 299792458 > -1 $R2: Int = -1 > 1_800_123456 $R3: Int = 1800123456 Numbers can also be written in binary, octal, or hexadecimal using prefixes 0b, 0o (zero and the letter "o") or 0x. Please note that Swift does not inherit C's use of a leading zero (0) to represent an octal value, unlike Java and JavaScript which do. Examples include: > 0b1010011 $R0: Int = 83 > 0o123 $R1: Int = 83 > 0123 $R2: Int = 123 > 0x7b $R3: Int = 123   Floating point literals There are three floating point types that are available in Swift which use the IEEE754 floating point standard. The Double type represents 64 bits worth of data, while Float stores 32 bits of data. In addition, Float80 is a specialized type that stores 80 bits worth of data (Float32 and Float64 are available as aliases for Float and Double, respectively, although they are not commonly used in Swift programs). Some CPUs internally use 80 bit precision to perform math operations, and the Float80 type allows this accuracy to be used in Swift. Not all architectures support Float80 natively, so this should be used sparingly. By default, floating point values in Swift use the Double type. As floating point representation cannot represent some numbers exactly, some values will be displayed with a rounding error; for example: > 3.141 $R0: Double = 3.141 > Float(3.141) $R1: Float = 3.1400003 Floating point values can be specified in decimal or hexadecimal. Decimal floating point uses e as the exponent for base 10, whereas hexadecimal floating point uses p as the exponent for base 2. A value of AeB has the value A*10^B and a value of 0xApB has the value A*2^B. For example: > 299.792458e6 $R0: Double = 299792458 > 299.792_458_e6 $R1: Double = 299792458 > 0x1p8 $R2: Double = 256 > 0x1p10 $R3: Double = 1024 > 0x4p10 $R4: Double = 4096 > 1e-1 $R5: Double = 0.10000000000000001 > 1e-2 $R6: Double = 0.01> 0x1p-1 $R7: Double = 0.5 > 0x1p-2 $R8: Double = 0.25 > 0xAp-1 $R9: Double = 5 String literals Strings can contain escaped characters, Unicode characters, and interpolated expressions. Escaped characters start with a slash () and can be one of the following: \: This is a literal slash
Read more
  • 0
  • 0
  • 19948

article-image-using-protocols-and-protocol-extensions
Packt
13 Oct 2015
22 min read
Save for later

Using Protocols and Protocol Extensions

Packt
13 Oct 2015
22 min read
In this article by Jon Hoffman, the author of Mastering Swift 2, we'll see how protocols are used as a type, how we can implement polymorphism in Swift using protocols, how to use protocol extensions, and why we would want to use protocol extensions. (For more resources related to this topic, see here.) While watching the presentations from WWDC 2015 about protocol extensions and protocol-oriented programming, I will admit that I was very skeptical. I have worked with object-oriented programming for so long that I was unsure if this new programming paradigm would solve all of the problems that Apple was claiming it would. Since I am not one to let my skepticism get in the way of trying something new, I set up a new project that mirrored the one I was currently working on, but wrote the code using Apple's recommendations for protocol-oriented programming and used protocol extensions extensively in the code. I can honestly say that I was amazed with how much cleaner the new project was compared to the original one. I believe that protocol extensions is going to be one of those defining features that set one programming language apart from the rest. I also believe that many major languages will soon have similar features. Protocol extensions are the backbone for Apple's new protocol-oriented programming paradigm and is arguably one of the most important additions to the Swift programming language. With protocol extensions, we are able to provide method and property implementations to any type that conforms to a protocol. To really understand how useful protocols and protocol extensions are, let's get a better understanding of protocols. While classes, structs, and enums can all conform to protocols in Swift, for this article, we will be focusing on classes and structs. Enums are used when we need to represent a finite number of cases and while there are valid use cases where we would have an enum conform to a protocol, they are very rare in my experience. Just remember that anywhere that we refer to a class or struct, we can also use an enum. Let's begin exploring protocols by seeing how they are full-fledged types in Swift. Protocol as a type Even though no functionality is implemented in a protocol, they are still considered a full-fledged type in the Swift programming language and can be used like any other type. What this means is we can use protocols as a parameter type or a return type in a function. We can also use them as the type for variables, constants, and collections. Let's take a look at some examples. For these few examples, we will use the PersonProtocol protocol: protocol PersonProtocol { var firstName: String {get set} var lastName: String {get set} var birthDate: NSDate {get set} var profession: String {get} init (firstName: String, lastName: String, birthDate: NSDate) } In this first example, we will see how we would use protocols as a parameter type or return type in functions, methods, or initializers: func updatePerson(person: PersonProtocol) -> PersonProtocol { // Code to update person goes here return person } In this example, the updatePerson() function accepts one parameter of the PersonProtocol protocol type and then returns a value of the PersonProtocol protocol type. Now let's see how we can use protocols as a type for constants, variables, or properties: var myPerson: PersonProtocol In this example, we create a variable of the PersonProtocol protocol type that is named myPerson. We can also use protocols as the item type to store in collection such as arrays, dictionaries, or sets: var people: [PersonProtocol] = [] In this final example, we create an array of PersonProtocol protocol types. As we can see from these three examples, even though the PersonProtocol protocol does not implement any functionality, we can still use protocols when we need to specify a type. We cannot, however, create an instance of a protocol. This is because no functionality is implemented in a protocol. As an example, if we tried to create an instance of the PersonProtocol protocol, we would be receiving the error: protocol type 'PersonProtocol' cannot be instantiated error, as shown in the following example: var test = PersonProtocol(firstName: "Jon", lastName: "Hoffman", birthDate: bDateProgrammer) We can use the instance of any class or struct that conforms to our protocol anywhere that the protocol type is required. As an example, if we defined a variable to be of the PersonProtocol protocol type, we could then populate that variable with any class or struct that conforms to the PersonProtocol protocol. For this example, let's assume that we have two types named SwiftProgrammer and FootballPlayer, which conform to the PersonProtocol protocol: var myPerson: PersonProtocol myPerson = SwiftProgrammer(firstName: "Jon", lastName: "Hoffman", birthDate: bDateProgrammer) print("(myPerson.firstName) (myPerson.lastName)") myPerson = FootballPlayer(firstName: "Dan", lastName: "Marino", birthDate: bDatePlayer) print("(myPerson.firstName) (myPerson.lastName)") In this example, we start off by creating the myPerson variable of the PersonProtocol protocol type. We then set the variable with an instance of the SwiftProgrammer type and print out the first and last names. Next, we set the myPerson variable to an instance of the FootballPlayer type and print out the first and last names again. One thing to note is that Swift does not care if the instance is a class or struct. It only matters that the type conforms to the PersonProtocol protocol type. Therefore, if our SwiftProgrammer type was a struct and the FootballPlayer type was a class, our previous example would be perfectly valid. As we saw earlier, we can use our PersonProtocol protocol as the type for an array. This means that we can populate the array with instances of any type that conforms to the PersonProtocol protocol. Once again, it does not matter if the type is a class or a struct as long as it conforms to the PersonProtocol protocol. Here is an example of this: var programmer = SwiftProgrammer(firstName: "Jon", lastName: "Hoffman", birthDate: bDateProgrammer) var player = FootballPlayer(firstName: "Dan", lastName: "Marino", birthDate: bDatePlayer) var people: [PersonProtocol] = [] people.append(programmer) people.append(player) In this example, we create an instance of the SwiftProgrammer type and an instance of the FootballPlayer type. We then add both instances to the people array. Polymorphism with protocols What we were seeing in the previous examples is a form of Polymorphism. The word polymorphism comes from the Greek roots Poly, meaning many and morphe, meaning form. In programming languages, polymorphism is a single interface to multiple types (many forms). In the previous example, the single interface was the PersonProtocol protocol and the multiple types were any type that conforms to that protocol. Polymorphism gives us the ability to interact with multiple types in a uniform manner. To illustrate this, we can extend our previous example where we created an array of the PersonProtocol types and loop through the array. We can then access each item in the array using the properties and methods define in the PersonProtocol protocol, regardless of the actual type. Let's see an example of this: for person in people { print("(person.firstName) (person.lastName): (person.profession)") } If we ran this example, the output would look similar to this: Jon Hoffman: Swift Programmer Dan Marino: Football Player We have mentioned a few times in this article that when we define the type of a variable, constant, collection type, and so on to be a protocol type, we can then use the instance of any type that conforms to that protocol. This is a very important concept to understand and it is what makes protocols and protocol extensions so powerful. When we use a protocol to access instances, as shown in the previous example, we are limited to using only properties and methods that are defined in the protocol. If we want to use properties or methods that are specific to the individual types, we would need to cast the instance to that type. Type casting with protocols Type casting is a way to check the type of the instance and/or to treat the instance as a specified type. In Swift, we use the is keyword to check if an instance is a specific type and the as keyword to treat the instance as a specific type. To start with, let's see how we would check the instance type using the is keyword. The following example shows how would we do this: for person in people { if person is SwiftProgrammer { print("(person.firstName) is a Swift Programmer") } } In this example, we use the if conditional statement to check whether each element in the people array is an instance of the SwiftProgrammer type and if so, we print that the person is a Swift programmer to the console. While this is a good method to check whether we have an instance of a specific class or struct, it is not very efficient if we wanted to check for multiple types. It is a lot more efficient to use the switch statement, as shown in the next example, if we want to check for multiple types: for person in people { switch (person) { case is SwiftProgrammer: print("(person.firstName) is a Swift Programmer") case is FootballPlayer: print("(person.firstName) is a Football Player") default: print("(person.firstName) is an unknown type") } } In the previous example, we showed how to use the switch statement to check the instance type for each element of the array. To do this check, we use the is keyword in each of the case statements in an attempt to match the instance type. We can also use the where statement with the is keyword to filter the array, as shown in the following example: for person in people where person is SwiftProgrammer { print("(person.firstName) is a Swift Programmer") } Now let's look at how we can cast an instance of a class or struct to a specific type. To do this, we can use the as keyword. Since the cast can fail if the instance is not of the specified type, the as keyword comes in two forms: as? and as!. With the as? form, if the casting fails, it returns a nil, and with the as! form, if the casting fails, we get a runtime error; therefore, it is recommended to use the as? form unless we are absolutely sure of the instance type or we perform a check of the instance type prior to doing the cast. Let's look at how we would use the as? keyword to cast an instance of a class or struct to a specified type: for person in people { if let p = person as? SwiftProgrammer { print("(person.firstName) is a Swift Programmer") } } Since the as? keyword returns an optional, we can use optional binding to perform the cast, as shown in this example. If we are sure of the instance type, we can use the as! keyword. The following example shows how to use the as! keyword when we filter the results of the array to only return instances of the SwiftProgrammer type: for person in people where person is SwiftProgrammer { let p = person as! SwiftProgrammer } Now that we have covered the basics of protocols, that is, how polymorphism works and type casting, let's dive into one of the most exciting new features of Swift protocol extensions. Protocol extensions Protocol extensions allow us to extend a protocol to provide method and property implementations to conforming types. It also allows us to provide common implementations to all the confirming types eliminating the need to provide an implementation in each individual type or the need to create a class hierarchy. While protocol extensions may not seem too exciting, once you see how powerful they really are, they will transform the way you think about and write code. Let's begin by looking at how we would use protocol extension with a very simplistic example. We will start off by defining a protocol called DogProtocol as follows: protocol DogProtocol { var name: String {get set} var color: String {get set} } With this protocol, we are saying that any type that conforms to the DogProtocol protocol, must have the two properties of the String type, namely, name and color. Now let's define the three types that conform to this protocol. We will name these types JackRussel, WhiteLab, and Mutt as follows: struct JackRussel: DogProtocol { var name: String var color: String } class WhiteLab: DogProtocol { var name: String var color: String init(name: String, color: String) { self.name = name self.color = color } } struct Mutt: DogProtocol { var name: String var color: String } We purposely created the JackRussel and Mutt types as structs and the WhiteLab type as a class to show the differences between how the two types are set up and to illustrate how they are treated in the same way when it comes to protocols and protocol extensions. The biggest difference that we can see in this example is the struct types provide a default initiator, but in the class, we must provide the initiator to populate the properties. Now let's say that we want to provide a method named speak to each type that conforms to the DogProtocol protocol. Prior to protocol extensions, we would start off by adding the method definition to the protocol, as shown in the following code: protocol DogProtocol { var name: String {get set} var color: String {get set} func speak() -> String } Once the method is defined in the protocol, we would then need to provide an implementation of the method in every type that conform to the protocol. Depending on the number of types that conformed to this protocol, this could take a bit of time to implement. The following code sample shows how we might implement this method: struct JackRussel: DogProtocol { var name: String var color: String func speak() -> String { return "Woof Woof" } } class WhiteLab: DogProtocol { var name: String var color: String init(name: String, color: String) { self.name = name self.color = color } func speak() -> String { return "Woof Woof" } } struct Mutt: DogProtocol { var name: String var color: String func speak() -> String { return "Woof Woof" } } While this method works, it is not very efficient because anytime we update the protocol, we would need to update all the types that conform to it and we may be duplicating a lot of code, as shown in this example. Another concern is, if we need to change the default behavior of the speak() method, we would have to go in each implementation and change the speak() method. This is where protocol extensions come in. With protocol extensions, we could take the speak() method definition out of the protocol itself and define it with the default behavior, in protocol extension. The following code shows how we would define the protocol and the protocol extension: protocol DogProtocol { var name: String {get set} var color: String {get set} } extension DogProtocol { func speak() -> String { return "Woof Woof" } } We begin by defining DogProtocol with the original two properties. We then create a protocol extension that extends DogProtocol and contains the default implementation of the speak() method. With this code, there is no need to provide an implementation of the speak() method in each of the types that conform to DogProtocol because they automatically receive the implementation as part of the protocol. Let's see how this works by setting our three types that conform to DogProtocol back to their original implementations and they should receive the speak() method from the protocol extension: struct JackRussel: DogProtocol { var name: String var color: String } class WhiteLab: DogProtocol { var name: String var color: String init(name: String, color: String) { self.name = name self.color = color } } struct Mutt: DogProtocol { var name: String var color: String } We can now use each of the types as shown in the following code: let dash = JackRussel(name: "Dash", color: "Brown and White") let lily = WhiteLab(name: "Lily", color: "White") let buddy = Mutt(name: "Buddy", color: "Brown") let dSpeak = dash.speak() // returns "woof woof" let lSpeak = lily.speak() // returns "woof woof" let bSpeak = buddy.speak() // returns "woof woof" As we can see in this example, by adding the speak() method to the DogProtocol protocol extension, we are automatically adding that method to all the types that conform to DogProtocol. The speak() method in the DogProtocol protocol extension can be considered a default implementation of the speak() method because we are able to override it in the type implementations. As an example, we could override the speak() method in the Mutt struct, as shown in the following code: struct Mutt: DogProtocol { var name: String var color: String func speak() -> String { return "I am hungry" } } When we call the speak() method for an instance of the Mutt type, it will return the string, "I am hungry". Now that we have seen how we would use protocols and protocol extensions, let's look at a more real-world example. In numerous apps, across multiple platforms (iOS, Android, and Windows), I have had the requirement to validate user input as it is entered. This validation can be done very easily with regular expressions; however, we do not want various regular expressions littered through out our code. It is very easy to solve this problem by creating different classes or structs that contains the validation code; however, we would have to organize these classes to make them easy to use and maintain. Prior to protocol extensions in Swift, I would use protocols to define the validation requirements and then create a struct that would conform to the protocol for each validation that I needed. Let's take a look at this preprotocol extension method. A regular expression is a sequence of characters that define a particular pattern. This pattern can then be used to search a string to see whether the string matches the pattern or contains a match of the pattern. Most major programming languages contain a regular expression parser, and if you are not familiar with regular expressions, it may be worth to learn more about them. The following code shows the TextValidationProtocol protocol that defines the requirements for any type that we want to use for text validation: protocol TextValidationProtocol { var regExMatchingString: String {get} var regExFindMatchString: String {get} var validationMessage: String {get} func validateString(str: String) -> Bool func getMatchingString(str: String) -> String? } In this protocol, we define three properties and two methods that any type that conforms to TextValidationProtocol must implement. The three properties are: regExMatchingString: This is a regular expression string used to verify that the input string contains only valid characters. regExFindMatchString: This is a regular expression string used to retrieve a new string from the input string that contains only valid characters. This regular expression is generally used when we need to validate the input real time, as the user enters information, because it will find the longest matching prefix of the input string. validationMessage: This is the error message to display if the input string contains non-valid characters. The two methods for this protocol are as follows: validateString: This method will return true if the input string contains only valid characters. The regExMatchingString property will be used in this method to perform the match. getMatchingString: This method will return a new string that contains only valid characters. This method is generally used when we need to validate the input real time as the user enters information because it will find the longest matching prefix of the input string. We will use the regExFindMatchString property in this method to retrieve the new string. Now let's see how we would create a struct that conforms to this protocol. The following struct would be used to verify that the input string contains only alpha characters: struct AlphaValidation1: TextValidationProtocol { static let sharedInstance = AlphaValidation1() private init(){} let regExFindMatchString = "^[a-zA-Z]{0,10}" let validationMessage = "Can only contain Alpha characters" var regExMatchingString: String { get { return regExFindMatchString + "$" } } func validateString(str: String) -> Bool { if let _ = str.rangeOfString(regExMatchingString, options: .RegularExpressionSearch) { return true } else { return false } } func getMatchingString(str: String) -> String? { if let newMatch = str.rangeOfString(regExFindMatchString, options: .RegularExpressionSearch) { return str.substringWithRange(newMatch) } else { return nil } } } In this implementation, the regExFindMatchString and validationMessage properties are stored properties, and the regExMatchingString property is a computed property. We also implement the validateString() and getMatchingString() methods within the struct. Normally, we would have several different types that conform to TextValidationProtocol where each one would validate a different type of input. As we can see from the AlphaValidation1 struct, there is a bit of code involved with each validation type. A lot of the code would also be duplicated in each type. The code for both methods (validateString() and getMatchingString()) and the regExMatchingString property would be duplicated in every validation class. This is not ideal, but if we wanted to avoid creating a class hierarchy with a super class that contains the duplicate code (I personally prefer using value types over classes), we would have no other choice. Now let's see how we would implement this using protocol extensions. With protocol extensions we need to think about the code a little differently. The big difference is, we do not need, nor want to define everything in the protocol. With standard protocols or when we use class hierarchy, all the methods and properties that you would want to access using the generic superclass or protocol would have to be defined within the superclass or protocol. With protocol extensions, it is preferred for us not to define a property or method in the protocol if we are going to be defining it within the protocol extension. Therefore, when we rewrite our text validation types with protocol extensions, TextValidationProtocol would be greatly simplified to look similar to this: protocol TextValidationProtocol { var regExFindMatchString: String {get} var validationMessage: String {get} } In original TextValidationProtocol, we defined three properties and two methods. As we can see in this new protocol, we are only defining two properties. Now that we have our TextValidationProtocol defined, let's create the protocol extension for it: extension TextValidationProtocol { var regExMatchingString: String { get { return regExFindMatchString + "$" } } func validateString(str: String) -> Bool { if let _ = str.rangeOfString(regExMatchingString, options: .RegularExpressionSearch) { return true } else { return false } } func getMatchingString(str: String) -> String? { if let newMatch = str.rangeOfString(regExFindMatchString, options: .RegularExpressionSearch) { return str.substringWithRange(newMatch) } else { return nil } } } In the TextValidationProtocol protocol extension, we define the two methods and the third property that were defined in original TextValidationProtocol, but were not defined in the new one. Now that we have created our protocol and protocol extension, we are able to define our text validation types. In the following code, we define three structs that we will use to validate text when a users types it in: struct AlphaValidation: TextValidationProtocol { static let sharedInstance = AlphaValidation() private init(){} let regExFindMatchString = "^[a-zA-Z]{0,10}" let validationMessage = "Can only contain Alpha characters" } struct AlphaNumericValidation: TextValidationProtocol { static let sharedInstance = AlphaNumericValidation() private init(){} let regExFindMatchString = "^[a-zA-Z0-9]{0,15}" let validationMessage = "Can only contain Alpha Numeric characters" } struct DisplayNameValidation: TextValidationProtocol { static let sharedInstance = DisplayNameValidation() private init(){} let regExFindMatchString = "^[\s?[a-zA-Z0-9\-_\s]]{0,15}" let validationMessage = "Display Name can contain only contain Alphanumeric Characters" } In each one of the text validation structs, we create a static constant and a private initiator so that we can use the struct as a singleton. After we define the singleton pattern, all we do in each type is set the values for the regExFindMatchString and validationMessage properties. Now we have not duplicated the code virtually because even if we could, we would not want to define the singleton code in the protocol extension because we would not want to force that pattern on all the conforming types. To use the text validation classes, we would want to create a dictionary object that would map the UITextField objects to the validation class to use it like this: var validators = [UITextField: TextValidationProtocol]() We could then populate the validators dictionary as shown here: validators[alphaTextField] = AlphaValidation.sharedInstance validators[alphaNumericTextField] = AlphaNumericValidation.sharedInstance validators[displayNameTextField] = DisplayNameValidation.sharedInstance We can now set the EditingChanged event of the text fields to a single method named keyPressed(). To set the edition changed event for each field, we would add the following code to the viewDidLoad() method of our view controller: alphaTextField.addTarget(self, action:Selector("keyPressed:"), forControlEvents: UIControlEvents.EditingChanged) alphaNumericTextField.addTarget(self, action: Selector("keyPressed:"), forControlEvents: UIControlEvents.EditingChanged) displayNameTextField.addTarget(self, action: Selector("keyPressed:"), forControlEvents: UIControlEvents.EditingChanged) Now lets create the keyPressed() method that each text field calls when a user types a character into the field: @IBAction func keyPressed(textField: UITextField) { if let validator = validators[textField] where !validator.validateString(textField.text!) { textField.text = validator.getMatchingString(textField.text!) messageLabel?.text = validator.validationMessage } } In this method, we use the if let validator = validators[textField] statement to retrieve the validator for the particular text field and then we use the where !validator.validateString(textField.text!) statement to validate the string that the user has entered. If the string fails validation, we use the getMatchingString() method to update the text in the text field by removing all the characters from the input string, starting with the first invalid character and then displaying the error message from the text validation class. If the string passes validation, the text in the text field is left unchanged. Summary In this article, we saw that protocols are treated as full-fledged types by Swift. We also saw how polymorphism can be implemented in Swift with protocols. We concluded this article with an in-depth look at protocol extensions and saw how we would use them in Swift. Protocols and protocol extensions are the backbone of Apple's new protocol-oriented programming paradigm. This new model for programming has the potential to change the way we write and think about code. While we did not specifically cover protocol-oriented programming in this article, understanding the topics in this article gives us the solid understanding of protocols and protocol extensions needed to learn about this new programming model. Resources for Article: Further resources on this subject: Using OpenStack Swift [Article] Dragging a CCNode in Cocos2D-Swift [Article] Installing OpenStack Swift [Article]
Read more
  • 0
  • 0
  • 18285

article-image-delegate-pattern-limitations-swift
Anthony Miller
18 Mar 2016
5 min read
Save for later

Delegate Pattern Limitations in Swift

Anthony Miller
18 Mar 2016
5 min read
If you've ever built anything using UIKit, then you are probably familiar with the delegate pattern. The delegate pattern is used frequently throughout Apple's frameworks and many open source libraries you may come in contact with. But many times, it is treated as a one-size-fits-all solution for problems that it is just not suited for. This post will describe the major shortcomings of the delegate pattern. Note: This article assumes that you have a working knowledge of the delegate pattern. If you would like to learn more about the delegate pattern, see The Swift Programming Language - Delegation. 1. Too Many Lines! Implementation of the delegate pattern can be cumbersome. Most experienced developers will tell you that less code is better code, and the delegate pattern does not really allow for this. To demonstrate, let's try implementing a new view controller that has a delegate using the least amount of lines possible. First, we have to create a view controller and give it a property for its delegate: class MyViewController: UIViewController { var delegate: MyViewControllerDelegate? } Then, we define the delegate protocol. protocol MyViewControllerDelegate { func foo() } Now we have to implement the delegate. Let's make another view controller that presents a MyViewController: class DelegateViewController: UIViewController { func presentMyViewController() { let myViewController = MyViewController() presentViewController(myViewController, animated: false, completion: nil) } } Next, our DelegateViewController needs to conform to the delegate protocol: class DelegateViewController: UIViewController, MyViewControllerDelegate { func presentMyViewController() { let myViewController = MyViewController() presentViewController(myViewController, animated: false, completion: nil) } func foo() { /// Respond to the delegate method. } } Finally, we can make our DelegateViewController the delegate of MyViewController: class DelegateViewController: UIViewController, MyViewControllerDelegate { func presentMyViewController() { let myViewController = MyViewController() myViewController.delegate = self presentViewController(myViewController, animated: false, completion: nil) } func foo() { /// Respond to the delegate method. } } That's a lot of boilerplate code that is repeated every time you want to create a new delegate. This opens you up to a lot of room for errors. In fact, the above code has a pretty big error already that we are going to fix now. 2. No Non-Class Type Delegates Whenever you create a delegate property on an object, you should use the weak keyword. Otherwise, you are likely to create a retain cycle. Retain cycles are one of the most common ways to create memory leaks and can be difficult to track down. Let's fix this by making our delegate weak: class MyViewController: UIViewController { weak var delegate: MyViewControllerDelegate? } This causes another problem though. Now we are getting a build error from Xcode! 'weak' cannot be applied to non-class type 'MyViewControllerDelegate'; consider adding a class bound. This is because you can't make a weak reference to a value type, such as a struct or an enum, so in order to use the weak keyword here, we have to guarantee that our delegate is going to be a class. Let's take Xcode's advice here and add a class bound to our protocol: protocol MyViewControllerDelegate: class { func foo() } Well, now everything builds just fine, but we have another issue. Now your delegate must be an object (sorry structs and enums!). You are now creating more constraints on what can conform to your delegate. The whole point of the delegate pattern is to allow an unknown "something" to respond to the delegate events. We should be putting as few constraints as possible on our delegate object, which brings us to the next issue with the delegate pattern. 3. Optional Delegate Methods In pure Swift, protocols don't have optional functions. This means, your delegate must implement every method in the delegate protocol, even if it is irrelevant in your case. For example, you may not always need to be notified when a user taps a cell in a UITableView. There are ways to get around this though. In Swift 2.0+, you can make a protocol extension on your delegate protocol that contains a default implementation for protocol methods that you want to make optional. Let's make a new optional method on our delegate protocol using this method: protocol MyViewControllerDelegate: class { func foo() func optionalFunction() } extension MyViewControllerDelegate { func optionalFunction() { } } This adds even more unnecessary code. It isn't really clear what the intention of this extension is unless you understand what's going on already, and there is no way to explicitly show that this method is optional. Alternatively, if you mark your protocol as @objc, you can use the optional keyword in your function declaration. The problem here is that now your delegate must be an Objective-C object. Just like our last example, this is creating additional constraints on your delegate, and this time they are even more restrictive. 4. There Can Be Only One The delegate pattern only allows for one delegate to respond to events. This may be just fine for some situations, but if you need multiple objects to be notified of an event, the delegate pattern may not work for you. Another common scenario you may come across is when you need different objects to be notified of different delegate events. The delegate pattern can be a very useful tool, which is why it is so widely used, but recognizing the limitations that it creates is important when you are deciding whether it is the right solution for any given problem. About the author Anthony Miller is the lead iOS developer at App-Order in Las Vegas, Nevada, USA. He has written and released numerous apps on the App Store and is an avid open source contributor. When he's not developing, Anthony loves board games, line-dancing, and frequent trips to Disneyland.
Read more
  • 0
  • 0
  • 17579

article-image-understanding-uikitfundamentals
Packt
01 Jun 2016
9 min read
Save for later

Understanding UIKitFundamentals

Packt
01 Jun 2016
9 min read
In this article by Jak Tiano, author of the book Learning Xcode, we're mostly going to be talking about concepts rather than concrete code examples. Since we've been using UIKit throughout the whole book (and we will continue to do so), I'm going to do my best to elaborate on some things we've already seen and give you new information that you can apply to what we do in the future. (For more resources related to this topic, see here) As we've heard a lot about UIKit. We've seen it at the top of our Swift files in the form of import UIKit. We've used many of the UI elements and classes it provides for us. Now, it's time to take an isolated look at the biggest and most important framework in iOS development. Application management Unlike most other frameworks in the iOS SDK, UIKit is deeply integrated into the way your app runs. That's because UIKit is responsible for some of the most essential functionalities of an app. It also manages your application's window and view architecture, which we'll be talking about next. It also drives the main run loop, which basically means that it is executing your program. The UIDevice class In addition to these very important features, UIKit also gives you access to some other useful information about the device the app is currently running on through the UIDevice class. Using online resources and documentation: Since this article is about exploring frameworks, it is a good time to remind you that you can (and should!) always be searching online for anything and everything. For example, if you search for UIDevice, you'll end up on Apple's developer page for the UIDevice class, where you can see even more bits of information that you can pull from it. As we progress, keep in mind that searching the name of a class or framework will usually give you quick access to the full documentation. Here are some code examples of the information you can access: UIDevice.currentDevice().name UIDevice.currentDevice().model UIDevice.currentDevice().orientation UIDevice.currentDevice().batteryLevel UIDevice.currentDevice().systemVersion Some developers have a little bit of fun with this information: for example, Snapchat gives you a special filter to use for photos when your battery is fully charged.Always keep an open mind about what you can do with data you have access to! Views One of the most important responsibilities of UIKit is that it provides views and the view hierarchy architecture. We've talked before about what a view is within the MVC programming paradigm, but here we're referring to the UIView class that acts as the base for (almost) all of our visual content in iOS programming. While it wasn't too important to know about when just getting our feet wet, now is a good time to really dig in a bit and understand what UIViews are and how they work both on their own and together. Let's start from the beginning: a view (UIView) defines a rectangle on your screen that is responsible for output and input, meaning drawing to the screen and receiving touch events.It can also contain other views, known as subviews, which ultimately create a view hierarchy. As a result of this hierarchy, we have to be aware of the coordinate systems involved. Now, let's talk about each of these three functions: drawing, hierarchies, and coordinate systems. Drawing Each UIView is responsible for drawing itself to the screen. In order to optimize drawing performance, the views will usually try to render their content once and then reuse that image content when it doesn't change. It can even move and scale content around inside of it without needing to redraw, which can be an expensive operation: An overview of how UIView draws itself to the screen With the system provided views, all of this is handled automatically. However, if you ever need to create your own UIView subclass that uses custom drawing, it's important to know what goes on behind the scenes. To implement custom drawing in a view, you need to implement the drawRect() function in your subclass. When something changes in your view, you need to call the setNeedsDisplay() function, which acts as a marker to let the system know that your view needs to be redrawn. During the next drawing cycle, the code in your drawRect() function will be executed to refresh the content of your view, which will then be cached for performance. A code example of this custom drawing functionality is a bit beyond the scope of this article, but discussing this will hopefully give you a better understanding of how drawing works in addition to giving you a jumping off point should you need to do this in the future. Hierarchies Now, let's discuss view hierarchies. When we would use a view controller in a storyboard, we would drag UI elements onto the view controller. However, what we were actually doing is adding a subview to the base view of the view controller. And in fact, that base view was a subview of the UIWindow, which is also a UIView. So, though, we haven't really acknowledged it, we've already put view hierarchies to work many times. The easiest way to think about what happens in a view hierarchy is that you set one view's parent coordinate system relative to another view. By default, you'd be setting a view's coordinate system to be relative to the base view, which is normally just the whole screen. But you can also set the parent coordinate system to some other view so that when you move or transform the parent view, the children views are moved and transformed along with it. Example of how parenting works with a view hierarchy. It's also important to note that the view hierarchy impacts the draw order of your views. All of a view's subviews will be drawn on top of the parent view, and the subviews will be drawn in the order they were added (the last subview added will be on top). To add a subview through code, you can use the addSubview() function. Here's an example: var view1 = UIView() var view2 = UIView() view1.addSubview(view2) The top-most views will intercept a touch first, and if it doesn't respond, it will pass it down the view hierarchy until a view does respond. Coordinate systems With all of this drawing and parenting, we need to take a minute to look at how the coordinate system works in UIKit for our views.The origin (0,0 point) in UIKit is the top left of the screen, and increases along X to the right, and increases on the Y downward. Each view is placed in this upper-left positioning system relative to its parent view's origin. Be careful! Other frameworks in iOS use different coordinate systems. For example, SpriteKit uses the lower-left corner as the origin. Each view also has its own setof positioning information. This is composed of the view's frame, bounds, and center. The frame rectangle describes the origin and the size of view relative to its parent view's coordinate system. The bounds rectangle describes the origin and the size of the view from its local coordinate system. The center is just the center point of the view relative to the parent view. When dealing with so many different coordinate systems, it can seem like a nightmare to compare positions from different views. Luckily, the UIView class provides a simple convertPoint()function to convert points between systems. Try running this little experiment in a playground to see how the point gets converted from one view's coordinate system to the other: import UIKit let view1 = UIView(frame: CGRect(x: 0, y: 0, width: 50, height: 50)) let view2 = UIView(frame: CGRect(x: 10, y: 10, width: 30, height: 30)) view1.addSubview(view2) let pointFrom1 = CGPoint(x: 20, y: 20) let pointFromView2 = view1.convertPoint(pointFrom1, toView: view2) Hopefully, you now have a much better understanding of some of the underlying workings of the view system in UIKit. Documents, displays, printing, and more In this section, I'm going to do my best to introduce you to the many additional features of the UIKit framework. The idea is to give you a better understanding of what is possible with UIKit, and if anything sounds interesting to you, you can go off and explore these features on your own. Documents UIKit has built in support for documents, much like you'd find on a desktop operating system. Using the UIDocument class, UIKit can help you save and load documents in the background in addition to saving them to iCloud. This could be a powerful feature for any app that allows the user to create content that they expect to save and resume working on later. Displays On most new iOS devices, you can connect external screens via HDMI. You can take advantage of these external displays by creating a new instance of the UIWindow class, and associating it with the external display screen. You can then add subviews to that window to create a secondscreen experience for devices like a bigscreen TV. While most consumers don't ever use HDMI-connected external displays, this is a great feature to keep in mind when working on internal applications for corporate or personal use. Printing Using the UIPrintInteractionController, you can set up and send print jobs to AirPrint-enabled printers on the user's network. Before you print, you can also create PDFs by drawing content off screen to make printing easier. And more! There are many more features of UIKit that are just waiting to be explored! To be honest, UIKit seems to be pretty much a dumping ground for any general features that were just a bit too small to deserve their own framework. If you do some digging in Apple's documentation, you'll find all kinds of interesting things you can do with UIKit, such as creating custom keyboards, creating share sheets, and custom cut-copy-paste support. Summary In this article, we looked at the biggest and most important UIKit and learned about some of the most important system processes like the view hierarchy. Resources for Article:   Further resources on this subject: Building Surveys using Xcode [article] Run Xcode Run [article] Tour of Xcode [article]
Read more
  • 0
  • 0
  • 17290
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at €18.99/month. Cancel anytime
article-image-building-surveys-using-xcode
Packt
19 Jan 2016
14 min read
Save for later

Building Surveys using Xcode

Packt
19 Jan 2016
14 min read
In this article by Dhanushram Balachandran and Edward Cessna author of book Getting Started with ResearchKit, you can find the Softwareitis.xcodeproj project in the Chapter_3/Softwareitis folder of the RKBook GitHub repository (https://github.com/dhanushram/RKBook/tree/master/Chapter_3/Softwareitis). (For more resources related to this topic, see here.) Now that you have learned about the results of tasks from the previous section, we can modify the Softwareitis project to incorporate processing of the task results. In the TableViewController.swift file, let's update the rows data structure to include the reference for processResultsMethod: as shown in the following: //Array of dictionaries. Each dictionary contains [ rowTitle : (didSelectRowMethod, processResultsMethod) ] var rows : [ [String : ( didSelectRowMethod:()->(), processResultsMethod:(ORKTaskResult?)->() )] ] = [] Update the ORKTaskViewControllerDelegate method taskViewController(taskViewController:, didFinishWithReason:, error:) in TableViewController to call processResultsMethod, as shown in the following: func taskViewController(taskViewController: ORKTaskViewController, didFinishWithReason reason: ORKTaskViewControllerFinishReason, error: NSError?) { if let indexPath = tappedIndexPath { //1 let rowDict = rows[indexPath.row] if let tuple = rowDict.values.first { //2 tuple.processResultsMethod(taskViewController.result) } } dismissViewControllerAnimated(true, completion: nil) } Retrieves the dictionary of the tapped row and its associated tuple containing the didSelectRowMethod and processResultsMethod references from rows. Invokes the processResultsMethod with taskViewController.result as the parameter. Now, we are ready to create our first survey. In Survey.swift, under the Surveys folder, you will find two methods defined in the TableViewController extension: showSurvey() and processSurveyResults(). These are the methods that we will be using to create the survey and process the results. Instruction step Instruction step is used to show instruction or introductory content to the user at the beginning or middle of a task. It does not produce any result as its an informational step. We can create an instruction step using the ORKInstructionStep object. It has title and detailText properties to set the appropriate content. It also has the image property to show an image. The ORKCompletionStep is a special type of ORKInstructionStep used to show the completion of a task. The ORKCompletionStep shows an animation to indicate the completion of the task along with title and detailText, similar to ORKInstructionStep. In creating our first Softwareitis survey, let's use the following two steps to show the information: func showSurvey() { //1 let instStep = ORKInstructionStep(identifier: "Instruction Step") instStep.title = "Softwareitis Survey" instStep.detailText = "This survey demonstrates different question types." //2 let completionStep = ORKCompletionStep(identifier: "Completion Step") completionStep.title = "Thank you for taking this survey!" //3 let task = ORKOrderedTask(identifier: "first survey", steps: [instStep, completionStep]) //4 let taskViewController = ORKTaskViewController(task: task, taskRunUUID: nil) taskViewController.delegate = self presentViewController(taskViewController, animated: true, completion: nil) } The explanation of the preceding code is as follows: Creates an ORKInstructionStep object with an identifier "Instruction Step" and sets its title and detailText properties. Creates an ORKCompletionStep object with an identifier "Completion Step" and sets its title property. Creates an ORKOrderedTask object with the instruction and completion step as its parameters. Creates an ORKTaskViewController object with the ordered task that was previously created and presents it to the user. Let's update the processSurveyResults method to process the results of the instruction step and the completion step as shown in the following: func processSurveyResults(taskResult: ORKTaskResult?) { if let taskResultValue = taskResult { //1 print("Task Run UUID : " + taskResultValue.taskRunUUID.UUIDString) print("Survey started at : (taskResultValue.startDate!) Ended at : (taskResultValue.endDate!)") //2 if let instStepResult = taskResultValue.stepResultForStepIdentifier("Instruction Step") { print("Instruction Step started at : (instStepResult.startDate!) Ended at : (instStepResult.endDate!)") } //3 if let compStepResult = taskResultValue.stepResultForStepIdentifier("Completion Step") { print("Completion Step started at : (compStepResult.startDate!) Ended at : (compStepResult.endDate!)") } } } The explanation of the preceding code is given in the following: As mentioned at the beginning, each task run is associated with a UUID. This UUID is available in the taskRunUUID property, which is printed in the first line. The second line prints the start and end date of the task. These are useful user analytics data with regards to how much time the user took to finish the survey. Obtains the ORKStepResult object corresponding to the instruction step using the stepResultForStepIdentifier method of the ORKTaskResult object. Prints the start and end date of the step result, which shows the amount of time for which the instruction step was shown before the user pressed the Get Started or Cancel buttons. Note that, as mentioned earlier, ORKInstructionStep does not produce any results. Therefore, the results property of the ORKStepResult object will be nil. You can use a breakpoint to stop the execution at this line of code and verify it. Obtains the ORKStepResult object corresponding to the completion step. Similar to the instruction step, this prints the start and end date of the step. The preceding code produces screens as shown in the following image: After the Done button is pressed in the completion step, Xcode prints the output that is similar to the following: Task Run UUID : 0A343E5A-A5CD-4E7C-88C6-893E2B10E7F7 Survey started at : 2015-08-11 00:41:03 +0000     Ended at : 2015-08-11 00:41:07 +0000Instruction Step started at : 2015-08-11 00:41:03 +0000   Ended at : 2015-08-11 00:41:05 +0000Completion Step started at : 2015-08-11 00:41:05 +0000   Ended at : 2015-08-11 00:41:07 +0000 Question step Question steps make up the body of a survey. ResearchKit supports question steps with various answer types such as boolean (Yes or No), numeric input, date selection, and so on. Let's first create a question step with the simplest boolean answer type by inserting the following line of code in showSurvey(): let question1 = ORKQuestionStep(identifier: "question 1", title: "Have you ever been diagnosed with Softwareitis?", answer: ORKAnswerFormat.booleanAnswerFormat()) The preceding code creates a ORKQuestionStep object with identifier question 1, title with the question, and an ORKBooleanAnswerFormat object created using the booleanAnswerFormat() class method of ORKAnswerFormat. The answer type for a question is determined by the type of the ORKAnswerFormat object that is passed in the answer parameter. The ORKAnswerFormat has several subclasses such as ORKBooleanAnswerFormat, ORKNumericAnswerFormat, and so on. Here, we are using ORKBooleanAnswerFormat. Don't forget to insert the created question step in the ORKOrderedTask steps parameter by updating the following line: let task = ORKOrderedTask(identifier: "first survey", steps: [instStep, question1, completionStep]) When you run the preceding changes in Xcode and start the survey, you will see the question step with the Yes or No options. We have now successfully added a boolean question step to our survey, as shown in the following image: Now, its time to process the results of this question step. The result is produced in an ORKBooleanQuestionResult object. Insert the following lines of code in processSurveyResults(): //1 if let question1Result = taskResultValue.stepResultForStepIdentifier("question 1")?.results?.first as? ORKBooleanQuestionResult { //2 if question1Result.booleanAnswer != nil { let answerString = question1Result.booleanAnswer!.boolValue ? "Yes" : "No" print("Answer to question 1 is (answerString)") } else { print("question 1 was skipped") } } The explanation of the preceding code is as follows: Obtains the ORKBooleanQuestionResult object by first obtaining the step result using the stepResultForStepIdentifier method, accessing its results property, and finally obtaining the only ORKBooleanQuestionResult object available in the results array. The booleanAnswer property of ORKBooleanQuestionResult contains the user's answer. We will print the answer if booleanAnswer is non-nil. If booleanAnswer is nil, it indicates that the user has skipped answering the question by pressing the Skip this question button. You can disable the skipping-of-a-question step by setting its optional property to false. We can add the numeric and scale type question steps using the following lines of code in showSurvey(): //1 let question2 = ORKQuestionStep(identifier: "question 2", title: "How many apps do you download per week?", answer: ORKAnswerFormat.integerAnswerFormatWithUnit("Apps per week")) //2 let answerFormat3 = ORKNumericAnswerFormat.scaleAnswerFormatWithMaximumValue(10, minimumValue: 0, defaultValue: 5, step: 1, vertical: false, maximumValueDescription: nil, minimumValueDescription: nil) let question3 = ORKQuestionStep(identifier: "question 3", title: "How many apps do you download per week (range)?", answer: answerFormat3) The explanation of the preceding code is as follows: Creates ORKQuestionStep with the ORKNumericAnswerFormat object, created using the integerAnswerFormatWithUnit method with Apps per week as the unit. Feel free to refer to the ORKNumericAnswerFormat documentation for decimal answer format and other validation options that you can use. First creates ORKScaleAnswerFormat with minimum and maximum values and step. Note that the number of step increments required to go from minimumValue to maximumValue cannot exceed 10. For example, maximum value of 100 and minimum value of 0 with a step of 1 is not valid and ResearchKit will raise an exception. The step needs to be at least 10. In the second line, ORKScaleAnswerFormat is fed in the ORKQuestionStep object. The following lines in processSurveyResults() process the results from the number and the scale questions: //1 if let question2Result = taskResultValue.stepResultForStepIdentifier("question 2")?.results?.first as? ORKNumericQuestionResult { if question2Result.numericAnswer != nil { print("Answer to question 2 is (question2Result.numericAnswer!)") } else { print("question 2 was skipped") } } //2 if let question3Result = taskResultValue.stepResultForStepIdentifier("question 3")?.results?.first as? ORKScaleQuestionResult { if question3Result.scaleAnswer != nil { print("Answer to question 3 is (question3Result.scaleAnswer!)") } else { print("question 3 was skipped") } } The explanation of the preceding code is as follows: Question step with ORKNumericAnswerFormat generates the result with the ORKNumericQuestionResult object. The numericAnswer property of ORKNumericQuestionResult contains the answer value if the question is not skipped by the user. The scaleAnswer property of ORKScaleQuestionResult contains the answer for a scale question. As you can see in the following image, the numeric type question generates a free form text field to enter the value, while scale type generates a slider: Let's look at a slightly complicated question type with ORKTextChoiceAnswerFormat. In order to use this answer format, we need to create the ORKTextChoice objects before hand. Each text choice object provides the necessary data to act as a choice in a single choice or multiple choice question. The following lines in showSurvey() create a single choice question with three options: //1 let textChoice1 = ORKTextChoice(text: "Games", detailText: nil, value: 1, exclusive: false) let textChoice2 = ORKTextChoice(text: "Lifestyle", detailText: nil, value: 2, exclusive: false) let textChoice3 = ORKTextChoice(text: "Utility", detailText: nil, value: 3, exclusive: false) //2 let answerFormat4 = ORKNumericAnswerFormat.choiceAnswerFormatWithStyle(ORKChoiceAnswerStyle.SingleChoice, textChoices: [textChoice1, textChoice2, textChoice3]) let question4 = ORKQuestionStep(identifier: "question 4", title: "Which category of apps do you download the most?", answer: answerFormat4) The explanation of the preceding code is as follows: Creates text choice objects with text and value. When a choice is selected, the object in the value property is returned in the corresponding ORKChoiceQuestionResult object. The exclusive property is used in multiple choice questions context. Refer to the documentation for its use. First, creates an ORKChoiceAnswerFormat object with the text choices that were previously created and specifies a single choice type using the ORKChoiceAnswerStyle enum. You can easily change this question to multiple choice question by changing the ORKChoiceAnswerStyle enum to multiple choice. Then, an ORKQuestionStep object is created using the answer format object. Processing the results from a single or multiple choice question is shown in the following. Needless to say, this code goes in the processSurveyResults() method: //1 if let question4Result = taskResultValue.stepResultForStepIdentifier("question 4")?.results?.first as? ORKChoiceQuestionResult { //2 if question4Result.choiceAnswers != nil { print("Answer to question 4 is (question4Result.choiceAnswers!)") } else { print("question 4 was skipped") } } The explanation of the preceding code is as follows: The result for a single or multiple choice question is returned in an ORKChoiceQuestionResult object. The choiceAnswers property holds the array of values for the chosen options. The following image shows the generated choice question UI for the preceding code: There are several other question types, which operate in a very similar manner like the ones we discussed so far. You can find them in the documentations of ORKAnswerFormat and ORKResult classes. The Softwareitis project has implementation of two additional types: date format and time interval format. Using custom tasks, you can create surveys that can skip the display of certain questions based on the answers that the users have provided so far. For example, in a smoking habits survey, if the user chooses "I do not smoke" option, then the ability to not display the "How many cigarettes per day?" question. Form step A form step allows you to combine several related questions in a single scrollable page and reduces the number of the Next button taps for the user. The ORKFormStep object is used to create the form step. The questions in the form are represented using the ORKFormItem objects. The ORKFormItem is similar to ORKQuestionStep, in which it takes the same parameters (title and answer format). Let's create a new survey with a form step by creating a form.swift extension file and adding the form entry to the rows array in TableViewController.swift, as shown in the following: func setupTableViewRows() { rows += [ ["Survey" : (didSelectRowMethod: self.showSurvey, processResultsMethod: self.processSurveyResults)], //1 ["Form" : (didSelectRowMethod: self.showForm, processResultsMethod: self.processFormResults)] ] } The explanation of the preceding code is as follows: The "Form" entry added to the rows array to create a new form survey with the showForm() method to show the form survey and the processFormResults() method to process the results from the form. The following code shows the showForm() method in Form.swift file: func showForm() { //1 let instStep = ORKInstructionStep(identifier: "Instruction Step") instStep.title = "Softwareitis Form Type Survey" instStep.detailText = "This survey demonstrates a form type step." //2 let question1 = ORKFormItem(identifier: "question 1", text: "Have you ever been diagnosed with Softwareitis?", answerFormat: ORKAnswerFormat.booleanAnswerFormat()) let question2 = ORKFormItem(identifier: "question 2", text: "How many apps do you download per week?", answerFormat: ORKAnswerFormat.integerAnswerFormatWithUnit("Apps per week")) //3 let formStep = ORKFormStep(identifier: "form step", title: "Softwareitis Survey", text: nil) formStep.formItems = [question1, question2] //1 let completionStep = ORKCompletionStep(identifier: "Completion Step") completionStep.title = "Thank you for taking this survey!" //4 let task = ORKOrderedTask(identifier: "survey with form", steps: [instStep, formStep, completionStep]) let taskViewController = ORKTaskViewController(task: task, taskRunUUID: nil) taskViewController.delegate = self presentViewController(taskViewController, animated: true, completion: nil) } The explanation of the preceding code is as follows: Creates an instruction and a completion step, similar to the earlier survey. Creates two ORKFormItem objects using the questions from the earlier survey. Notice the similarity with the ORKQuestionStep constructors. Creates ORKFormStep object with an identifier form step and sets the formItems property of the ORKFormStep object with the ORKFormItem objects that are created earlier. Creates an ordered task using the instruction, form, and completion steps and presents it to the user using a new ORKTaskViewController object. The results are processed using the following processFormResults() method: func processFormResults(taskResult: ORKTaskResult?) { if let taskResultValue = taskResult { //1 if let formStepResult = taskResultValue.stepResultForStepIdentifier("form step"), formItemResults = formStepResult.results { //2 for result in formItemResults { //3 switch result { case let booleanResult as ORKBooleanQuestionResult: if booleanResult.booleanAnswer != nil { let answerString = booleanResult.booleanAnswer!.boolValue ? "Yes" : "No" print("Answer to (booleanResult.identifier) is (answerString)") } else { print("(booleanResult.identifier) was skipped") } case let numericResult as ORKNumericQuestionResult: if numericResult.numericAnswer != nil { print("Answer to (numericResult.identifier) is (numericResult.numericAnswer!)") } else { print("(numericResult.identifier) was skipped") } default: break } } } } } The explanation of the preceding code is as follows: Obtains the ORKStepResult object of the form step and unwraps the form item results from the results property. Iterates through each of the formItemResults, each of which will be the result for a question in the form. The switch statement detects the different types of question results and accesses the appropriate property that contains the answer. The following image shows the form step: Considerations for real world surveys Many clinical research studies that are conducted using a pen and paper tend to have well established surveys. When you try to convert these surveys to ResearchKit, they may not convert perfectly. Some questions and answer choices may have to be reworded so that they can fit on a phone screen. You are advised to work closely with the clinical researchers so that the changes in the surveys still produce comparable results with their pen and paper counterparts. Another aspect to consider is to eliminate some of the survey questions if the answers can be found elsewhere in the user's device. For example, age, blood type, and so on, can be obtained from HealthKit if the user has already set them. This will help in improving the user experience of your app. Summary Here we have learned to build surveys using Xcode. Resources for Article: Further resources on this subject: Signing up to be an iOS developer[article] Code Sharing Between iOS and Android[article] Creating a New iOS Social Project[article]
Read more
  • 0
  • 0
  • 16980

article-image-creating-mutable-and-immutable-classes-swift
Packt
20 Jan 2016
8 min read
Save for later

Creating Mutable and Immutable Classes in Swift

Packt
20 Jan 2016
8 min read
In this article by Gastón Hillar, author of the book Object-Oriented Programming with Swift, we will learn how to create mutable and immutable classes in Swift. (For more resources related to this topic, see here.) Creating mutable classes So far, we worked with different type of properties. When we declare stored instance properties with the var keyword, we create a mutable instance property, which means that we can change their values for each new instance we create. When we create an instance of a class that defines many public-stored properties, we create a mutable object, which is an object that can change its state. For example, let's think about a class named MutableVector3D that represents a mutable 3D vector with three public-stored properties: x, y, and z. We can create a new MutableVector3D instance and initialize the x, y, and z attributes. Then, we can call the sum method with the delta values for x, y, and z as arguments. The delta values specify the difference between the existing and new or desired value. So, for example, if we specify a positive value of 30 in the deltaX parameter, it means we want to add 30 to the X value. The following lines declare the MutableVector3D class that represents the mutable version of a 3D vector in Swift: public class MutableVector3D { public var x: Float public var y: Float public var z: Float init(x: Float, y: Float, z: Float) { self.x = x self.y = y self.z = z } public func sum(deltaX: Float, deltaY: Float, deltaZ: Float) { x += deltaX y += deltaY z += deltaZ } public func printValues() { print("X: (self.x), Y: (self.y), Z: (self.z))") } } Note that the declaration of the sum instance method uses the func keyword, specifies the arguments with their types enclosed in parentheses, and then declares the body for the method enclosed in curly brackets. The public sum instance method receives the delta values for x, y, and z (deltaX, deltaY and deltaZ) and mutates the object, which means that the method changes the values of x, y, and z. The public printValues method prints the values of the three instance-stored properties: x, y, and z. The following lines create a new MutableVector3D instance method called myMutableVector, initialized with the values for the x, y, and z properties. Then, the code calls the sum method with the delta values for x, y, and z as arguments and finally calls the printValues method to check the new values after the object mutated with the call to the sum method: var myMutableVector = MutableVector3D(x: 30, y: 50, z: 70) myMutableVector.sum(20, deltaY: 30, deltaZ: 15) myMutableVector.printValues() The results of the execution in the Playground are shown in the following screenshot: The initial values for the myMutableVector fields are 30 for x, 50 for y, and 70 for z. The sum method changes the values of the three instance-stored properties; therefore, the object state mutates as follows: myMutableVector.X mutates from 30 to 30 + 20 = 50 myMutableVector.Y mutates from 50 to 50 + 30 = 80 myMutableVector.Z mutates from 70 to 70 + 15 = 85 The values for the myMutableVector fields after the call to the sum method are 50 for x, 80 for y, and 85 for z. We can say that the method mutated the object's state; therefore, myMutableVector is a mutable object and an instance of a mutable class. It's a very common requirement to generate a 3D vector with all the values initialized to 0—that is, x = 0, y = 0, and z = 0. A 3D vector with these values is known as an origin vector. We can add a type method to the MutableVector3D class named originVector to generate a new instance of the class initialized with all the values in 0. Type methods are also known as class or static methods in other object-oriented programming languages. It is necessary to add the class keyword before the func keyword to generate a type method instead of an instance. The following lines define the originVector type method: public class func originVector() -> MutableVector3D { return MutableVector3D(x: 0, y: 0, z: 0) } The preceding method returns a new instance of the MutableVector3D class with 0 as the initial value for all the three elements. The following lines call the originVector type method to generate a 3D vector, the sum method for the generated instance, and finally, the printValues method to check the values for the three elements on the Playground: var myMutableVector2 = MutableVector3D.originVector() myMutableVector2.sum(5, deltaY: 10, deltaZ: 15) myMutableVector2.printValues() The following screenshot shows the results of executing the preceding code in the Playground: Creating immutable classes Mutability is very important in object-oriented programming. In fact, whenever we expose mutable properties, we create a class that will generate mutable instances. However, sometimes a mutable object can become a problem and in certain situations, we want to avoid the objects to change their state. For example, when we work with concurrent code, an object that cannot change its state solves many concurrency problems and avoids potential bugs. For example, we can create an immutable version of the previous MutableVector3D class to represent an immutable 3D vector. The new ImmutableVector3D class has three immutable instance properties declared with the let keyword instead of the previously used var[SI1]  keyword: x, y, and z. We can create a new ImmutableVector3D instance and initialize the immutable instance properties. Then, we can call the sum method with the delta values for x, y, and z as arguments. The sum public instance method receives the delta values for x, y, and z (deltaX, deltaY, and deltaZ), and returns a new instance of the same class with the values of x, y, and z initialized with the results of the sum. The following lines show the code of the ImmutableVector3D class: public class ImmutableVector3D { public let x: Float public let y: Float public let z: Float init(x: Float, y: Float, z: Float) { self.x = x self.y = y self.z = z } public func sum(deltaX: Float, deltaY: Float, deltaZ: Float) -> ImmutableVector3D { return ImmutableVector3D(x: x + deltaX, y: y + deltaY, z: z + deltaZ) } public func printValues() { print("X: (self.x), Y: (self.y), Z: (self.z))") } public class func equalElementsVector(initialValue: Float) -> ImmutableVector3D { return ImmutableVector3D(x: initialValue, y: initialValue, z: initialValue) } public class func originVector() -> ImmutableVector3D { return equalElementsVector(0) } } In the new ImmutableVector3D class, the sum method returns a new instance of the ImmutableVector3D class—that is, the current class. In this case, the originVector type method returns the results of calling the equalElementsVector type method with 0 as an argument. The equalElementsVector type method receives an initialValue argument for all the elements of the 3D vector, creates an instance of the actual class, and initializes all the elements with the received unique value. The originVector type method demonstrates how we can call another type method within a type method. Note that both the type methods specify the returned type with -> followed by the type name (ImmutableVector3D) after the arguments enclosed in parentheses. The following line shows the declaration for the equalElementsVector type method with the specified return type: public class func equalElementsVector(initialValue: Float) -> ImmutableVector3D { The following lines call the originVector type method to generate an immutable 3D vector named vector0 and the sum method for the generated instance and save the returned instance in the new vector1 variable. The call to the sum method generates a new instance and doesn't mutate the existing object: var vector0 = ImmutableVector3D.originVector() var vector1 = vector0.sum(5, deltaX: 10, deltaY: 15) vector1.printValues() The code doesn't allow the users of the ImmutableVector3D class to change the values of the x, y, and z properties declared with the let keyword. The code doesn't compile if you try to assign a new value to any of these properties after they were initialized. Thus, we can say that the ImmutableVector3D class is 100 percent immutable. Finally, the code calls the printValues method for the returned instance (vector1) to check the values for the three elements on the Playground, as shown in the following screenshot: The immutable version adds an overhead compared with the mutable version because it is necessary to create a new instance of the class as a result of calling the sum method. The previously analyzed mutable version just changed the values for the attributes, and it wasn't necessary to generate a new instance. Obviously, the immutable version has both a memory and performance overhead. However, when we work with concurrent code, it makes sense to pay for the extra overhead to avoid potential issues caused by mutable objects. We just have to make sure we analyze the advantages and tradeoffs in order to decide which is the most convenient way of coding our specific classes. Summary In this article, we learned how to create mutable and immutable classes in Swift. Resources for Article: Further resources on this subject: Exploring Swift[article] The Swift Programming Language[article] Playing with Swift[article]
Read more
  • 0
  • 0
  • 16618

article-image-extra-extra-collection-and-closure-changes-rock
Packt
28 Sep 2016
19 min read
Save for later

Extra, Extra Collection, and Closure Changes that Rock!

Packt
28 Sep 2016
19 min read
In this article by Keith Elliott, author of, Swift 3 New Features , we are focusing on collection and closure changes in Swift 3. There are several nice additions that will make working with collections even more fun. We will also explore some of the confusing side effects of creating closures in Swift 2.2 and how those have been fixed in Swift 3. (For more resources related to this topic, see here.) Collection and sequence type changes Let’s begin our discussion with Swift 3 changes to Collection and Sequence types. Some of the changes are subtle and others are bound to require a decent amount of refactoring to your custom implementations. Swift provides three main collection types for warehousing your values: arrays, dictionaries, and sets. Arrays allow you to store values in an ordered list. Dictionaries provide unordered the key-value storage for your collections. Finally, sets provide an unordered list of unique values (that is, no duplicates allowed). Lazy FlatMap for sequence of optionals [SE-0008] Arrays, sets, and dictionaries are implemented as generic types in Swift. They each implement the new Collection protocol, which implements the Sequence protocol. Along this path from top-level type to Sequence protocol, you will find various other protocols that are also implemented in this inheritance chain. For our discussion on flatMap and lazy flatMap changes, I want to focus in on Sequences. Sequences contain a group of values that allow the user to visit each value one at a time. In Swift, you might consider using a for-in loop to iterate through your collection. The Sequence protocol provides implementations of many operations that you might want to perform on a list using sequential access, all of which you could override when you adopt the protocol in your custom collections. One such operation is the flatMap function, which returns an array containing the flattened (or rather concatenated) values, resulting from a transforming operation applied to each element of the sequence. let scores = [0, 5, 6, 8, 9] .flatMap{ [$0, $0 * 2] } print(scores) // [0, 0, 5, 10, 6, 12, 8, 16, 9, 18]   In our preceding example, we take a list of scores and call flatMap with our transforming closure. Each value is converted into a sequence containing the original value and a doubled value. Once the transforming operations are complete, the flatMap method flattens the intermediate sequences into a single sequence. We can also use the flatMap method with Sequences that contain optional values to accomplish a similar outcome. This time we are omitting values from the sequence we flatten by return nil on the transformation. let oddSquared = [1, 2, 3, 4, 5, 10].flatMap { n in n % 2 == 1 ? n*n : nil } print(oddSquared) // [1, 9, 25] The previous two examples were fairly basic transformations on small sets of values. In a more complex situation, the collections that you need to work with might be very large with expensive transformation operations. Under those parameters, you would not want to perform the flatMap operation or any other costly operation until it was absolutely needed. Luckily, in Swift, we have lazy operations for this very use case. Sequences contain a lazy property that returns a LazySequence that can perform lazy operations on Sequence methods. Using our first example, we can obtain a lazy sequence and call flatMap to get a lazy implementation. Only in the lazy scenario, the operation isn’t completed until scores is used sometime later in code. let scores = [0, 5, 6, 8, 9] .lazy .flatMap{ [$0, $0 * 2] } // lazy assignment has not executed for score in scores{ print(score) } The lazy operation works, as we would expect in our preceding test. However, when we use the lazy form of flatMap with our second example that contains optionals, our flatMap executes immediately in Swift 2. While we expected oddSquared variable to hold a ready to run flatMap, delayed until we need it, we instead received an implementation that was identical to the non-lazy version. let oddSquared = [1, 2, 3, 4, 5, 10] .lazy // lazy assignment but has not executed .flatMap { n in n % 2 == 1 ? n*n : nil } for odd in oddSquared{ print(odd) } Essentially, this was a bug in Swift that has been fixed in Swift 3. You can read the proposal at the following link https://github.com/apple/swift-evolution/blob/master/proposals/0008-lazy-flatmap-for-optionals.md Adding the first(where:) method to sequence A common task for working with collections is to find the first element that matches a condition. An example would be to ask for the first student in an array of students whose test scores contain a 100. You can accomplish this using a predicate to return the filtered sequence that matched the criteria and then just give back the first student in the sequence. However, it would be much easier to just call a single method that could return the item without the two-step approach. This functionality was missing in Swift 2, but was voted in by the community and has been added for this release. In Swift 3, there is a now an extension method on the Sequence protocol to implement first(where:). ["Jack", "Roger", "Rachel", "Joey"].first { (name) -> Bool in name.contains("Ro") } // =>returns Roger This first(where:) extension is a nice addition to the language because it ensures that a simple and common task is actually easy to perform in Swift. You can read the proposal at the following link https://github.com/apple/swift-evolution/blob/master/proposals/0032-sequencetype-find.md. Add sequence(first: next:) and sequence(state: next:) public func sequence<T>(first: T, next: @escaping (T) -> T?) -> UnfoldSequence<T, (T?, Bool)> public func sequence<T, State>(state: State, next: @escaping (inout State) -> T?) -> UnfoldSequence<T, State> public struct UnfoldSequence<Element, State> : Sequence, IteratorProtocol These two functions were added as replacements to the C-style for loops that were removed in Swift 3 and to serve as a compliment to the global reduce function that already exists in Swift 2. What’s interesting about the additions is that each function has the capability of generating and working with infinite sized sequences. Let’s examine the first sequence function to get a better understanding of how it works. /// - Parameter first: The first element to be returned from the sequence. /// - Parameter next: A closure that accepts the previous sequence element and /// returns the next element. /// - Returns: A sequence that starts with `first` and continues with every /// value returned by passing the previous element to `next`. /// func sequence<T>(first: T, next: @escaping (T) -> T?) -> UnfoldSequence<T, (T?, Bool)> The first sequence method returns a sequence that is created from repeated invocations of the next parameter, which holds a closure that will be lazily executed. The return value is an UnfoldSequence that contains the first parameter passed to the sequence method plus the result of applying the next closure on the previous value. The sequence is finite if next eventually returns nil and is infinite if next never returns nil. let mysequence = sequence(first: 1.1) { $0 < 2 ? $0 + 0.1 : nil } for x in mysequence{ print (x) } // 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0 In the preceding example, we create and assign our sequence using the trailing closure form of sequence(first: next:). Our finite sequence will begin with 1.1 and will call next repeatedly until our next result is greater than 2 at which case next will return nil. We could easily convert this to an infinite sequence by removing our condition that our previous value must not be greater than 2. /// - Parameter state: The initial state that will be passed to the closure. /// - Parameter next: A closure that accepts an `inout` state and returns the /// next element of the sequence. /// - Returns: A sequence that yields each successive value from `next`. /// public func sequence<T, State>(state: State, next: (inout State) -> T?) -> UnfoldSequence<T, State> The second sequence function maintains mutable state that is passed to all lazy calls of next to create and return a sequence. This version of the sequence function uses a passed in closure that allows you to update the mutable state each time the next called. As was the case with our first sequence function, a finite sequence ends when next returns a nil. You can turn an finite sequence into an infinite one by never returning nil when next is called. Let’s create an example of how this version of the sequence method might be used. Traversing a hierarchy of views with nested views or any list of nested types is a perfect task for using the second version of the sequence function. Let’s create a an Item class that has two properties. A name property and an optional parent property to keep track of the item’s owner. The ultimate owner will not have a parent, meaning the parent property will be nil. class Item{ var parent: Item? var name: String = "" } Next, we create a parent and two nested children items. Child1 parent will be the parent item and child2 parent will be child1. let parent = Item() parent.name = "parent" let child1 = Item() child1.name = "child1" child1.parent = parent let child2 = Item() child2.name = "child2" child2.parent = child1 Now, it’s time to create our sequence. The sequence needs two parameters from us: a state parameter and a next closure. I made the state an Item with an initial value of child2. The reason for this is because I want to start at the lowest leaf of my tree and traverse to the ultimate parent. Our example only has three levels, but you could have lots of levels in a more complex example. As for the next parameter, I’m using a closure expression that expects a mutable Item as its state. My closure will also return an optional Item. In the body of our closure, I use our current Item (mutable state parameter) to access the item’s parent. I also updated the state and return the parent. let itemSeq = sequence(state: child2, next: { (next: inout Item)->Item? in let parent = next.parent next = parent != nil ? parent! : next return parent }) for item in itemSeq{ print("name: (item.name)") } There are some gotchas here that I want to address so that you will better understand how to define your own next closure for this sequence method. The state parameter could really be anything you want it to be. It’s for your benefit in helping you determine the next element of the sequence and to give you relevant information about where you are in the sequence. One idea to improve our example above would be to track how many levels of nesting we have. We could have made our state a tuple that contained an integer counter for the nesting level along with the current item. The next closure needs to be expanded to show the signature. Because of Swift’s expressiveness and conciseness, when it comes to closures, you might be tempted to convert the next closure into a shorter form and omit the signature. Do not do this unless your next closure is extremely simple and you are positive that the compiler will be able to infer your types. Your code will be harder to maintain when you use the short closure format, and you won’t get extra points for style when someone else inherits it. Don’t forget to update your state parameter in the body of your closure. This really is your best chance to know where you are in your sequence. Forgetting to update the state will probably cause you to get unexpected results when you try to step through your sequence. Make a clear decision ahead of the time about whether you are creating a finite or infinite sequence. This decision is evident in how you return from your next closure. An infinite sequence is not bad to have when you are expecting it. However, if you iterate over this sequence using a for-in loop, you could get more than you bargained for, provided you were assuming this loop would end. A new Model for Collections and Indices [SE-0065]Swift 3 introduces a new model for collections that moves the responsibility of the index traversal from the index to the collection itself. To make this a reality for collections, the Swift team introduced four areas of change: The Index property of a collection can be any type that implements the Comparable protocol Swift removes any distinction between intervals and ranges, leaving just ranges Private index traversal methods are now public Changes to ranges make closed ranges work without the potential for errors You can read the proposal at the following link https://github.com/apple/swift-evolution/blob/master/proposals/0065-collections-move-indices.md. Introducing the collection protocol In Swift 3, Foundation collection types such as Arrays, Sets, and Dictionaries are generic types that implement the newly created Collection protocol. This change was needed in order to support traversal on the collection. If you want to create custom collections of your own, you will need to understand the Collection protocol and where it lives in the collection protocol hierarchy. We are going to cover the important aspects to the new collection model to ease you transition and to get you ready to create custom collection types of your own. The Collection protocol builds on the Sequence protocol to provide methods for accessing specific elements when using a collection. For example, you can use a collection’s index(_:offsetBy:) method to return an index that is a specified distance away from the reference index. let numbers = [10, 20, 30, 40, 50, 60] let twoAheadIndex = numbers.index(numbers.startIndex, offsetBy: 2) print(numbers[twoAheadIndex]) //=> 30 In the preceding example, we create the twoAheadIndex constant to hold the position in our numbers collection that is two positions away from our starting index. We simply use this index to retrieve the value from our collection using subscript notation. Conforming to the Collection Protocol If you would like to create your own custom collections, you need to adopt the Collection protocol by declaring startIndex and endIndex properties, a subscript to support access to your elements, and the index(after: ) method to facilitate traversing your collection’s indices. When we are migrating existing types over to Swift 3, the migrator has some known issues with converting custom collections. It’s likely that you can easily resolve the compiler issues by checking the imported types for conformance to the Collection protocol. Additionally, you need to conform to the Sequence and IndexableBase protocols as the Collection protocol adopts them both. public protocol Collection : Indexable, Sequence { … } A simple custom collection could look like the following example. Note that I have defined my Index type to be an Int. In Swift 3, you define the Index to be any type that implements the Comparable protocol. struct MyCollection<T>: Collection{ typealias Index = Int var startIndex: Index var endIndex: Index var _collection: [T] subscript(position: Index) -> T{ return _collection[position] } func index(after i: Index) -> Index { return i + 1 } init(){ startIndex = 0 endIndex = 0 _collection = [] } mutating func add(item: T){ _collection.append(item) } } var myCollection: MyCollection<String> = MyCollection() myCollection.add(item: "Harry") myCollection.add(item: "William") myCollection[0] The Collection protocol has default implementations for most of its methods, the Sequence protocols methods, and the IndexableBase protocols methods. This means you are only required to provide a few things of your own. You can, however, implement as many of the other methods as make sense for your collection. New Range and Associated Indices Types Swift 2’s Range<T>, ClosedInterval<T>, and OpenInterval<T> are going away in Swift 3. These types are being replaced with four new types. Two of the new range types support general ranges with bounds that implement the Comparable protocol: Range<T> and ClosedRange<T>. The other two range types conform to RandomAccessCollection. These types support ranges whose bounds implement the Strideable protocol. Last, ranges are no longer iterable since ranges are now represented as a pair of indices. To keep legacy code working, the Swift team introduced an associated indices type, which is iterable. In addition, three generic types were created to provide a default indices type for each type of collection traversal category. The generics are DefaultIndices<C>, DefaultBidirectionalIndices<C>, and DefaultRandomAccessIndices<C>; each stores its underlying collection for traversal. Quick Takeaways I covered a lot of stuff in a just a few pages on collection types in Swift 3. Here are the highlights to keep in mind about the collections and indices. Collections types (built-in and custom) implement the Collection protocol. Iterating over collections has moved to the collection—the index no longer has that ability. You can create your own collections by adopting the Collection protocol. You need to implement: startIndex and endIndex properties The subscript method to support access to your elements The index(after: ) method to facilitate traversing your collection’s indices Closure changes for Swift 3 A closure in Swift is a block of code that can be used in a function call as a parameter or assigned to a variable to execute their functionality at a later time. Closures are a core feature to Swift and are familiar to developers that are new to Swift as they remind you of lambda functions in other programming languages. For Swift 3, there were two notable changes that I will highlight in this section. The first change deals with inout captures. The second is a change that makes non-escaping closures the default. Limiting inout Capture of @noescape Closures]In Swift 2, capturing inout parameters in an escaping closure was difficult for developers to understand. Closures are used everywhere in Swift especially in the standard library and with collections. Some closures are assigned to variables and then passed to functions as arguments. If the function that contains the closure parameter returns from its call and the passed in closure is used later, then you have an escaping closure. On the other hand, if the closure is only used within the function to which it is passed and not used later, then you have a nonescaping closure. The distinction is important here because of the mutating nature of inout parameters. When we pass an inout parameter to a closure, there is a possibility that we will not get the result we expect due to how the inout parameter is stored. The inout parameter is captured as a shadow copy and is only written back to the original if the value changes. This works fine most of the time. However, when the closure is called at a later time (that is, when it escapes), we don’t get the result we expect. Our shadow copy can’t write back to the original. Let’s look at an example. var seed = 10 let simpleAdderClosure = { (inout seed: Int)->Int in seed += 1 return seed * 10 } var result = simpleAdderClosure(&seed) //=> 110 print(seed) // => 11 In the preceding example, we get what we expect. We created a closure to increment our passed in inout parameter and then return the new parameter multiplied by 10. When we check the value of seed after the closure is called, we see that the value has increased to 11. In our second example, we modify our closure to return a function instead of just an Int value. We move our logic to the closure that we are defining as our return value. let modifiedClosure = { (inout seed: Int)-> (Int)->Int in return { (Int)-> Int in seed += 1 return seed * 10 } } print(seed) //=> 11 var resultFn = modifiedClosure(&seed) var result = resultFn(1) print(seed) // => 11 This time when we execute the modifiedClosure with our seed value, we get a function as the result. After executing this intermediate function, we check our seed value and see that the value is unchanged; even though, we are still incrementing the seed value. These two slight differences in syntax when using inout parameters generate different results. Without knowledge of how shadow copy works, it would be hard understand the difference in results. Ultimately, this is just another situation where you receive more harm than good by allowing this feature to remain in the language. You can read the proposal at the following link https://github.com/apple/swift-evolution/blob/master/proposals/0035-limit-inout-capture.md. Resolution In Swift 3, the compiler now limits inout parameter usage with closures to non-escaping (@noescape). You will receive an error if the compiler detects that your closure escapes when it contains inout parameters. Making non-escaping closures the default [SE-0103] You can read the proposal at https://github.com/apple/swift-evolution/blob/master/proposals/0103-make-noescape-default.md. In previous versions of Swift, the default behavior of function parameters whose type was a closure was to allow escaping. This made sense as most of the Objective-C blocks (closures in Swift) imported into Swift were escaping. The delegation pattern in Objective-C, as implemented as blocks, was composed of delegate blocks that escaped. So, why would the Swift team want to change the default to non-escaping as the default? The Swift team believes you can write better functional algorithms with non-escaping closures. An additional supporting factor is the change to require non-escaping closures when using inout parameters with the closure [SE-0035]. All things considered, this change will likely have little impact on your code. When the compiler detects that you are attempting to create an escaping closure, you will get an error warning that you are possibly creating an escaping closure. You can easily correct the error by adding @escaping or via the fixit that accompanies the error. In Swift 2.2: var callbacks:[String : ()->String] = [:] func myEscapingFunction(name:String, callback:()->String){ callbacks[name] = callback } myEscapingFunction("cb1", callback: {"just another cb"}) for cb in callbacks{ print("name: (cb.0) value: (cb.1())") } In Swift 3: var callbacks:[String : ()->String] = [:] func myEscapingFunction(name:String, callback: @escaping ()->String){ callbacks[name] = callback } myEscapingFunction(name:"cb1", callback: {"just another cb"}) for cb in callbacks{ print("name: (cb.0) value: (cb.1())") } Summary In this article, we covered changes to collections and closures. You learned about the new Collection protocol that forms the base of the new collection model and how to adopt the protocol in our own custom collections. The new collection model made a significant change in moving collection traversal from the index to the collection itself. The new collection model changes are necessary in order to support Objective-C interactivity and to provide a mechanism to iterate over the collections items using the collection itself. As for closures, we also explored the motivation for the language moving to non-escaping closures as the default. You also learned how to properly use inout parameters with closures in Swift 3. Resources for Article: Further resources on this subject: Introducing the Swift Programming Language [article] Concurrency and Parallelism with Swift 2 [article] Exploring Swift [article]
Read more
  • 0
  • 0
  • 14739

article-image-integrating-objective-c
Packt
01 Apr 2016
11 min read
Save for later

Integrating with Objective-C

Packt
01 Apr 2016
11 min read
In this article written by Kyle Begeman author of the book Swift 2 Cookbook, we will cover the following recipes: Porting your code from one language to another Replacing the user interface classes Upgrading the app delegate Introduction Swift 2 is out, and we can see that it is going to replace Objective-C on iOS development sooner or later, however how should you migrate your Objective-C app? Is it necessary to rewrite everything again? Of course you don't have to rewrite a whole application in Swift from scratch, you can gradually migrate it. Imagine a four years app developed by 10 developers, it would take a long time to be rewritten. Actually, you've already seen that some of the codes we've used in this book have some kind of "old Objective-C fashion". The reason is that not even Apple computers could migrate the whole Objective-C code into Swift. (For more resources related to this topic, see here.) Porting your code from one language to another In the previous recipe we learned how to add a new code into an existing Objective-C project, however you shouldn't only add new code but also, as far as possible, you should migrate your old code to the new Swift language. If you would like to keep your application core on Objective-C that's ok, but remember that new features are going to be added on Swift and it will be difficult keeping two languages on the same project. In this recipe we are going to port part of the code, which is written in Objective-C to Swift. Getting ready Make a copy of the previous recipe, if you are using any version control it's a good time for committing your changes. How to do it… Open the project and add a new file called Setup.swift, here we are going to add a new class with the same name (Setup): class Setup { class func generate() -> [Car]{ var result = [Car]() for distance in [1.2, 0.5, 5.0] { var car = Car() car.distance = Float(distance) result.append(car) } var car = Car() car.distance = 4 var van = Van() van.distance = 3.8 result += [car, van] return result } } Now that we have this car array generator we can call it on the viewDidLoad method replacing the previous code: - (void)viewDidLoad { [super viewDidLoad]; vehicles = [Setup generate]; [self->tableView reloadData]; } Again press play and check that the application is still working. How it works… The reason we had to create a class instead of creating a function is that you can only export to Objective-C classes, protocols, properties, and subscripts. Bear that in mind in case of developing with the two languages. If you would like to export a class to Objective-C you have two choices, the first one is inheriting from NSObject and the other one is adding the @objc attribute before your class, protocol, property, or subscript. If you paid attention, our method returns a Swift array but it was converted to an NSArray, but as you might know, they are different kinds of array. Firstly, because Swift arrays are mutable and NSArray are not, and the other reason is that their methods are different. Can we use NSArray in Swift? The answer is yes, but I would recommend avoiding it, imagine once finished migrating to Swift your code still follows the old way, it would be another migration. There's more… Migrating from Objective-C is something that you should do with care, don't try to change the whole application at once, remember that some Swift objects behave differently from Objective-C, for example, dictionaries in Swift have the key and the value types specified but in Objective-C they can be of any type. Replacing the user interface classes At this moment you know how to migrate the model part of an application, however in real life we also have to replace the graphical classes. Doing it is not complicated but it could be a bit full of details. Getting ready Continuing with the previous recipe, make a copy of it or just commit the changes you have and let's continue with our migration. How to do it… First create a new file called MainViewController.swift and start importing the UIKit: import UIKit The next step is creating a class called MainViewController, this class must inherit from UIViewController and implement the protocols UITableViewDataSource and UITableViewDelegate: class MainViewController:UIViewController,UITableViewDataSource, UITableViewDelegate {  Then, add the attributes we had in the previous view controller, keep the same name you have used before: private var vehicles = [Car]() @IBOutlet var tableView:UITableView! Next, we need to implement the methods, let's start with the table view data source methods: func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{ return vehicles.count } func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{ var cell:UITableViewCell? = self.tableView.dequeueReusableCellWithIdentifier ("vehiclecell") if cell == nil { cell = UITableViewCell(style: .Subtitle, reuseIdentifier: "vehiclecell") } var currentCar = self.vehicles[indexPath.row] cell!.textLabel?.numberOfLines = 1 cell!.textLabel?.text = "Distance (currentCar.distance * 1000) meters" var detailText = "Pax: (currentCar.pax) Fare: (currentCar.fare)" if currentCar is Van{ detailText += ", Volume: ( (currentCar as Van).capacity)" } cell!.detailTextLabel?.text = detailText cell!.imageView?.image = currentCar.image return cell! } Pay attention that this conversion is not 100% equivalent, the fare for example isn't going to be shown with two digits of precision, there is an explanation later of why we are not going to fix this now.  The next step is adding the event, in this case we have to do the action done when the user selects a car: func tableView(tableView: UITableView, willSelectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath? { var currentCar = self.vehicles[indexPath.row] var time = currentCar.distance / 50.0 * 60.0 UIAlertView(title: "Car booked", message: "The car will arrive in (time) minutes", delegate: nil, cancelButtonTitle: "OK").show() return indexPath } As you can see, we need only do one more step to complete our code, in this case it's the view didLoad. Pay attention that another difference from Objective-C and Swift is that in Swift you have to specify that you are overloading an existing method: override func viewDidLoad() { super.viewDidLoad() vehicles = Setup.generate() self.tableView.reloadData() } } // end of class Our code is complete, but of course our application is still using the old code. To complete this operation, click on the storyboard, if the document outline isn't being displayed, click on the Editor menu and then on Show Document Outline: Now that you can see the document outline, click on View Controller that appears with a yellow circle with a square inside: Then on the right-hand side, click on the identity inspector, next go to the custom class and change the value of the class from ViewController to MainViewController. After that, press play and check that your application is running, select a car and check that it is working. Be sure that it is working with your new Swift class by paying attention on the fare value, which in this case isn't shown with two digits of precision. Is everything done? I would say no, it's a good time to commit your changes. Lastly, delete the original Objective-C files, because you won't need them anymore. How it works… As you can see, it's not so hard replacing an old view controller with a Swift one, the first thing you need to do is create a new view controller class with its protocols. Keep the same names you had on your old code for attributes and methods that are linked as IBActions, it will make the switch very straightforward otherwise you will have to link again. Bear in mind that you need to be sure that your changes are applied and that they are working, but sometimes it is a good idea to have something different, otherwise your application can be using the old Objective-C and you didn't realize it. Try to modernize our code using the Swift way instead of the old Objective-C style, for example, nowadays it's preferable using interpolation rather than using stringWithFormat. We also learned that you don't need to relink any action or outlet if you keep the same name. If you want to change the name of anything you might first keep its original name, test your app, and after that you can refactor it following the traditional factoring steps. Don't delete the original Objective-C files until you are sure that the equivalent Swift file is working on every functionality. There's more… This application had only one view controller, however applications usually have more than one view controller. In this case, the best way you can update them is one by one instead of all of them at the same time. Upgrading the app delegate As you know there is an object that controls the events of an application, which is called application delegate. Usually you shouldn't have much code here, but a few of them you might have. For example, you may deactivate the camera or the GPS requests when your application goes to the background and reactivate them when the app returns active. Certainly it is a good idea to update this file even if you don't have any new code on it, so it won't be a problem in the future. Getting ready If you are using the version control system, commit your changes from the last recipe or if you prefer just copy your application. How to do it… Open the previous application recipe and create a new Swift file called ApplicationDelegate.swift, then you can create a class with the same name. As in our previous class we didn't have any code on the application delegate, so we can differentiate it by printing on the log console. So add this traditional application delegate on your Swift file: class ApplicationDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { print("didFinishLaunchingWithOptions") return true } func applicationWillResignActive(application: UIApplication) { print("applicationWillResignActive") } func applicationDidEnterBackground(application: UIApplication) { print("applicationDidEnterBackground") } func applicationWillEnterForeground(application: UIApplication) { print("applicationWillEnterForeground") } func applicationDidBecomeActive(application: UIApplication) { print("applicationDidBecomeActive") } func applicationWillTerminate(application: UIApplication) { print("applicationWillTerminate") } } Now go to your project navigator and expand the Supporting Files group, after that click on the main.m file. In this file we are going to import the magic file, the Swift header file: #import "Chapter_8_Vehicles-Swift.h" After that we have to specify that the application delegate is the new class we have, so replace the AppDelegate class on the UIApplicationMain call with ApplicationDelegate. Your main function should be like this: int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([ApplicationDelegate class])); } } It's time to press play and check whether the application is working or not. Press the home button or the combination shift + command + H if you are using the simulator and again open your application. Have a look that you have some messages on your log console. Now that you are sure that your Swift code is working, remove the original app delegate and its importation on the main.m. Test your app just in case. You could consider that we had finished this part, but actually we still have another step to do: removing the main.m file. Now it is very easy, just click on the ApplicationDelegate.swift file and before the class declaration add the attribute @UIApplicationMain, then right click on the main.h and choose to delete it. Test it and your application is done. How it works… The application delegate class has always been specified at the starting of an application. In Objective-C, it follows the C start point, which is a function called main. In iOS, you can specify the class that you want to use as an application delegate. If you program for OS X the procedure is different, you have to go to your nib file and change its class name to the new one. Why did we have to change the main function and then eliminate it? The reason is that you should avoid massive changes, if something goes wrong you won't know the step where you failed, so probably you will have to rollback everything again. If you do your migration step by step ensuring that it is still working, it means that in case of finding an error, it will be easier to solve it. Avoid doing massive changes on your project, changing step by step will be easier to solve issues. There's more… In this recipe, we learned the last steps of how to migrate an app from Objective-C to Swift code, however we have to remember that programming is not only about applications, you can also have a framework. In the next recipe, we are going to learn how to create your own framework compatible with Swift and Objective-C. Summary This article shows you how Swift and Objective-C can live together and give you a step-by-step guide on how to migrate your Objective-C app to Swift. Resources for Article: Further resources on this subject: Concurrency and Parallelism with Swift 2 [article] Swift for Open Source Developers [article] Your First Swift 2 Project [article]
Read more
  • 0
  • 0
  • 14500
article-image-debugging
Packt
14 Jan 2016
11 min read
Save for later

Debugging

Packt
14 Jan 2016
11 min read
In this article by Brett Ohland and Jayant Varma, the authors of Xcode 7 Essentials (Second Edition), we learn about the debugging process, as the Grace Hopper had a remarkable career. She not only became a Rear Admiral in the U.S. Navy but also contributed to the field of computer science in many important ways during her lifetime. She was one of the first programmers on an early computer called Mark I during World War II. She invented the first compiler and was the head of a group that created the FLOW-MATIC language, which would later be extended to create the COBOL programming language. How does this relate to debugging? Well, in 1947, she was leading a team of engineers who were creating the successor of the Mark I computer (called Mark II) when the computer stopped working correctly. The culprit turned out to be a moth that had managed to fly into, and block the operation of, an important relay inside of the computer; she remarked that they had successfully debugged the system and went on to popularize the term. The moth and the log book page that it is attached to are on display in The Smithsonian Museum of American History in Washington D.C. While physical bugs in your systems are an astronomically rare occurrence, software bugs are extremely common. No developer sets out to write a piece of code that doesn't act as expected and crash, but bugs are inevitable. Luckily, Xcode has an assortment of tools and utilities to help you become a great detective and exterminator. In this article, we will cover the following topics: Breakpoints The LLDB console Debugging the view hierarchy Tooltips and a Quick Look (For more resources related to this topic, see here.) Breakpoints The typical development cycle of writing code, compiling, and then running your app on a device or in the simulator doesn't give you much insight into the internal state of the program. Clicking the stop button will, as the name suggests, stop the program and remove it from the memory. If your app crashes, or if you notice that a string is formatted incorrectly or the wrong photo is loaded into a view, you have no idea what code caused the issue. Surely, you could use the print statement in your code to output values on the console, but as your application involves more and more moving parts, this becomes unmanageable. A better option is to create breakpoints. A breakpoint is simply a point in your source code at which the execution of your program will pause and put your IDE into a debugging mode. While in this mode, you can inspect any objects that are in the memory, see a trace of the program's execution flow, and even step the program into or over instructions in your source code. Creating a breakpoint is simple. In the standard editor, there is a gutter that is shown to the immediate left of your code. Most often, there are line numbers in this area, and clicking on a line number will add a blue arrow to that line. That is a breakpoint. If you don't see the line numbers in your gutter, simply open Xcode's settings by going to Xcode | Settings (or pressing the Cmd + , keyboard shortcut) and toggling the line numbers option in the editor section. Clicking on the breakpoint again will dim the arrow and disable the breakpoint. You can remove the breakpoint completely by clicking, dragging, and releasing the arrow indicator well outside of the gutter. A dust ball animation will let you know that it has been removed. You can also delete breakpoints by right-clicking on the arrow indicator and selecting Delete. The Standard Editor showing a breakpoint on line 14 Listing breakpoints You can see a list of all active or inactive breakpoints in your app by opening the breakpoint navigator in the sidebar to the left (Cmd + 7). The list will show the file and line number of each breakpoint. Selecting any of them will quickly take the source editor to that location. Using the + icon at the bottom of the sidebar will let you set many more types of advanced breakpoints, such as the Exception, Symbolic, Open GL Errors, and Test Failure breakpoints. More information about these types can be found on Apple's Developer site at https://developer.apple.com. The debug area When Xcode reaches a breakpoint, its debugging mode will become active. The debug navigator will appear in the sidebar on the left, and if you've printed any information onto the console, the debug area will automatically appear below the editor area: The buttons in the top bar of the debug area are as follows (from left to right): Hide/Show debug area: Toggles the visibility of the debug area Activate/Deactivate breakpoints: This icon activates or deactivates all breakpoints Step Over: Execute the current line or function and pause at the next line Step Into: This executes the current line and jumps to any functions that are called Step Out: This exits the current function and places you at the line of code that called the current function Debug view hierarchy: This shows you a stacked representation of the view hierarchy Location: Since the simulator doesn't have GPS, you can set its location here (Apple HQ, London, and City Bike Ride are some of them) Stack Frame selector: This lets you choose a frame in which the current breakpoint is running The main window of the debug area can be split into two panes: the variables view and the LLDB console. The variables view The variables view shows all the variables and constants that are in the memory and within the current scope of your code. If the instance is a value type, it will show the value, and if it's an object type, you'll see a memory address, as shown in the following screenshot: This view shows all the variables and constants that are in the memory and within the current scope of your code. If the instance is a value type, it will show the value, and if it's an object type, you'll see a memory address. For collection types (arrays and dictionaries), you have the ability to drill down to the contents of the collection by toggling the arrow indicator on the left-hand side of each instance. In the bottom toolbar, there are three sections: Scope selector: This let's you toggle between showing the current scope, showing the global scope, or setting it to auto to select for you Information icons: The Quick Look icon will show quick look information in a popup, while the print information button will print the instance's description on the console Filter area: You can filter the list of values using this standard filter input box The console area The console area is the area where the system will place all system-generated messages as well as any messages that are printed using the print or NSLog statements. These messages will be displayed only while the application is running. While you are in debug mode, the console area becomes an interactive console in the LLDB debugger. This interactive mode lets you print the values of instances in memory, run debugger commands, inspect code, evaluate code, step through, and even skip code. As Xcode has matured over the years, more and more of the advanced information available for you in the console has become accessible in the GUI. Two important and useful commands for use within the console are p and po: po: Prints the description of the object p: Prints the value of an object Depending on the type of variable or constant, p and po may give different information. As an example, let's take a UITableViewCell that was created in our showcase app, now place a breakpoint in the tableView:cellForRowAtIndexPath method in the ExamleTableView class: (lldb) p cell (UITableViewCell) $R0 = 0x7a8f0000 {   UIView = {     UIResponder = {       NSObject = {         isa = 0x7a8f0000       }       _hasAlternateNextResponder = ' '       _hasInputAssistantItem = ' '     }     ... removed 100 lines  (lldb) po cell <UITableViewCell: 0x7a8f0000; frame = (0 0; 320 44); text = 'Helium'; clipsToBounds = YES; autoresize = W; layer = <CALayer: 0x7a6a02c0>> The p has printed out a lot of detail about the object while po has displayed a curated list of information. It's good to know and use each of these commands; each one displays different information. The debug navigator To open the debug navigator, you can click on its icon in the navigator sidebar or use the Cmd + 6 keyboard shortcut. This navigator will show data only while you are in debug mode: The navigator has several groups of information: The gauges area: At a glance, this shows information about how your application is using the CPU, Memory, Disk, Network, and iCloud (only when your app is using it) resources. Clicking on each gauge will show more details in the standard editor area. The processes area: This lists all currently active threads and their processes. This is important information for advanced debugging. The information in the gauges area used to be accessible only if you ran your application in and attached the running process to a separate instruments application. Because of the extra step in running our app in this separate application, Apple started including this information inside of Xcode starting from Xcode 6. This information is invaluable for spotting issues in your application, such as memory leaks, or spotting inefficient code by watching the CPU usage. The preceding screenshot shows the Memory Report screen. Because this is running in the simulator, the amount of RAM available for your application is the amount available on your system. The gauge on the left-hand side shows the current usage as a percentage of the available RAM. The Usage Comparison area shows how much RAM your application is using compared to other processes and the available free space. Finally, the bottom area shows a graph of memory usage over time. Each of these pieces of information is useful for the debugging of your application for crashes and performance. Quick Look There, we were able to see from within the standard editor the contents of variables and constants. While Xcode is in debug mode, we have this very ability. Simply hover the mouse over most instance variables and a Quick Look popup will appear to show you a graphical representation, like this: Quick Look knows how to handle built-in classes, such as CGRect or UIImage, but what about custom classes that you create? Let's say that you create a class representation of an Employee object. What information would be the best way to visualize an instance? You could show the employee's photo, their name, their employee number, and so on. Since the system can't judge what information is important, it will rely on the developer to decide. The debugQuickLookObject() method can be added to any class, and any object or value that is returned will show up within the Quick Look popup: func debugQuickLookObject() -> AnyObject {     return "This is the custom preview text" } Suppose we were to add that code to the ViewController class and put a breakpoint on the super.viewDidLoad() line: import UIKit class ViewController: UIViewController {       override func viewDidLoad() {         super.viewDidLoad()         // Do any additional setup after loading the view, typically from a nib.     }       override func didReceiveMemoryWarning() {         super.didReceiveMemoryWarning()         // Dispose of any resources that can be recreated.     }       func debugQuickLookObject() -> AnyObject {         return "I am a quick look value"     }   } Now, in the variables list in the debug area, you can click on the Quick Look icon, and the following screen will appear: Summary Debugging is an art as well as a science. Because of this, it easily can—and does—take entire books to cover the subject. The best way to learn techniques and tools is by experimenting on your own code. Resources for Article:   Further resources on this subject: Introduction to GameMaker: Studio [article] Exploring Swift [article] Using Protocols and Protocol Extensions [article]
Read more
  • 0
  • 0
  • 14482

article-image-building-iphone-app-using-swift-part-1
Ryan Loomba
17 Mar 2016
6 min read
Save for later

Building an iPhone App Using Swift: Part 1

Ryan Loomba
17 Mar 2016
6 min read
In this post, I’ll be showing you how to create an iPhone app using Apple’s new Swift programming language. Swift is a new programming language that Apple released in June at their special WWDC event in San Francisco, CA. You can find more information about Swift on the official page. Apple has released a book on Swift, The Swift Programming Language, which is available on the iBook Store or can be viewed online here. OK—let’s get started! The first thing you need in order to write an iPhone app using Swift is to download a copy of Xcode 6. Currently, the only way to get a copy of Xcode 6 is to sign up for Apple’s developer program. The cost to enroll is $99 USD/year, so enroll here. Once enrolled, click on the iOS 8 GM Seed link, and scroll down to the link that says Xcode 6 GM Seed. Once Xcode is installed, go to File -> New -> New Project. We will click on Application within the iOS section and choose a Single View Application: Click on the play button in the top left of the project to build the project. You should see the iPhone simular open with a blank white screen. Next, click on the top-left blue Sample Swift App project file and navigate to the general tab. In the Deployment Info section, select portrait for the device orientation. This will force the app to only be viewed in portrait mode. First View Controller If we navigate on the left to Main.storyboard, we see a single View Controller, with a single View. First, make sure that Use Size Classes is unchecked in the Interface Builder Document section. Let’s add a text view to the top of our view. In the bottom right text box, search for Text View. Drag the Text View and position it at the top of the View. Click on the Attributes inspectoron the right toolbar to adjust the font and alignment. If we click the play button to build the project, we should see the same white screen, but now with our Swift Sample App text. View a web page Let’s add our first feature–a button that will open up a web page. First embed our controller in a navigation controller, so we can easily navigate back and forth between views. Select the view controller in the storyboard, then go to Editor -> Embed in -> Navigation controller. Note that you might need to resize the text view you added in the previous step. Now, let’s add a button that will open up a web view. Back to our view, in the bottom right let’s search for a button and drag it somewhere in the view and label it Web View. The final product should look like this: If we build the project and click on the button, nothing will happen. We need to create a destination controller that will contain the web view. Go to File -> New and create a new Cocoa Touch Class: Let’s name our new controller WebViewController and make it a subclass of UIViewController. Make sure you choose Swift as the language. Click Create to save the controller file. Back to our storyboard, search for a View Controller in the bottom-right search box and drag to the storyboard. In the Attributes inspector toolbar on the right side of the screen, let’s give this controller the title WebViewController. In the identity inspector, let’s give this view controller a custom class of WebViewController: Let’s wire up our two controllers. Ctrl + click on the Web View button we created earlier and hold. Drag your cursor over to your newly created WebViewController. Upon release, choose push. On our storyboard, let’s search for a web view in the lower-right search box and drag it into our newly created WebViewController. Resize the web view so that it takes up the entire screen, except for the top nav bar area. If we hit the large play button at the top left to build our app, clicking on the Web View link will take us to a blank screen. We’ll also have a back button that takes us back to the first screen. Writing some Swift code Let’s have the web view load up a pre-determined website. Time to get our hands dirty writing some Swift! The first thing we need to do is link the WebView in our controller to the WebViewController.swift file. In the storyboard, click on the Assistant editor button at the top-right of the screen. You should see the storyboard view of WebViewController and WebViewController.swift next to each other. Control click on WebViewController in the storyboard and drag it over to the line right before the WebViewController class is defined. Name the variable webView: In the viewDidLoad function, we are going to add some intitialization to load up our webpage. After super.viewDidLoad(), let’s first declare the URL we want to use. This can be any URL; for the example, I’m going to use my own homepage. It will look something like this: let requestURL = NSURL(string: http://ryanloomba.com) In Swift, the keyword let is used to desiginate contsants, or variables that will not change. Next, we will convert this URL into an NSURLRequest object. Finally, we will tell our WebView to make this request and pass in the request object: import UIKit class WebViewController: UIViewController { @IBOutlet var webView: UIWebView! override func viewDidLoad() { super.viewDidLoad() let requestURL = NSURL(string: "http://ryanloomba.com") let request = NSURLRequest(URL: requestURL) webView.loadRequest(request) // Do any additional setup after loading the view. } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } /* // MARK: - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) { // Get the new view controller using segue.destinationViewController. // Pass the selected object to the new view controller. } */ } Try changing the URL to see different websites. Here’s an example of what it should look like: About the author Ryan is a software engineer and electronic dance music producer currently residing in San Francisco, CA. Ryan started up as a biomedical engineer but fell in love with web/mobile programming after building his first Android app, you can find him on GitHub @rloomba
Read more
  • 0
  • 0
  • 14481

article-image-how-make-generic-typealiases-swift
Alexander Altman
16 Nov 2015
4 min read
Save for later

How to Make Generic typealiases in Swift

Alexander Altman
16 Nov 2015
4 min read
Swift's typealias declarations are a good way to clean up our code. It's generally considered good practice in Swift to use typealiases to give more meaningful and domain-specific names to types that would otherwise be either too general-purpose or too long and complex. For example, the declaration: typealias Username = String gives a less vague name to the type String, since we're going to be using strings as usernames and we want a more domain-relevant name for that type. Similarly, the declaration: typealias IDMultimap = [Int: Set<Username>] gives a name for [Int: Set<Username>] that is not only more meaningful, but somewhat shorter. However, we run into problems when we want to do something a little more advanced; there is a possible application of typealias that Swift doesn't let us make use of. Specifically, Swift doesn't accept typealiases with generic parameters. If we try it the naïvely obvious way, typealias Multimap<Key: Hashable, Value: Hashable> = [Key: Set<Value>] we get an error at the begining of the type parameter list: Expected '=' in typealias declaration. Swift (as of version 2.1, at least) doesn't let us directly declare a generic typealias. This is quite a shame, as such an ability would be very useful in a lot of different contexts, and languages that have it (such as Rust, Haskell, Ocaml, F♯, or Scala) make use of it all the time, including in their standard libraries. Is there any way to work around this linguistic lack? As it turns out, there is! The Solution It's actually possible to effectively give a typealias type parameters, despite Swift appearing to disallow it. Here's how we can trick Swift into accepting a generic typealias: enum Multimap<Key: Hashable, Value: Hashable> { typealias T = [Key: Set<Value>] } The basic idea here is that we declare a generic enum whose sole purpose is to hold our (now technically non-generic) typealias as a member. We can then supply the enum with its type parameters and project out the actual typealias inside, like so: let idMMap: Multimap<Int, Username>.T = [0: ["alexander", "bob"], 1: [], 2: ["christina"]] func hasID0(user: Username) -> Bool { return idMMap[0]?.contains(user) ?? false } Notice that we used an enum rather than a struct; this is because an enum with no cases cannot have any instances (which is exactly what we want), but a struct with no members still has (at least) one instance, which breaks our layer of abstraction. We are essentially treating our caseless enum as a tiny generic module, within which everything (that is, just the typealias) has access to the Key and Value type parameters. This pattern is used in at least a few libraries dedicated to functional programming in Swift, since such constructs are especially valuable there. Nonetheless, this is a broadly useful technique, and it's the best method currently available for creating generic typealias in Swift. The Applications As sketched above, this technique works because Swift doesn't object to an ordinary typealias nested inside a generic type declaration. However, it does object to multiple generic types being nested inside each other; it even objects to either a generic type being nested inside a non-generic type or a non-generic type being nested inside a generic type. As a result, type-level currying is not possible. Despite this limitation, this kind of generic typealias is still useful for a lot of purposes; one big one is specialized error-return types, in which Swift can use this technique to imitate Rust's standard library: enum Result<V, E> { case Ok(V) case Err(E) } enum IO_Result<V> { typealias T = Result<V, ErrorType> } Another use for generic typealiases comes in the form of nested collections types: enum DenseMatrix<Element> { typealias T = [[Element]] } enum FlatMatrix<Element> { typealias T = (width: Int, elements: [Element]) } enum SparseMatrix<Element> { typealias T = [(x: Int, y: Int, value: Element)] } Finally, since Swift is a relatively young language, there are sure to be undiscovered applications for things like this; if you search, maybe you'll find one! Super-charge your Swift development by learning how to use the Flyweight pattern – Click here to read more About the author Alexander Altman (https://pthariensflame.wordpress.com) is a functional programming enthusiast who enjoys the mathematical and ergonomic aspects of programming language design. He's been working with Swift since the language's first public release, and he is one of the core contributors to the TypeLift (https://github.com/typelift) project.
Read more
  • 0
  • 0
  • 13545
article-image-how-use-currying-swift-fun-and-profit
Alexander Altman
06 Apr 2016
5 min read
Save for later

How to Use Currying in Swift for Fun and Profit

Alexander Altman
06 Apr 2016
5 min read
Swift takes inspiration from functional languages in a lot of its features, and one of those features is currying. The idea behind currying is relatively straightforward, and Apple has already taken the time to explain the basics of it in The Swift Programming Language. Nonetheless, there's a lot more to currying in Swift than what first meets the eye. What is currying? Let's say we have a function, f, which takes two parameters, a: Int and b: String, and returns a Bool: func f(a: Int, _ b: String) -> Bool { // … do somthing here … } Here, we're taking both a and b simultaneously as parameters to our function, but we don't have to do it that way! We can just as easily write this function to take just a as a parameter and then return another function that takes b as it's only parameter and returns the final result: func f(a: Int) -> ((String) -> Bool) { return { b in // … do somthing here … } } (I've added a few extra parentheses for clarity, but Swift is actually just fine if you write String -> Bool instead of ((String) -> Bool); the two notations mean exactly the same thing.) This formulation uses a closure, but you can also use a nested function for the exact same effect: func f(a: Int) -> ((String) -> Bool) { func g(b: String) -> Bool { // … do somthing here … } return g } Of course, Swift wouldn't be Swift without providing a convenient syntax for things like this, so there is even a third way to write the curried version of f, and it's (usually) preferred over either of the previous two: func f(a: Int)(_ b: String) -> Bool { // … do somthing here … } Any of these iterations of our curried function f can be called like this: let res: Bool = f(1)("hello") Which should look very similar to the way you would call the original uncurried f: let res: Bool = f(1, "hello") Currying isn't limited to just two parameters either; here's an example of a partially curried function of five parameters (taking them in groups of two, one, and two): func weirdAddition(x: Int, use useX: Bool)(_ y: Int)(_ z: Int, use useZ: Bool) -> Int { return (useX ? x : 0) + y + (useZ ? z : 0) } How is currying used in Swift? Believe it or not, Swift actually uses currying all over the place, even if you don't notice it. Probably, the most prominent example is that of instance methods, which are just curried type methods: // This: NSColor.blueColor().shadowWithLevel(1/3) // …is the same as this: NSColor.shadowWithLevel(NSColor.blueColor())(1/3) But, there's a much deeper implication of currying's availability in Swift: all functions secretly take only one parameter! How is this possible, you ask? It has to do with how Swift treats tuples. A function that “officially” takes, say, three parameters, actually only takes one parameter that happens to be a three-tuple. This is perhaps most visible when exploited via the higher-order collections method: func dotProduct(xVec: [Double], _ yVec: [Double]) -> Double { // Note that (this particular overload of) the `*` operator // has the signature `(Double, Double) -> Double`. return zip(xVec, yVec).map(*).reduce(0, combine: +) } It would seem that anything you can do with tuples, you can do with a function parameter list and vice versa; in fact, that is almost true. The four features of function parameter lists that don't carry over directly into tuples are the variadic, inout, defaulted, and @autoclosure parameters. You can, technically, form a variadic, inout, defaulted, or @autoclosure tuple type, but if you try to use it in any context other than as a function's parameter type, swiftc will give you an error. What you definitely can do with tuples is use named values, notwithstanding the unfortunate prohibition on single-element tuples in Swift (named or not). Apple provides some information on tuples with named elements in The Swift Programming Language; it also gives an example of one in the same book. It should be noted that the names given to tuple elements are somewhat ephemeral in that they can very easily be introduced, eliminated, and altered via implicit conversions. This applies regardless of whether the tuple type is that of a standalone value or of a function's parameter: // converting names in a function's parameter list func printBoth(first x: Int, second y: String) { print(x, y, separator: ", ") } let printTwo: (a: Int, b: String) -> Void = printBoth // converting names in a standalone tuple type // (for some reason, Swift dislikes assigning `firstAndSecond` // directly to `aAndB`, but going through `nameless` is fine) let firstAndSecond: (first: Int, second: String) = (first: 1, second: "hello") let nameless: (Int, String) = firstAndSecond let aAndB: (a: Int, b: String) = nameless Currying, with its connection to tuples, is a very powerful feature of Swift. Use it wherever it seems helpful, and the language will be more than happy to oblige. About the author Alexander Altman is a functional programming enthusiast who enjoys the mathematical and ergonomic aspects of programming language design. He's been working with Swift since the language's first public release, and he is one of the core contributors to the TypeLift project.
Read more
  • 0
  • 0
  • 12534

article-image-bsd-socket-library
Packt
17 Jan 2014
9 min read
Save for later

BSD Socket Library

Packt
17 Jan 2014
9 min read
(For more resources related to this topic, see here.) Introduction The Berkeley Socket API (where API stands for Application Programming Interface) is a set of standard functions used for inter-process network communications. Other socket APIs also exist; however, the Berkeley socket is generally regarded as the standard. The Berkeley Socket API was originally introduced in 1983 when 4.2 BSD was released. The API has evolved with very few modifications into a part of the Portable Operating System Interface for Unix (POSIX) specification. All modern operating systems have some implementation of the Berkeley Socket Interface for connecting devices to the Internet. Even Winsock, which is MS Window's socket implementation, closely follows the Berkeley standards. BSD sockets generally rely on client/server architecture when they establish their connections. Client/server architecture is a networking approach where a device is assigned one of the two following roles: Server: A server is a device that selectively shares resources with other devices on the network Client: A client is a device that connects to a server to make use of the shared resources Great examples of the client/server architecture are web pages. When you open a web page in your favorite browser, for example https://www.packtpub.com, your browser (and therefore your computer) becomes the client and Packt Publishing's web servers become the servers. One very important concept to keep in mind is that any device can be a server, a client, or both. For example, you may be visiting the Packt Publishing website, which makes you a client, and at the same time you have file sharing enabled, which also makes your device a server. The Socket API generally uses one of the following two core protocols: Transmission Control Protocol (TCP): TCP provides a reliable, ordered, and error-checked delivery of a stream of data between two devices on the same network. TCP is generally used when you need to ensure that all packets are correctly received and are in the correct order (for example, web pages). User Datagram Protocol (UDP): UDP does not provide any of the error-checking or reliability features of TCP, but offers much less overhead. UDP is generally used when providing information to the client quickly is more important than missing packets (for example, a streaming video). Darwin, which is an open source POSIX compliant operating system, forms the core set of components upon which Mac OS X and iOS are based. This means that both OS X and iOS contain the BSD Socket Library. The last paragraph is very important to understand when you begin thinking about creating network applications for the iOS platform, because almost any code example that uses the BSD Socket Library will work on the iOS platform. The biggest difference between using the BSD Socket API on any standard Unix platform and the iOS platform is that the iOS platform does not support forking of processes. You will need to use multiple threads rather than multiple processes. The BSD Socket API can be used to build both client and server applications. There are a few networking concepts that you should understand: IP address: Any device on an Internet Protocol (IP) network, whether it is a client or server, has a unique identifier known as an IP address. The IP address serves two basic purposes: host identification and location identification. There are currently two IP address formats: IPv4: This is currently the standard for the Internet and most internal intranets. This is an example of an IPv4 address: 83.166.169.231. IPv6: This is the latest revision of the Internet Protocol (IP). It was developed to eventually replace IPv4 and to address the long-anticipated problem of running out of IPv4 addresses. This is an example of an IPv6 address: 2001:0db8:0000:0000:0000:ff00:0042:8329. An IPv6 can be shortened by replacing all the consecutive zero fields with two colons. The previous address could be rewritten as 2001:0db8::ff00:0042:8329. Ports: A port is an application or process-specific software construct serving as a communications endpoint on a device connected to an IP network, where the IP address identifies the device to connect to, and the port number identifies the application to connect to. The best way to think of network addressing is to think about how you mail a letter. For a letter to reach its destination, you must put the complete address on the envelope. For example, if you were going to send a letter to friend who lived at the following address: Your Friend 123 Main St Apt. 223 San Francisco CA, 94123 If I were to translate that into network addressing, the IP address would be equal to the street address, city, state, and zip code (123 Main St, San Francisco CA, 94123), and the apartment number would be equal to the port number (223). So the IP address gets you to the exact location, and the port number will tell you which door to knock on. A device has 65,536 available ports with the first 1024 being reserved for common protocols such as HTTP, HTTPS, SSH, and SMTP. Fully Qualified Domain Name (FQDN): As humans, we are not very good at remembering numbers; for example, if your friend tells you that he found a really excellent website for books and the address was 83.166.169.231, you probably would not remember that two minutes from now. However, if he tells you that the address was www.packtpub.com, you would probably remember it. FQDN is the name that can be used to refer to a device on an IP network. So now you may be asking yourself, how does the name get translated to the IP address? The Domain Name Server (DNS) would do that. Domain Name System Servers: A Domain Name System Server translates a fully qualified domain name to an IP address. When you use an FQDN of www.packtpub.com, your computer must get the IP address of the device from the DNS configured in your system. To find out what the primary DNS is for your machine, open a terminal window and type the following command: cat /etc/resolv.conf Byte order: As humans, when we look at a number, we put the most significant number first and the least significant number last; for example, in number 123, 1 represents 100, so it is the most significant number, while 3 is the least significant number. For computers, the byte order refers to the order in which data (not only integers) is stored into memory. Some computers store the most significant bytes first (at the lowest byte address), while others store the most significant bytes last. If a device stores the most significant bytes first, it is known as big-endian, while a device that stores the most significant bytes last is known as little-endian. The order of how data is stored in memory is of great importance when developing network applications, where you may have two devices that use different byte-ordering communication. You will need to account for this by using the Network-to-Host and Host-to-Network functions to convert between the byte order of your device and the byte order of the network. The byte order of the device is commonly referred to as the host byte order, and the byte order of the network is commonly referred to as the network byte order. Finding the byte order of your device One of the concepts that was briefly discussed in this article was how devices store information in memory (byte order). After that discussion, you may be wondering what the byte order of your device is. The byte order of a device depends on the Microprocessor architecture being used by the device. You can pretty easily go on to the Internet and search for "Mac OS X i386 byte order" and find out what the byte order is, but where is the fun in that? We are developers, so let's see if we can figure it out with code. We can determine the byte order of our devices with a few lines of C code; however, like most of the code in this article, we will put the C code within an Objective-C wrapper to make it easy to port to your projects. How to do it… Let's get started by defining an ENUM in our header file: We create an ENUM that will be used to identify the byte order of the system as shown in the following code: typedef NS_ENUM(NSUInteger, EndianType) { ENDIAN_UNKNOWN, ENDIAN_LITTLE, ENDIAN_BIG }; To determine the byte order of the device, we will use the byteOrder method as shown in the following code: -( EndianType)byteOrder { union { short sNum; char cNum[sizeof(short)]; } un; un.sNum = 0x0102; if (sizeof(short) == 2) { if(un.cNum[0] == 1 && un.cNum[1] == 2) return ENDIAN_BIG; else if (un.cNum[0] == 2 && un.cNum[1] == 1) return ENDIAN_LITTLE; else return ENDIAN_UNKNOWN; } else return ENDIAN_UNKNOWN; } How it works… In the ByteOrder header file, we defined an ENUM with three constants. The constants are as follows: ENDIAN_UNKNOWN: We are unable to determine the byte order of the device ENDIAN_LITTLE: This specifies that the most significant bytes are last (little-endian) ENDIAN_BIG: This specifies that the most significant bytes are first (big-endian) The byteOrder method determines the byte order of our device and returns an integer that can be translated using the constants defined in the header file. To determine the byte order of our device, we begin by creating a union of short int and char[]. We then store the value 0x0102 in the union. Finally, we look at the character array to determine the order in which the integer was stored in the character array. If the number one was stored first, it means that the device uses big-endian; if the number two was stored first, it means that the device uses little-endian.
Read more
  • 0
  • 0
  • 12273
Modal Close icon
Modal Close icon