diff --git a/2012-07-07-nsindexset.md b/2012-07-07-nsindexset.md index e6916fef..1f56fac2 100644 --- a/2012-07-07-nsindexset.md +++ b/2012-07-07-nsindexset.md @@ -1,10 +1,10 @@ --- layout: post title: NSIndexSet - ref: "https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSSet_Class/Reference/Reference.html" framework: Foundation rating: 7.8 +description: "NSIndexSet (and its mutable counterpart, NSMutableIndexSet) is a sorted collection of unique unsigned integers. Think of it like an NSRange that supports non-contiguous series. It has wicked fast operations for finding indexes in ranges or set intersections, and comes with all of the convenience methods you'd expect in a Foundation collection class." --- `NSIndexSet` (and its mutable counterpart, `NSMutableIndexSet`) is a sorted collection of unique unsigned integers. Think of it like an `NSRange` that supports non-contiguous series. It has wicked fast operations for finding indexes in ranges or set intersections, and comes with all of the convenience methods you'd expect in a Foundation collection class. diff --git a/2012-07-14-nscache.md b/2012-07-14-nscache.md index 304d1139..2fb08f90 100644 --- a/2012-07-14-nscache.md +++ b/2012-07-14-nscache.md @@ -1,15 +1,15 @@ --- layout: post title: NSCache - ref: "https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSCache_Class/Reference/Reference.html" framework: Foundation rating: 7.5 +description: "Poor NSCache, always being overshadowed by NSMutableDictionary. It's as if no one knew how it provides all of that garbage collection behavior that developers take great pains to re-implement themselves." --- Poor `NSCache`, always being overshadowed by `NSMutableDictionary`. It's as if no one knew how it provides all of that garbage collection behavior that developers take great pains to re-implement themselves. -That's right: `NSCache` is basically just an `NSMutableDictionary` that automatically evicts objects in order to free up space in memory as needed. No need to respond to memory warnings or contrive a cache-clearing timer mechanism. The only other difference is that keys aren't copied as they are in an `NSMutableDictionary`, which is actually to its advantage (no need for keys to conform to ``). +That's right: `NSCache` is basically just an `NSMutableDictionary` that automatically evicts objects in order to free up space in memory as needed. No need to respond to memory warnings or contrive a cache-clearing timer mechanism. The only other difference is that keys aren't copied as they are in an `NSMutableDictionary`, which is actually to its advantage (no need for keys to conform to ``). If developers only knew... @@ -23,7 +23,7 @@ Take `setObject:forKey:cost:`, for example. It's the same `setObject:forKey:` me Alright, so far so good... -> However, this eviction process is not in a guaranteed order. As a consequence, if you try to manipulate the cost values to achieve some specific behavior, the consequences could be detrimental to your program. +> However, this eviction process is not in a guaranteed order. As a consequence, if you try to manipulate the cost values to achieve some specific behavior, the consequences could be detrimental to your program. Huh? So what's the point, then? diff --git a/2012-07-24-nssortdescriptor.md b/2012-07-24-nssortdescriptor.md index 2468e7b5..137f878e 100644 --- a/2012-07-24-nssortdescriptor.md +++ b/2012-07-24-nssortdescriptor.md @@ -1,13 +1,13 @@ --- layout: post title: NSSortDescriptor - ref: "https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSSortDescriptor_Class/Reference/Reference.html" framework: Foundation rating: 8.4 +description: "Sorting: it's the mainstay of Computer Science 101 exams and whiteboarding interview questions. But when was the last time you actually needed to know how to implement Quicksort yourself?" --- -Sorting: it's the mainstay of Computer Science 101 exams and whiteboarding interview questions. But when was the last time you actually needed to know how to implement Quicksort yourself? +Sorting: it's the mainstay of Computer Science 101 exams and whiteboarding interview questions. But when was the last time you actually needed to know how to implement Quicksort yourself? When making apps, sorting is just something you can assume to be fast, and utility is a function of convenience and clarity of intention. And when it comes to that, you'd be hard-pressed to find a better implementation than Foundation's `NSSortDescriptor`. @@ -18,13 +18,13 @@ When making apps, sorting is just something you can assume to be fast, and utili > - `key`: for a given collection, the key for the corresponding value to be sorted on for each object in the collection. > - `ascending`: a boolean specifying whether the collection should be sorted in ascending (`YES`) or descending (`NO`) order. -There is an optional third parameter that relates to how the sorted values are compared to one another. By default, this is a simple equality check, but this behavior can be changed by passing either a `selector` (`SEL`) or `comparator` (`NSComparator`). +There is an optional third parameter that relates to how the sorted values are compared to one another. By default, this is a simple equality check, but this behavior can be changed by passing either a `selector` (`SEL`) or `comparator` (`NSComparator`). > Any time you're sorting user-facing strings, be sure to pass the selector `localizedStandardCompare:`, which will sort according to the language rules of the current locale (locales may differ on ordering of case, diacritics, and so forth). Collection classes like `NSArray` and `NSSet` have methods to return sorted arrays of the objects that take an array of `sortDescriptors`. Sort descriptors are applied in order, so that if two elements happen to be tied for a particular sorting criteria, the tie is broken by any subsequent descriptors. -To put that into more practical terms, consider a `Person` class with properties for `firstName` & `lastName` of type `NSString *`, and `age`, which is an `NSUInteger`. +To put that into more practical terms, consider a `Person` class with properties for `firstName` & `lastName` of type `NSString *`, and `age`, which is an `NSUInteger`. ~~~{objective-c} @interface Person : NSObject @@ -95,13 +95,13 @@ NSMutableArray *people = [NSMutableArray array]; [people addObject:person]; }]; -NSSortDescriptor *firstNameSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"firstName" - ascending:YES +NSSortDescriptor *firstNameSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"firstName" + ascending:YES selector:@selector(localizedStandardCompare:)]; -NSSortDescriptor *lastNameSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"lastName" - ascending:YES +NSSortDescriptor *lastNameSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"lastName" + ascending:YES selector:@selector(localizedStandardCompare:)]; -NSSortDescriptor *ageSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"age" +NSSortDescriptor *ageSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:NO]; NSLog(@"By age: %@", [people sortedArrayUsingDescriptors:@[ageSortDescriptor]]); diff --git a/2012-07-31-nsdatecomponents.md b/2012-07-31-nsdatecomponents.md index 32599c45..2dd8c0ab 100644 --- a/2012-07-31-nsdatecomponents.md +++ b/2012-07-31-nsdatecomponents.md @@ -1,10 +1,10 @@ --- layout: post title: NSDateComponents - ref: "https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSDateComponents_Class/Reference/Reference.html" framework: Foundation rating: 6.9 +description: "NSDateComponents serves an important role in Foundation's date and time APIs. By itself, it's nothing impressive—just a container for information about a date (its month, year, day of month, week of year, or whether that month is a leap month). However, combined with NSCalendar, NSDateComponents becomes a remarkably convenient interchange format for calendar calculations." --- `NSDateComponents` serves an important role in Foundation's date and time APIs. By itself, it's nothing impressive—just a container for information about a date (its month, year, day of month, week of year, or whether that month is a leap month). However, combined with `NSCalendar`, `NSDateComponents` becomes a remarkably convenient interchange format for calendar calculations. @@ -63,7 +63,7 @@ Perhaps the most powerful feature of `NSDateComponents`, however, is the ability ~~~{objective-c} NSCalendar *calendar = [NSCalendar currentCalendar]; - + NSDateComponents *components = [[NSDateComponents alloc] init]; [components setYear:1987]; [components setMonth:3]; diff --git a/2012-08-13-nsincrementalstore.md b/2012-08-13-nsincrementalstore.md index 2216f28d..d44abb9d 100644 --- a/2012-08-13-nsincrementalstore.md +++ b/2012-08-13-nsincrementalstore.md @@ -1,7 +1,6 @@ --- layout: post title: NSIncrementalStore - ref: "https://developer.apple.com/library/mac/#documentation/CoreData/Reference/NSIncrementalStore_Class/Reference/NSIncrementalStore.html" framework: Foundation rating: 9.5 @@ -9,7 +8,7 @@ published: true description: Even for a blog dedicated to obscure APIs, NSIncrementalStore sets a new standard. It was introduced in iOS 5, with no more fanfare than the requisite entry in the SDK changelog. Ironically, it is arguably the most important thing to come out of iOS 5, which will completely change the way we build apps from here on out. --- -Even for a blog dedicated to obscure APIs, `NSIncrementalStore` brings a new meaning to the word "obscure". +Even for a blog dedicated to obscure APIs, `NSIncrementalStore` brings a new meaning to the word "obscure". It was introduced in iOS 5, with no more fanfare than the requisite entry in the SDK changelog. @@ -23,7 +22,7 @@ And yet, `NSIncrementalStore` is arguably the most important thing to come out o `NSIncrementalStore` is an abstract subclass of `NSPersistentStore` designed to "create persistent stores which load and save data incrementally, allowing for the management of large and/or shared datasets". And while that may not sound like much, consider that nearly all of the database adapters we rely on load incrementally from large, shared data stores. What we have here is a goddamned miracle. -For those of you not as well-versed in Core Data, here's some background: +For those of you not as well-versed in Core Data, here's some background: [Core Data](http://developer.apple.com/library/mac/#documentation/cocoa/Conceptual/CoreData/cdProgrammingGuide.html) is Apple's framework for object relational mapping. It's used in at least half of all of the first-party apps on Mac and iOS, as well as thousands of other third-party apps. Core Data is complex, but that's because it solves complex problems, covering a decades-worth of one-offs and edge cases. @@ -64,7 +63,7 @@ NSMutableDictionary *mutableMetadata = [NSMutableDictionary dictionary]; ### `-executeRequest:withContext:error:` -Here's where things get interesting, from an implementation standpoint. (And where it all goes to hell, from an API design standpoint) +Here's where things get interesting, from an implementation standpoint. (And where it all goes to hell, from an API design standpoint) `executeRequest:withContext:error:` passes an `NSPersistentStoreRequest`, an `NSManagedObjectContext` and an `NSError` pointer. @@ -79,18 +78,18 @@ This method requires very specific and very different return values depending on > **Return**: `NSArray` of objects matching request - Result Type: `NSCountResultType` - + > **Return**: NSNumberNSArray containing one NSNumber of count of objects matching request #### Request Type: `NSSaveRequestType` - + > **Return**: Empty `NSArray` So, one method to do all read _and_ write operations with a persistence backend. At least all of the heavy lifting goes to the same place, right? ### `-newValuesForObjectWithID:withContext:error:` -This method is called when an object faults, or has its values refreshed by the managed object context. +This method is called when an object faults, or has its values refreshed by the managed object context. It returns an `NSIncrementalStoreNode`, which is a container for the ID and current values for a particular managed object. The node should include all of the attributes, as well as the managed object IDs of any to-one relationships. There is also a `version` property of the node that can be used to determine the current state of an object, but this may not be applicable to all storage implementations. @@ -98,7 +97,7 @@ If an object with the specified `objectID` cannot be found, this method should r ### `-newValueForRelationship:forObjectWithID: withContext:error:` -This one is called when a relationship needs to be refreshed, either from a fault or by the managed object context. +This one is called when a relationship needs to be refreshed, either from a fault or by the managed object context. Unlike the previous method, the return value will be just the current value for a single relationship. The expected return type depends on the nature of the relationship: diff --git a/2012-08-27-cfbag.md b/2012-08-27-cfbag.md index 5c3a7843..b038ffcc 100644 --- a/2012-08-27-cfbag.md +++ b/2012-08-27-cfbag.md @@ -1,15 +1,14 @@ --- layout: post title: CFBag - ref: "https://developer.apple.com/library/mac/#documentation/CoreFOundation/Reference/CFMutableBagRef/Reference/reference.html" framework: CoreFoundation rating: 7.2 published: true -description: In the pantheon of collection data types in computer science, bag doesn't really have the same clout as lists, sets, associative arrays, trees, graphs, or priority queues. In fact, it's pretty obscure. You've probably never heard of it. +description: "In the pantheon of collection data types in computer science, bag doesn't really have the same clout as lists, sets, associative arrays, trees, graphs, or priority queues. In fact, it's pretty obscure. You've probably never heard of it." --- -Objective-C is a language caught between two worlds. +Objective-C is a language caught between two worlds. On one side, it follows the thoughtful, object-oriented philosophy of [Smalltalk](http://en.wikipedia.org/wiki/Smalltalk), which brings ideas like message sending and named parameters. On the other, are the inescapable vestiges of C, which brings it power and a dash of chaos. @@ -86,7 +85,7 @@ However, toll-free bridging is the exception when it comes to collection classes - * Indicates Mutable Counterpart + * Indicates Mutable Counterpart @@ -95,7 +94,7 @@ Take a look at the second row, with `NSCountedSet` and `CFBag`. Notice that unli ## Bags, in the Abstract -In the pantheon of collection data types in computer science, bag doesn't really have the same clout as lists, sets, associative arrays, trees, graphs, or priority queues. +In the pantheon of collection data types in computer science, bag doesn't really have the same clout as lists, sets, associative arrays, trees, graphs, or priority queues. In fact, it's pretty obscure. You've probably never heard of it. @@ -105,7 +104,7 @@ Its practical applications are... limited, but you'll know one when it comes up. ## Working with `CFMutableBag` -As an implementation of the bag data type, `CFBag` and its mutable counterpart, `CFMutableBag`, are pretty slick. +As an implementation of the bag data type, `CFBag` and its mutable counterpart, `CFMutableBag`, are pretty slick. Although it lacks the object-oriented convenience of `NSCountedSet`, it makes up for it with a number of ways to customize its behavior. When `CFBag` is created, it can be initialized with a number of callbacks, defined by the `CFBagCallBacks` struct, which specify the way values are inserted, removed, and compared: @@ -127,7 +126,7 @@ typedef struct CFBagCallBacks CFBagCallBacks; - `equal`: callback used to compare values in the collection for equality - `hash`: callback used to compute hash codes for values in the collection -For example, if you were implementing a vote tallying application, you could specify a normalizing function for `retain` to ensure that votes for mixed-case or misspelled names went to the right candidate, or ensure that the "correct" candidate is shown to be the winner when all the votes are in, with `equal` callback. +For example, if you were implementing a vote tallying application, you could specify a normalizing function for `retain` to ensure that votes for mixed-case or misspelled names went to the right candidate, or ensure that the "correct" candidate is shown to be the winner when all the votes are in, with `equal` callback. `CFMutableBag` also has `CFBagApplyFunction`, which has the ability to transform values over the collection, like if you wanted to smooth out vote counts, or something like that. @@ -135,6 +134,6 @@ So in closing, if you need to rig an election, `CFBag` is your best bet. --- -But seriously, `CFBag`, useful in its own right, serves as a reminder of the hidden gems to be found within the standard frameworks and libraries--indeed what is at the very heart of being an NSHipster. +But seriously, `CFBag`, useful in its own right, serves as a reminder of the hidden gems to be found within the standard frameworks and libraries--indeed what is at the very heart of being an NSHipster. Also, `CFBinaryHeap`? `NSPointerFunctions`? `NSMapTable`? Surely, you'll be seeing more of these in future editions. diff --git a/2012-09-03-nslocale.md b/2012-09-03-nslocale.md index ce0f4734..4c6b0157 100644 --- a/2012-09-03-nslocale.md +++ b/2012-09-03-nslocale.md @@ -1,7 +1,6 @@ --- layout: post title: NSLocale - ref: "https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSLocale_Class/Reference/Reference.html" framework: Foundation rating: 9.0 @@ -9,9 +8,9 @@ published: true description: "Internationalization is like flossing: everyone knows they should do it, but probably don't." --- -Internationalization is like flossing: everyone knows they should do it, but probably don't. +Internationalization is like flossing: everyone knows they should do it, but probably don't. -And like any habit, it becomes second-nature with practice, to the point that you couldn't imagine _not_ doing it. All it takes is for someone to show you the way. +And like any habit, it becomes second-nature with practice, to the point that you couldn't imagine _not_ doing it. All it takes is for someone to show you the way. Let NSHipster be your dental hygienist Virgil through these foreign lands.. without all of the lecturing about tooth decay (promsies!) @@ -20,7 +19,7 @@ Let NSHipster be your dental hygienist Virgil through these foreign lands.. with As is necessary in any discussion about Internationalization (i18n) or Localization (l10n), we must take some time to differentiate the two: - **Localization** is the process of adapting your application for a specific market, or _locale_. -- **Internationalization** is the process of preparing your app to be localized. +- **Internationalization** is the process of preparing your app to be localized. > Internationalization is a necessary, but not sufficient condition for localization, and will be the focus of this article. Localization, which involves the translation of text and assets into a particular language, will be covered in a future edition of NSHipster. @@ -39,7 +38,7 @@ Fortunately for us, we don't have to do this alone. Meet `NSLocale`: - Collation and Sorting - Use of Symbols, Colors, and Iconography -Each locale corresponds to a _locale identifier_, such as `en_US`, `fr_FR`, `ja_JP`, and `en_GB`, which include a language code (e.g. `en` for English) and a region code (e.g. `US` for United States). +Each locale corresponds to a _locale identifier_, such as `en_US`, `fr_FR`, `ja_JP`, and `en_GB`, which include a language code (e.g. `en` for English) and a region code (e.g. `US` for United States). Locale identifiers can encode more explicit preferences about currency, calendar system, or number formats, such as in the case of `de_DE@collation=phonebook,currency=DDM`, which specifies German spoken in Germany, using [phonebook collation](http://developer.mimer.com/charts/german_phonebook.htm), and using the pre-Euro [Deutsche Mark](http://en.wikipedia.org/wiki/Deutsche_Mark). @@ -49,7 +48,7 @@ Users can change their locale settings in the "Language & Text" (or "Internation ## Formatting Dates & Numbers -Although `NSLocale` encapsulates a rich set of domain-specific information, its typical usage is rather understated. +Although `NSLocale` encapsulates a rich set of domain-specific information, its typical usage is rather understated. If there's just one thing you should learn about `NSLocale`, it's that you should always pass `[NSLocale currentLocale]` into your `NSDateFormatter` and `NSNumberFormatter` instances. Doing this will ensure that dates, numbers, and currencies will be formatted according to the localization preferences of the user. @@ -81,13 +80,13 @@ But let's get back to some of the cool features of `NSLocale` itself, shall we? - `NSLocaleAlternateQuotationBeginDelimiterKey` - `NSLocaleAlternateQuotationEndDelimiterKey` -While this all may seem like fairly esoteric stuff, you may be surprised by the number of opportunities your application has to use this information to make for a better user experience. +While this all may seem like fairly esoteric stuff, you may be surprised by the number of opportunities your application has to use this information to make for a better user experience. It's the small things, like knowing that quotation marks vary between locales: -> English: “I can eat glass, it doesn't harm me.” -> German: „Ich kann Glas essen, das tut mir nicht weh.“ -> Japanese:「私はガラスを食べられます。それは私を傷つけません。」 +> English: “I can eat glass, it doesn't harm me.” +> German: „Ich kann Glas essen, das tut mir nicht weh.“ +> Japanese:「私はガラスを食べられます。それは私を傷つけません。」 So if you were building a component that added quotations around arbitrary text, you should use `NSLocaleQuotationBeginDelimiterKey` and `NSLocaleAlternateQuotationEndDelimiterKey` rather than assuming `@"\""` for English quotation marks. @@ -101,7 +100,7 @@ NSLog(@"fr_FR: %@", [frLocale displayNameForKey:NSLocaleIdentifier value:@"fr_FR NSLog(@"en_US: %@", [frLocale displayNameForKey:NSLocaleIdentifier value:@"en_US"]); ~~~ -> fr_FR: français (France) +> fr_FR: français (France) > en_US: anglais (États-Unis) You should use this method any time you need to display information about the user's current locale, or any alternative locales available to them, like in this screen from the Settings app: @@ -123,7 +122,7 @@ Even if your server doesn't yet localize its resources, putting this in place no --- -Internationalization is often considered to be an un-sexy topic in programming--just another chore that most projects don't have to worry about. In actuality, designing software for other locales is a valuable exercise (and not just for the economic benefits of expanding your software into other markets). +Internationalization is often considered to be an un-sexy topic in programming--just another chore that most projects don't have to worry about. In actuality, designing software for other locales is a valuable exercise (and not just for the economic benefits of expanding your software into other markets). One of the greatest joys and challenges in programming is in designing systems that can withstand change. The only way designs can survive this level of change is to identify and refactor assumptions about the system that may not always hold. In this way, internationalization represents the greatest challenge, making us question everything about our cultural identity. And in doing so, we become not just better programmers, but better people, too. diff --git a/2012-09-10-uiaccessibility.md b/2012-09-10-uiaccessibility.md index 10b2ca0c..de11d38b 100644 --- a/2012-09-10-uiaccessibility.md +++ b/2012-09-10-uiaccessibility.md @@ -1,22 +1,21 @@ --- layout: post title: UIAccessibility - ref: "http://developer.apple.com/library/ios/#documentation/uikit/reference/UIAccessibility_Protocol/Introduction/Introduction.html" framework: UIKit rating: 10.0 published: true -description: Accessibility, like internationalization, is one of those topics that's difficult to get developers excited about. But as you know, NSHipster is all about getting developers excited about this kind of stuff. +description: "Accessibility, like internationalization, is one of those topics that's difficult to get developers excited about. But as you know, NSHipster is all about getting developers excited about this kind of stuff." --- -> We all want to help one another, human beings are like that. +> We all want to help one another, human beings are like that. > - [Charlie Chaplin](http://en.wikiquote.org/wiki/Charlie_Chaplin) You know what I wish everyone would copy from Apple? Their assistive technologies. iPhones and iPads--magical as they are--become downright _life-changing_ for individuals with disabilities and their families because of Apple's commitment to accessibility. Look no further than the [WWDC 2012 Introduction Video](http://www.youtube.com/watch?v=MbP_pxR5cMk), which opens with Per Busch, a blind man who walks the woods of Kassel, Germany with the aid of [Ariadne GPS](http://www.ariadnegps.eu). It's a lovely reminder of the kind of impact our work can have on others. -Accessibility, like [internationalization](http://nshipster.com/nslocale/), is one of those topics that's difficult to get developers excited about. But as you know, NSHipster is _all about_ getting developers excited about this kind of stuff. Let's get started: +Accessibility, like [internationalization](http://nshipster.com/nslocale/), is one of those topics that's difficult to get developers excited about. But as you know, NSHipster is _all about_ getting developers excited about this kind of stuff. Let's get started: --- @@ -24,7 +23,7 @@ Accessibility, like [internationalization](http://nshipster.com/nslocale/), is o All of the standard views and controls in UIKit implement `UIAccessibility`, so applications are accessible by default. As a result, the task of improving the accessibility of your application is one of minor adjustments rather than wholesale re-implementation. -Here's a list of all of the properties in `UIAccessibility`: +Here's a list of all of the properties in `UIAccessibility`: - `accessibilityLabel` - `accessibilityHint` @@ -40,7 +39,7 @@ Here's a list of all of the properties in `UIAccessibility`: Before we go any further, take a couple minutes to play with VoiceOver, and understand how accessibility information is conveyed to the user. Open the Settings app, tap General, scroll to the bottom and tap Accessibility. In Accessibility, you'll see settings for assistive technologies grouped by category: Vision, Hearing, Learning, and Physical & Motor. -Tap VoiceOver, and then tap the VoiceOver switch to turn it on. An alert will pop up telling you that enabling VoiceOver changes the way you control your device. Dismiss the alert, and now VoiceOver is now enabled on your device. +Tap VoiceOver, and then tap the VoiceOver switch to turn it on. An alert will pop up telling you that enabling VoiceOver changes the way you control your device. Dismiss the alert, and now VoiceOver is now enabled on your device. Don't Panic--unlike setting your device to another language, there's no real risk of not being able to figure out how to turn VoiceOver off. @@ -64,7 +63,7 @@ So now that you have an idea of what you're working with, let's talk about imple If there was just one thing you could do to improve the accessibility of your app, paying attention to accessibility labels and hints of UI elements would be it. -Accessibility labels and hints tell VoiceOver what to say when selecting user interface elements. This information should be helpful, but concise. +Accessibility labels and hints tell VoiceOver what to say when selecting user interface elements. This information should be helpful, but concise. - **`accessibilityLabel`** identifies a user interface element. Every accessible view and control _must_ supply a label. - **`accessibilityHint`** describes the results of interacting with a user interface element. A hint should be supplied _only_ if the result of an interaction is not obvious from the element's label. @@ -118,7 +117,7 @@ For example, if a custom button control displays an image and plays a sound when As a general rule, the cleverness of a custom UI element is directly proportional to how gnarly its implementation is. Overlapping & invisible views, table view hacks, first responder shenanigans: sometimes it's better not to ask how something works. -However, when it comes to accessibility, it's important to set the record straight. +However, when it comes to accessibility, it's important to set the record straight. `accessibilityFrame` and `accessibilityActivationPoint` are used to define the accessible portions and locations of UI elements, without changing their outward appearance. @@ -128,12 +127,12 @@ As you try out your app in VoiceOver mode, try interacting with all of the eleme Accessibility value corresponds to the content of a user interface element. For a label, the value is its text. For a `UISlider`, it's the current numeric value represented by the control. -Want to know a quick way to improve the accessibility of your table views? Try setting the `accessibilityValue` property for cells to be a localized summary of the cell's content. For example, if you had a table view that showed status updates, you might set the `accessibilityLabel` to "Update from #{User Name}", and the `accessibilityValue` to the content of that status update. +Want to know a quick way to improve the accessibility of your table views? Try setting the `accessibilityValue` property for cells to be a localized summary of the cell's content. For example, if you had a table view that showed status updates, you might set the `accessibilityLabel` to "Update from #{User Name}", and the `accessibilityValue` to the content of that status update. --- Apple has done a great service to humanity in making accessibility a first-class citizen in its hardware and software. You're missing out on some of the best engineering, design, and technical writing that Apple has ever done if you ignore `UIAccessibility`. -Do yourself a favor and read the _excellent_ [Accessibility Programming Guide for iOS](http://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/iPhoneAccessibility/Introduction/Introduction.html). It only takes an hour or two to get the hang of everything. +Do yourself a favor and read the _excellent_ [Accessibility Programming Guide for iOS](http://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/iPhoneAccessibility/Introduction/Introduction.html). It only takes an hour or two to get the hang of everything. Who knows? You may end up changing someone's life because of it. diff --git a/2012-09-17-nscharacterset.md b/2012-09-17-nscharacterset.md index 3b7e318d..8496e143 100644 --- a/2012-09-17-nscharacterset.md +++ b/2012-09-17-nscharacterset.md @@ -1,7 +1,6 @@ --- layout: post title: NSCharacterSet - ref: "http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/nscharacterset_Class/Reference/Reference.html" framework: Foundation rating: 8.5 @@ -35,7 +34,7 @@ But a string implementation is only as good as the programmer who wields it. So - `whitespaceAndNewlineCharacterSet` - `whitespaceCharacterSet` -Contrary to what its name might suggest, `NSCharacterSet` has _nothing_ to do with `NSSet`. +Contrary to what its name might suggest, `NSCharacterSet` has _nothing_ to do with `NSSet`. However, `NSCharacterSet` _does_ have quite a bit in common with `NSIndexSet`, conceptually if not also in its underlying implementation. `NSIndexSet`, covered [previously](http://nshipster.com/nsindexset/), represents a sorted collection of unique unsigned integers. Unicode characters are likewise unique unsigned integers that roughly correspond to some orthographic representation. Thus, a character set like `NSCharacterSet +lowercaseCharacterSet` is analogous to the `NSIndexSet` of the integers 97 to 122. @@ -72,7 +71,7 @@ Now, it's not uncommon for the top-voted / accepted answer to not be the correct Without further ado, here are the 9 _incorrect_ answers: - "Use `stringByTrimmingCharactersInSet`" - _Only strips the leading and trailing whitespace, as you know._ -- "Replace ' ' with ''" - _This removes **all** of the spaces. Swing and a miss._ +- "Replace ' ' with ''" - _This removes **all** of the spaces. Swing and a miss._ - "Use a regular expression" - _Kinda works, except it doesn't handle leading and trailing whitespace. A regular expression is overkill anyway._ - "Use Regexp Lite" - _No seriously, regular expressions are completely unnecessary. And it's definitely not worth the external dependency._ - "Use OgreKit" - _Ditto any other third-party regexp library._ @@ -85,7 +84,7 @@ I don't mean to rag on any of the answerers personally--this is all to point out ## String Tokenization -**Do not use `NSCharacterSet` to tokenize strings.** +**Do not use `NSCharacterSet` to tokenize strings.** **Use `CFStringTokenizer` instead.** You can be forgiven for using `componentsSeparatedByCharactersInSet:` to clean up user input, but do this for anything more complex, and you'll be in a world of pain. @@ -129,7 +128,7 @@ NSMutableCharacterSet *skippedCharacters = [NSMutableCharacterSet punctuationCha }]; ~~~ -We first construct an `NSMutableCharacterSet` from the union of whitespace and punctuation characters. Telling `NSScanner` to skip these characters greatly reduces the logic necessary to parse values from the string. +We first construct an `NSMutableCharacterSet` from the union of whitespace and punctuation characters. Telling `NSScanner` to skip these characters greatly reduces the logic necessary to parse values from the string. `scanCharactersFromSet:` with the letters character set captures the start and (optional) end day of the week for each entry. `scanInteger` similarly captures the next contiguous integer value. diff --git a/2012-10-15-addressbookui.md b/2012-10-15-addressbookui.md index 343d6ddb..68554d1b 100644 --- a/2012-10-15-addressbookui.md +++ b/2012-10-15-addressbookui.md @@ -1,7 +1,6 @@ --- layout: post title: AddressBookUI - ref: "http://developer.apple.com/library/ios/#documentation/AddressBookUI/Reference/AddressBookUI_Framework/_index.html" framework: AddressBookUI rating: 6.2 @@ -30,7 +29,7 @@ The first argument for the function is a dictionary containing the address compo - `kABPersonAddressCountryKey` - `kABPersonAddressCountryCodeKey` -`kABPersonAddressCountryCodeKey` is an especially important attribute, as it determines which locale used to format the address string. If you are unsure of the country code, or one isn't provided with your particular data set, `NSLocale` may be able to help you out: +`kABPersonAddressCountryCodeKey` is an especially important attribute, as it determines which locale used to format the address string. If you are unsure of the country code, or one isn't provided with your particular data set, `NSLocale` may be able to help you out: ~~~{objective-c} [mutableAddressComponents setValue:[[[NSLocale alloc] initWithIdentifier:@"en_US"] objectForKey:NSLocaleCountryCode] forKey:(__bridge NSString *)kABPersonAddressCountryCodeKey]; diff --git a/2012-10-22-nslinguistictagger.md b/2012-10-22-nslinguistictagger.md index baae2fcf..b6f0e64b 100644 --- a/2012-10-22-nslinguistictagger.md +++ b/2012-10-22-nslinguistictagger.md @@ -1,7 +1,6 @@ --- layout: post title: NSLinguisticTagger - ref: "http://developer.apple.com/library/ios/#documentation/cocoa/reference/NSLinguisticTagger_Class/Reference/Reference.html" framework: Foundation rating: 9.7 @@ -11,7 +10,7 @@ description: "NSLinguisticTagger is a veritable Swiss Army Knife of linguistic f `NSLinguisticTagger` is a veritable Swiss Army Knife of linguistic functionality, with the ability to [tokenize](http://en.wikipedia.org/wiki/Tokenization) natural language strings into words, determine their part-of-speech & [stem](http://en.wikipedia.org/wiki/Word_stem), extract names of people, places, & organizations, and tell you the languages & respective [writing system](http://en.wikipedia.org/wiki/Writing_system) used in the string. -For most of us, this is far more power than we know what to do with. But perhaps this is just for lack sufficient opportunity to try. After all, almost every application deals with natural language in one way or another--perhaps `NSLinguisticTagger` could add a new level of polish, or enable brand new features entirely. +For most of us, this is far more power than we know what to do with. But perhaps this is just for lack sufficient opportunity to try. After all, almost every application deals with natural language in one way or another--perhaps `NSLinguisticTagger` could add a new level of polish, or enable brand new features entirely. --- @@ -36,14 +35,14 @@ tagger.string = question; This code would print the following: -> What: _Pronoun_ -> is: _Verb_ -> the: _Determiner_ -> weather: _Noun_ -> in: _Preposition_ +> What: _Pronoun_ +> is: _Verb_ +> the: _Determiner_ +> weather: _Noun_ +> in: _Preposition_ > San Francisco: _PlaceName_ -If we filter on nouns, verbs, and place name, we get `[is, weather, San Francisco]`. +If we filter on nouns, verbs, and place name, we get `[is, weather, San Francisco]`. Just based on this alone, or perhaps in conjunction with something like the [Latent Semantic Mapping](http://developer.apple.com/library/mac/#documentation/LatentSemanticMapping/Reference/LatentSemanticMapping_header_reference/Reference/reference.html) framework, we can conclude that a reasonable course of action would be to make an API request to determine the current weather conditions in San Francisco. diff --git a/2012-10-29-uilocalizedindexedcollation.md b/2012-10-29-uilocalizedindexedcollation.md index 5d64170d..d5edc411 100644 --- a/2012-10-29-uilocalizedindexedcollation.md +++ b/2012-10-29-uilocalizedindexedcollation.md @@ -1,12 +1,11 @@ --- layout: post title: UILocalizedIndexedCollation - ref: "http://developer.apple.com/library/ios/#documentation/iPhone/Reference/UILocalizedIndexedCollation_Class/UILocalizedIndexedCollation.html" framework: UIKit rating: 7.1 published: true -description: UITableView starts to become unwieldy once it gets to a few hundred rows. If users are reduced to frantically scratching at the screen like a cat playing Fruit Ninja in order to get at what they want… you may want to rethink your UI approach. +description: "UITableView starts to become unwieldy once it gets to a few hundred rows. If users are reduced to frantically scratching at the screen like a cat playing Fruit Ninja in order to get at what they want... you may want to rethink your UI approach." --- UITableView starts to become unwieldy once it gets to a few hundred rows. If users are reduced to frantically scratching at the screen like a [cat playing Fruit Ninja](http://www.youtube.com/watch?v=CdEBgZ5Y46U) in order to get at what they want... you may want to rethink your UI approach. diff --git a/2012-11-05-nsurlprotocol.md b/2012-11-05-nsurlprotocol.md index 51bcd036..404bbb40 100644 --- a/2012-11-05-nsurlprotocol.md +++ b/2012-11-05-nsurlprotocol.md @@ -1,12 +1,11 @@ --- layout: post title: NSURLProtocol - ref: "https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSURLProtocol_Class/Reference/Reference.html" framework: Foundation rating: 7.4 published: true -description: Foundation’s URL Loading System is something that every iOS developer would do well to buddy up with. And of all of networking classes and protocols of Foundation, NSURLProtocol is perhaps the most obscure and powerful. +description: "Foundation’s URL Loading System is something that every iOS developer would do well to buddy up with. And of all of networking classes and protocols of Foundation, NSURLProtocol is perhaps the most obscure and powerful." --- iOS is all about networking--whether it's reading or writing state to and from the server, offloading computation to a distributed system, or loading remote images, audio, and video from the cloud. @@ -161,11 +160,11 @@ Each instance of a `NSURLProtocol` subclass has a `client` property, which is th * `-URLProtocol:wasRedirectedToRequest:redirectResponse:` * `-URLProtocolDidFinishLoading:` -In your implementation of `-startLoading` and `-stopLoading`, you will need to send each delegate method to your `client` when appropriate. For something simple, this may mean sending several in rapid succession, but it's important nonetheless. +In your implementation of `-startLoading` and `-stopLoading`, you will need to send each delegate method to your `client` when appropriate. For something simple, this may mean sending several in rapid succession, but it's important nonetheless. ### Registering the Subclass with the URL Loading System -Finally, in order to actually use an `NSURLProtocol` subclass, it needs to be registered into the URL Loading System. +Finally, in order to actually use an `NSURLProtocol` subclass, it needs to be registered into the URL Loading System. When a request is loaded, each registered protocol is asked "hey, can you handle this request?". The first one to respond with `YES` with `+canInitWithRequest:` gets to handle the request. URL protocols are consulted in reverse order of when they were registered, so by calling `[NSURLProtocol registerClass:[MyURLProtocol class]];` in `-application:didFinishLoadingWithOptions:`, your protocol will have priority over any of the built-in protocols. diff --git a/2012-11-12-nsvaluetransformer.md b/2012-11-12-nsvaluetransformer.md index b8c74fc9..30967eb0 100644 --- a/2012-11-12-nsvaluetransformer.md +++ b/2012-11-12-nsvaluetransformer.md @@ -1,7 +1,6 @@ --- layout: post title: NSValueTransformer - ref: "https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSValueTransformer_Class/Reference/Reference.html" framework: Foundation rating: 6.6 @@ -9,7 +8,7 @@ published: true description: "Of all the Foundation classes, NSValueTransformer is perhaps the one that fared the worst in the shift from OS X to iOS. But you know what? It's ripe for a comeback. With a little bit of re-tooling and some recontextualization, this blast from the past could be the next big thing in your application." --- -Of all the Foundation classes, `NSValueTransformer` is perhaps the one that fared the worst in the shift from OS X to iOS. +Of all the Foundation classes, `NSValueTransformer` is perhaps the one that fared the worst in the shift from OS X to iOS. Why? Well, there are two reasons: @@ -32,11 +31,11 @@ A typical implementation would look something like this: #pragma mark - @implementation ClassNameTransformer -+ (Class)transformedValueClass { - return [NSString class]; ++ (Class)transformedValueClass { + return [NSString class]; } -+ (BOOL)allowsReverseTransformation { ++ (BOOL)allowsReverseTransformation { return NO; } @@ -69,8 +68,8 @@ Nothing [a little metaprogramming](https://github.com/mattt/TransformerKit/blob/ ~~~{objective-c} NSString * const TKCapitalizedStringTransformerName = @"TKCapitalizedStringTransformerName"; -[NSValueTransformer registerValueTransformerWithName:TKCapitalizedStringTransformerName - transformedValueClass:[NSString class] +[NSValueTransformer registerValueTransformerWithName:TKCapitalizedStringTransformerName + transformedValueClass:[NSString class] returningTransformedValueWithBlock:^id(id value) { return [value capitalizedString]; }]; @@ -85,7 +84,7 @@ Now with its sexy new getup, we start to form a better understanding of where th - `NSValueTransformers` are the ideal way to represent an ordered chain of fixed transformations. For instance, an app interfacing with a legacy system might transform user input through a succession of string transformations (trim whitespace, remove diacritics, and then capitalize letters) before sending it off to the mainframe. - Unlike blocks, `NSValueTransformer` encapsulates reversible transformations. Let's say you were wanted to map keys from a REST API representation into a Model object; you could create a reversible transformation that converted `snake_case` to `llamaCase` when initializing, and `llamaCase` to `snake_case` when serializing back to the server. - Another advantage over blocks is that `NSValueTransformer` subclasses can expose new properties that could be used to configure behavior in a particular way. Access to `ivars` also make it easier to cleanly memoize results, or do any necessary book-keeping along the way. -- Lest we forget, `NSValueTransformer` can be used with Core Data, as a way to encode and decode compound data types from blob fields. It seems to have fallen out of fashion over the years, but serializing simple collections in this way, for example, is an excellent strategy for information that isn't well-modeled as its own entity. Just don't serialize images to a database this way--that's generally a Bad Idea™. +- Lest we forget, `NSValueTransformer` can be used with Core Data, as a way to encode and decode compound data types from blob fields. It seems to have fallen out of fashion over the years, but serializing simple collections in this way, for example, is an excellent strategy for information that isn't well-modeled as its own entity. Just don't serialize images to a database this way--that's generally a Bad Idea™. And the list goes on. diff --git a/2012-11-19-ns_enum-ns_options.md b/2012-11-19-ns_enum-ns_options.md index 0bad3ac8..ee3e9053 100644 --- a/2012-11-19-ns_enum-ns_options.md +++ b/2012-11-19-ns_enum-ns_options.md @@ -1,7 +1,6 @@ --- layout: post title: "NS_ENUM & NS_OPTIONS" - ref: "https://developer.apple.com/library/mac/#releasenotes/General/APIDiffsMacOSX10_8/Foundation.html" framework: Foundation rating: 7.0 @@ -15,9 +14,9 @@ So, there are a few ways you could parse that, but for the purposes of this arti Yes--that non-objective part of our favorite Smalltalk-inspired hybrid language, C can be a great asset. It's fast, it's battle-tested, it's the very foundation of modern computing. But more than that, C is the escape hatch for when the Object-Oriented paradigm cracks under its own cognitive weight. -Static functions are nicer than shoe-horned class methods. -Enums are nicer than string constants. -Bitmasks are nicer than arrays of string constants. +Static functions are nicer than shoe-horned class methods. +Enums are nicer than string constants. +Bitmasks are nicer than arrays of string constants. Preprocessor directives are nicer than runtime hacks. A skilled Objective-C developer is able to gracefully switch between Objective and Procedural paradigms, and use each to their own advantage. @@ -38,7 +37,7 @@ Introduced in Foundation with iOS 6 / Mac OS X 10.8, the `NS_ENUM` and `NS_OPTIO `enum`, or enumerated value types, are the C way to define constants for fixed values, like days of the week, or available styles of table view cells. In an `enum` declaration, constants without explicit values will automatically be assigned values sequentially, starting from `0`. -There are several legal ways that `enum`s can be defined. What's confusing is that there are subtle functional differences between each approach, and without knowing any better, someone is just as likely to use them interchangeably. +There are several legal ways that `enum`s can be defined. What's confusing is that there are subtle functional differences between each approach, and without knowing any better, someone is just as likely to use them interchangeably. For instance: @@ -51,7 +50,7 @@ enum { }; ~~~ -...declares integer values, but no type. +...declares integer values, but no type. Whereas: @@ -102,7 +101,7 @@ This approach combines the best of all of the aforementioned approaches, and eve ## `NS_OPTIONS` -`enum` can also be used to define a [bitmask][1]. Using a convenient property of binary math, a single integer value can encode a combination of values all at once using the bitwise `OR` (`|`), and decoded with bitwise `AND` (`&`). Each subsequent value, rather than automatically being incremented by 1 from 0, are manually given a value with a bit offset: `1 << 0`, `1 << 1`, `1 << 2`, and so on. If you imagine the binary representation of a number, like `10110` for 22, each bit can be though to represent a single boolean. In UIKit, for example, `UIViewAutoresizing` is a bitmask that can represent any combination of flexible top, bottom, left, and right margins, or width and height. +`enum` can also be used to define a [bitmask][1]. Using a convenient property of binary math, a single integer value can encode a combination of values all at once using the bitwise `OR` (`|`), and decoded with bitwise `AND` (`&`). Each subsequent value, rather than automatically being incremented by 1 from 0, are manually given a value with a bit offset: `1 << 0`, `1 << 1`, `1 << 2`, and so on. If you imagine the binary representation of a number, like `10110` for 22, each bit can be though to represent a single boolean. In UIKit, for example, `UIViewAutoresizing` is a bitmask that can represent any combination of flexible top, bottom, left, and right margins, or width and height. Rather than `NS_ENUM`, bitmasks should now use the `NS_OPTIONS` macro. diff --git a/2012-11-26-nsorderedset.md b/2012-11-26-nsorderedset.md index 06c24647..ee793ab3 100644 --- a/2012-11-26-nsorderedset.md +++ b/2012-11-26-nsorderedset.md @@ -1,12 +1,11 @@ --- layout: post title: "NSOrderedSet" - ref: "http://developer.apple.com/library/mac/#documentation/Foundation/Reference/NSOrderedSet_Class/Reference/Reference.html" framework: Foundation rating: 6.2 published: true -description: "Why isn't `NSOrderedSet` a subclass of `NSSet`? The answer may surprise you." +description: "Why isn't NSOrderedSet a subclass of NSSet? The answer may surprise you." --- Here's a question: why isn't `NSOrderedSet` a subclass of `NSSet`? @@ -91,7 +90,7 @@ This was fantastic news for anyone using Core Data at the time, as it solved one In this way, `NSOrderedSet` is an _answer to our [prayers](http://bugreport.apple.com/)_. -Unfortunately, its very existence in Foundation has created something between an attractive nuisance and a red herring for API designers. +Unfortunately, its very existence in Foundation has created something between an attractive nuisance and a red herring for API designers. Although it is perfectly suited to that one particular use case in Core Data, `NSOrderedSet` is probably not a great choice for the majority of APIs that could potentially use it. In cases where a simple collection of objects is passed as a parameter, a simple `NSArray` does the trick--even if there is an implicit understanding that you shouldn't have duplicate entries. This is even more the case when order matters for a collection parameter--just use `NSArray` (there should be code to deal with duplicates in the implementation anyway). If uniqueness does matter, or the semantics of sets makes sense for a particular method, `NSSet` has and remains a great choice. diff --git a/2012-12-03-kvc-collection-operators.md b/2012-12-03-kvc-collection-operators.md index ee52efdb..2f27aa4b 100644 --- a/2012-12-03-kvc-collection-operators.md +++ b/2012-12-03-kvc-collection-operators.md @@ -1,7 +1,6 @@ --- layout: post title: "KVC Collection Operators" - ref: "http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/KeyValueCoding/Articles/CollectionOperators.html" framework: Foundation rating: 7.9 @@ -9,7 +8,7 @@ published: true description: "Rubyists laugh at Objective-C’s bloated syntax. Although we lost a few pounds over the summer with our sleek new object literals, those Red-headed bullies still taunt us with their map one-liners and their fancy Symbol#to_proc. Fortunately, Key-Value Coding has an ace up its sleeves." --- -Rubyists laugh at Objective-C's bloated syntax. +Rubyists laugh at Objective-C's bloated syntax. Although we lost a few pounds over the summer with our [sleek new object literals](http://nshipster.com/at-compiler-directives/), those Red-headed bullies still taunt us with their `map` one-liners and their fancy [`Symbol#to_proc`](http://pragdave.pragprog.com/pragdave/2005/11/symbolto_proc.html). @@ -25,7 +24,7 @@ for (Employee *employee in employees) { double averageSalary = totalSalary / [employees count]; ~~~ -Meh. +Meh. Fortunately, [Key-Value Coding](https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/KeyValueCoding/Articles/KeyValueCoding.html) gives us a much more concise--almost Ruby-like--way to do this: @@ -134,7 +133,7 @@ This would be useful if we were to, for example, compare the inventory of severa _Example_: ~~~{objective-c} -[@[appleStoreInventory, verizonStoreInventory] valueForKeyPath:@"@distinctUnionOfArrays.name"]; // "iPhone 5", "iPad Mini", "MacBook Pro" +[@[appleStoreInventory, verizonStoreInventory] valueForKeyPath:@"@distinctUnionOfArrays.name"]; // "iPhone 5", "iPad Mini", "MacBook Pro" ~~~ --- @@ -145,7 +144,7 @@ Curiously, [Apple's documentation on KVC collection operators](http://developer. > **Note**: It is not currently possible to define your own collection operators. -This makes sense to spell out, since that's what most people are thinking about once they see collection operators for the first time. +This makes sense to spell out, since that's what most people are thinking about once they see collection operators for the first time. However, as it turns out, it _is_ actually possible, with a little help from our friend, `objc/runtime`. @@ -171,6 +170,6 @@ Is this insanely cool? You bet! This clever example has shown a possible directi --- -KVC Collection Operators are a must-know for anyone who wants to save a few extra lines of code and look cool in the process. +KVC Collection Operators are a must-know for anyone who wants to save a few extra lines of code and look cool in the process. While scripting languages like Ruby boast considerably more flexibility in its one-liner capability, perhaps we should take a moment to celebrate the restraint built into Objective-C and Collection Operators. After all, Ruby is hella slow, amiright? </troll> diff --git a/2012-12-10-instancetype.md b/2012-12-10-instancetype.md index 86f41f3e..964cea88 100644 --- a/2012-12-10-instancetype.md +++ b/2012-12-10-instancetype.md @@ -1,7 +1,6 @@ --- layout: post title: instancetype - ref: "http://clang.llvm.org/docs/LanguageExtensions.html#objc_instancetype" framework: Foundation rating: 7.3 @@ -83,7 +82,7 @@ Whether or not this becomes an accepted convention in Objective-C, it's fascinat --- -`instancetype` is just one of the many language extensions to Objective-C, with more being added with each new release. +`instancetype` is just one of the many language extensions to Objective-C, with more being added with each new release. Know it, love it. diff --git a/2012-12-17-cggeometry.md b/2012-12-17-cggeometry.md index 63050205..f1296858 100644 --- a/2012-12-17-cggeometry.md +++ b/2012-12-17-cggeometry.md @@ -1,12 +1,11 @@ --- layout: post title: CGGeometry - ref: "https://developer.apple.com/library/mac/#documentation/graphicsimaging/reference/CGGeometry/Reference/reference.html" framework: CoreGraphics rating: 8.0 published: true -description: "Unless you were a Math Geek or an Ancient Greek, Geometry was probably not your favorite subject in high school. No, chances are that you were that kid in class who dutifully programmed all of the necessary formulæ into your TI-8X calculator. Keeping in the tradition of doing the least amount of math possible, here are some semi-obscure CoreGraphics functions to make your job easier." +description: "Unless you were a Math Geek or an Ancient Greek, Geometry was probably not your favorite subject in high school. No, chances are that you were that kid in class who dutifully programmed all of the necessary formulae into your TI-8X calculator. Keeping in the tradition of doing the least amount of math possible, here are some semi-obscure CoreGraphics functions to make your job easier." --- Unless you were a Math Geek or an Ancient Greek, Geometry was probably not your favorite subject in high school. No, chances are that you were that kid in class who dutifully programmed all of the necessary formulæ into your TI-8X calculator. @@ -44,7 +43,7 @@ CGRect CGRectOffset( ) ~~~ -Consider using this anytime you're changing the origin of a rectangle. Not only can it save a line of code when changing both the horizontal and vertical position, but more importantly, it represents the translation more semantically than manipulating the origin values individually. +Consider using this anytime you're changing the origin of a rectangle. Not only can it save a line of code when changing both the horizontal and vertical position, but more importantly, it represents the translation more semantically than manipulating the origin values individually. ### `CGRectInset` @@ -58,9 +57,9 @@ CGRect CGRectInset( ) ~~~ -Want to make a view-within-a-view look good? Give it a nice 10pt padding with `CGRectInset`. Keep in mind that the rectangle will be resized around its center by ± `dx` on its left and right edge (for a total of `2 × dx`), and ± `dy` on its top and bottom edge (for a total of `2 × dy`). +Want to make a view-within-a-view look good? Give it a nice 10pt padding with `CGRectInset`. Keep in mind that the rectangle will be resized around its center by ± `dx` on its left and right edge (for a total of `2 × dx`), and ± `dy` on its top and bottom edge (for a total of `2 × dy`). -If you're using `CGRectInset` as a convenience function for resizing a rectangle, it is common to chain this with `CGRectOffset` by passing the result of `CGRectInset` as the `rect` argument in `CGRectOffset`. +If you're using `CGRectInset` as a convenience function for resizing a rectangle, it is common to chain this with `CGRectOffset` by passing the result of `CGRectInset` as the `rect` argument in `CGRectOffset`. ### `CGRectIntegral` @@ -78,7 +77,7 @@ It's important that `CGRect` values all are rounded to the nearest whole point. As a rule of thumb, if you are performing any operations that could result in fractional point values (e.g. division, `CGGetMid[X|Y]`, or `CGRectDivide`), use `CGRectIntegral` to normalize rectangles to be set as a view frame. -> † Technically, since the coordinate system operates in terms of points, Retina screens, which have 4 pixels for every point, can draw `± 0.5f` point values on odd pixels without blurriness. +> † Technically, since the coordinate system operates in terms of points, Retina screens, which have 4 pixels for every point, can draw `± 0.5f` point values on odd pixels without blurriness. Value Helper Functions ---------------------- @@ -94,7 +93,7 @@ These functions provide a shorthand way to calculate interesting dimensional val - `CGRectGetMaxX` - `CGRectGetMaxY` -These six functions return the minimum, middle, or maximum `x` or `y` value for a rectangle, taking the form: +These six functions return the minimum, middle, or maximum `x` or `y` value for a rectangle, taking the form: ~~~{objective-c} CGFloat CGRectGet[Min|Mid|Max][X|Y] ( @@ -122,7 +121,7 @@ CGFloat CGRectGetWidth ( ) ~~~ -Much like the previous functions, `CGRectGetWidth` & `CGRectGetHeight` are often preferable to returning the corresponding member of a `CGRect`'s `size`. While it's not extremely competitive in terms of character savings, remember that semantic clarity trumps brevity every time. +Much like the previous functions, `CGRectGetWidth` & `CGRectGetHeight` are often preferable to returning the corresponding member of a `CGRect`'s `size`. While it's not extremely competitive in terms of character savings, remember that semantic clarity trumps brevity every time. Identities ---------- @@ -162,7 +161,7 @@ void CGRectDivide( `CGRectDivide` divides a rectangle into two components in the following way: -- Take a rectangle and choose an `edge` (left, right, top, or bottom). +- Take a rectangle and choose an `edge` (left, right, top, or bottom). - Measure out an `amount` from that edge. - Everything from the `edge` to the measured `amount` is stored in the rectangle referenced in the `slice` argument. - The rest of the original rectangle is stored in the `remainder` out argument. diff --git a/2013-01-07-nil.md b/2013-01-07-nil.md index 0b735cee..93cb49f0 100644 --- a/2013-01-07-nil.md +++ b/2013-01-07-nil.md @@ -1,10 +1,9 @@ --- layout: post title: "nil / Nil / NULL / NSNull" - ref: "https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/NumbersandValues/Articles/Null.html" framework: Objective-C -published: true +description: "Understanding the concept of nothingness is as much a philosophical issue as it is a pragmatic one. We are inhabitants of a universe of somethings, yet reason in a logical universe of existential uncertainties. As a physical manifestation of a logical system, computers are faced with the intractable problem of how to represent nothing with something." --- Understanding the concept of nothingness is as much a philosophical issue as it is a pragmatic one. We are inhabitants of a universe of _somethings_, yet reason in a logical universe of existential uncertainties. As a physical manifestation of a logical system, computers are faced with the intractable problem of how to represent _nothing_ with _something_. @@ -15,7 +14,7 @@ C represents _nothing_ as `0` for primitive values, and `NULL` for pointers ([wh Objective-C builds on C's representation of _nothing_ by adding `nil`. `nil` is an _object_ pointer to nothing. Although semantically distinct from `NULL`, they are technically equivalent to one another. -On the framework level, Foundation defines `NSNull`, which defines a class method, `+null`, which returns the singleton `NSNull` object. `NSNull` is different from `nil` or `NULL`, in that it is an actual object, rather than a zero value. +On the framework level, Foundation defines `NSNull`, which defines a class method, `+null`, which returns the singleton `NSNull` object. `NSNull` is different from `nil` or `NULL`, in that it is an actual object, rather than a zero value. Additionally, in [Foundation/NSObjCRuntime.h](https://gist.github.com/4469665), `Nil` is defined as a _class_ pointer to nothing. This lesser-known title-case cousin of `nil` doesn't show up much very often, but it's at least worth noting. @@ -23,7 +22,7 @@ Additionally, in [Foundation/NSObjCRuntime.h](https://gist.github.com/4469665), Newly-`alloc`'d `NSObject`s start life with [their contents set to `0`](https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html). This means that all pointers that object has to other objects begin as `nil`, so it's unnecessary to, for instance, set `self.(association) = nil` in `init` methods. -Perhaps the most notable behavior of `nil`, though, is that it can have messages sent to it. +Perhaps the most notable behavior of `nil`, though, is that it can have messages sent to it. In other languages, like C++, this would crash your program, but in Objective-C, invoking a method on `nil` returns a zero value. This greatly simplifies expressions, as it obviates the need to check for `nil` before doing anything: diff --git a/2013-01-14-__attribute__.md b/2013-01-14-__attribute__.md index e7b52cbc..497a00d8 100644 --- a/2013-01-14-__attribute__.md +++ b/2013-01-14-__attribute__.md @@ -1,10 +1,9 @@ --- layout: post title: "__attribute__" - ref: "http://clang.llvm.org/docs/LanguageExtensions.html" framework: "Objective-C" -published: true +description: "A recurring theme of this publication has been the importance of a healthy relationship with the compiler. Like any craft, one's effectiveness as a practitioner is contingent on how they treat their tools. Take good care of them, and they'll take good care of you." --- A recurring theme of this publication has been the importance of a healthy relationship with the compiler. Like any craft, one's effectiveness as a practitioner is contingent on how they treat their tools. Take good care of them, and they'll take good care of you. diff --git a/2013-01-21-nslocalizedstring.md b/2013-01-21-nslocalizedstring.md index bfc3ef73..5c0f335a 100644 --- a/2013-01-21-nslocalizedstring.md +++ b/2013-01-21-nslocalizedstring.md @@ -1,11 +1,9 @@ --- layout: post title: NSLocalizedString - ref: "https://developer.apple.com/library/mac/#documentation/cocoa/reference/foundation/miscellaneous/foundation_functions/reference/reference.html" framework: Foundation rating: 9.5 -published: true description: "Strings are perhaps the most versatile data type in computing. They're passed around as symbols, used to encode numeric values, associate values to keys, represent resource paths, store linguistic content, and format information. Having a strong handle on user-facing strings is essential to making a great user experience." --- diff --git a/2013-01-28-nsvalue.md b/2013-01-28-nsvalue.md index bd005d83..296afe77 100644 --- a/2013-01-28-nsvalue.md +++ b/2013-01-28-nsvalue.md @@ -1,11 +1,9 @@ --- layout: post title: NSValue - ref: "https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSValue_Class/Reference/Reference.html" framework: Foundation rating: 6.0 -published: true description: "Boxing is the process of encapsulating scalars and value types with an object container, and is primarily used to store those values in collection objects—namely arrays and dictionaries. In Foundation, the reigning featherweight champion of boxing is NSValue." --- @@ -27,7 +25,7 @@ Boxing is the process of encapsulating scalars (`int`, `double`, `BOOL`, etc.) a `NSValue` is a simple container for a single C or Objective-C data value. It can hold scalars and value types, as well as pointers and object IDs. -While boxing is an admittedly dry subject matter, there are two methods in particular that are worth noting: `+valueWithBytes:objCType:`, which serves as a primer for working with `NSValue`, and +While boxing is an admittedly dry subject matter, there are two methods in particular that are worth noting: `+valueWithBytes:objCType:`, which serves as a primer for working with `NSValue`, and `+valueWithNonretainedObject:`, which is surprisingly useful for being relatively unknown. ## `valueWithBytes:objCType:` @@ -69,9 +67,9 @@ typedef struct example { If you already knew about `valueWithNonretainedObject`, you should be nodding with a knowing grin. If you didn't, you're likely staring incredulously with mouth agape. Or if not, you will be soon. -In short, `valueWithNonretainedObject:` allows objects to be added to a collection, without the need for satisfying ``. +In short, `valueWithNonretainedObject:` allows objects to be added to a collection, without the need for satisfying ``. -It's something that comes up occasionally, working with objects that can't be directly added to an `NSArray` or `NSDictionary`. Without knowing about `valueWithNonretainedObject:`, this would be something that would throw off your entire game—especially if you're just starting out in Objective-C. +It's something that comes up occasionally, working with objects that can't be directly added to an `NSArray` or `NSDictionary`. Without knowing about `valueWithNonretainedObject:`, this would be something that would throw off your entire game—especially if you're just starting out in Objective-C. But now you're in the know. You won't be stifled by such pedestrian concerns. You need not grope around for answers with [`NSPointerArray`](https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSPointerArray_Class/Introduction/Introduction.html) or [`NSMapTable`](https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/NSMapTable_class/Reference/NSMapTable.html#//apple_ref/occ/cl/NSMapTable). Today is a new day. diff --git a/2013-02-04-type-encodings.md b/2013-02-04-type-encodings.md index 19bf9e43..e74bf9a6 100644 --- a/2013-02-04-type-encodings.md +++ b/2013-02-04-type-encodings.md @@ -1,7 +1,6 @@ --- layout: post title: Type Encodings - ref: "https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html" framework: "Objective-C" rating: 7.8 @@ -9,13 +8,13 @@ published: true description: "From number stations and numerology to hieroglyphics and hobo codes, there is something truly fascinating about finding meaning that hides in plain sight. Though hidden messages in and of themselves are rarely useful or particularly interesting, it's the thrill of the hunt that piques our deepest curiosities." --- -From [number stations](http://en.wikipedia.org/wiki/Numbers_station) and [numerology](http://en.wikipedia.org/wiki/Numerology) to [hieroglyphs](http://en.wikipedia.org/wiki/Egyptian_hieroglyphs) and [hobo codes](http://en.wikipedia.org/wiki/Hobo#Hobo_.28sign.29_code), there is something truly fascinating about finding meaning that hides in plain sight. Though hidden messages in and of themselves are rarely useful or particularly interesting, it's the thrill of the hunt that piques our deepest curiosities. +From [number stations](http://en.wikipedia.org/wiki/Numbers_station) and [numerology](http://en.wikipedia.org/wiki/Numerology) to [hieroglyphs](http://en.wikipedia.org/wiki/Egyptian_hieroglyphs) and [hobo codes](http://en.wikipedia.org/wiki/Hobo#Hobo_.28sign.29_code), there is something truly fascinating about finding meaning that hides in plain sight. Though hidden messages in and of themselves are rarely useful or particularly interesting, it's the thrill of the hunt that piques our deepest curiosities. It is in this spirit that we take a look at [Objective-C Type Encodings](https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html) in this week's edition of NSHipster. --- -[Last week](http://nshipster.com/nsvalue/), in a discussion about `NSValue`, there was mention of `+valueWithBytes:objCType:`, whose second parameter should be created with the Objective-C `@encode()` compiler directive. +[Last week](http://nshipster.com/nsvalue/), in a discussion about `NSValue`, there was mention of `+valueWithBytes:objCType:`, whose second parameter should be created with the Objective-C `@encode()` compiler directive. `@encode`, one of the [`@` Compiler Directives](http://nshipster.com/at-compiler-directives/), returns a C string that encodes the internal representation of a given type (e.g., `@encode(int)` → `i`), similar to the ANSI C `typeof` operator. Apple's Objective-C runtime uses type encodings internally to help facilitate message dispatching. @@ -212,13 +211,13 @@ These are the type qualifiers for methods declared in a protocol: For anyone familiar with [NSDistantObject](https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSDistantObject_Class/Reference/Reference.html), you'll doubtless recognize these as a vestige of [Distributed Objects](https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/DistrObjects/DistrObjects.html#//apple_ref/doc/uid/10000102i). -Although DO has fallen out of fashion in the age of iOS, it was an interprocess messaging protocol used between Cocoa applications--even running on different machines on the network. Under these constraints, there were benefits to be had from the additional context. +Although DO has fallen out of fashion in the age of iOS, it was an interprocess messaging protocol used between Cocoa applications--even running on different machines on the network. Under these constraints, there were benefits to be had from the additional context. For example, parameters in distributed object messages were passed as proxies by default. In situations where proxying would be unnecessarily inefficient, the `bycopy` qualifier could be added to make sure a full copy of the object was sent. Also by default, parameters were `inout`, signifying that objects needed to be sent back and forth when sending the message. By specifying a parameter as `in` or `out` instead, the application could avoid the round-trip overhead. --- -So what do we gain from our newfound understanding of Objective-C Type Encodings? +So what do we gain from our newfound understanding of Objective-C Type Encodings? Honestly, not that much (unless you're doing any crazy metaprogramming). But as we said from the very outset, there is wisdom in the pursuit of deciphering secret messages. diff --git a/2013-02-11-nsurlcache.md b/2013-02-11-nsurlcache.md index 9d654d63..1ae10e87 100644 --- a/2013-02-11-nsurlcache.md +++ b/2013-02-11-nsurlcache.md @@ -1,10 +1,10 @@ --- layout: post title: NSURLCache - ref: "https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSURLCache_Class/Reference/Reference.html" framework: Foundation rating: 8.7 +description: "NSURLCache provides a composite in-memory and on-disk caching mechanism for URL requests to your application. As part of Foundation's URL Loading System, any request loaded through NSURLConnection will be handled by NSURLCache." --- `NSURLCache` provides a composite in-memory and on-disk caching mechanism for URL requests to your application. As part of Foundation's [URL Loading System](https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/URLLoadingSystem/URLLoadingSystem.html#//apple_ref/doc/uid/10000165i), any request loaded through `NSURLConnection` will be handled by `NSURLCache`. @@ -16,11 +16,11 @@ When a request has finished loading its response from the server, a cached respo In order to take advantage of `NSURLCache`, a shared URL cache must be initialized and set. This should be done in `-application:didFinishLaunchingWithOptions:` on iOS, or `–applicationDidFinishLaunching:` on Mac OS X: ~~~{objective-c} -- (BOOL)application:(UIApplication *)application - didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +- (BOOL)application:(UIApplication *)application + didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - NSURLCache *URLCache = [[NSURLCache alloc] initWithMemoryCapacity:4 * 1024 * 1024 - diskCapacity:20 * 1024 * 1024 + NSURLCache *URLCache = [[NSURLCache alloc] initWithMemoryCapacity:4 * 1024 * 1024 + diskCapacity:20 * 1024 * 1024 diskPath:nil]; [NSURLCache setSharedURLCache:URLCache]; } @@ -39,7 +39,7 @@ Caching policies are specified in both the request (by the client) and in the re - `NSURLRequestReturnCacheDataDontLoad`: Existing cache data should be used, regardless of its age or expiration date. If there is no existing data in the cache corresponding to the request, no attempt is made to load the data from the originating source, and the load is considered to have failed, (i.e. "offline" mode). - `NSURLRequestReloadRevalidatingCacheData`: Existing cache data may be used provided the origin source confirms its validity, otherwise the URL is loaded from the origin source. -It may not surprise you that these values are poorly understood and often confused with one another. +It may not surprise you that these values are poorly understood and often confused with one another. Adding to the confusion is the fact that `NSURLRequestReloadIgnoringLocalAndRemoteCacheData` and `NSURLRequestReloadRevalidatingCacheData` [_aren't even implemented_](https://gist.github.com/mattt/4753073#file-nsurlrequest-h-L95-L108)! ([Link to Radar](http://openradar.appspot.com/radar?id=1755401)). @@ -114,7 +114,7 @@ Once the server response has been received, the `NSURLConnection` delegate has a In `-connection:willCacheResponse:`, the `cachedResponse` object has been automatically created from the result of the URL connection. Because there is no mutable counterpart to `NSCachedURLResponse`, in order to change anything about `cachedResponse`, a new object must be constructed, passing any modified values into `–initWithResponse:data:userInfo:storagePolicy:`, for instance: ~~~{objective-c} -- (NSCachedURLResponse *)connection:(NSURLConnection *)connection +- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse { NSMutableDictionary *mutableUserInfo = [[cachedResponse userInfo] mutableCopy]; @@ -133,7 +133,7 @@ In `-connection:willCacheResponse:`, the `cachedResponse` object has been automa If `-connection:willCacheResponse:` returns `nil`, the response will not be cached. ~~~{objective-c} -- (NSCachedURLResponse *)connection:(NSURLConnection *)connection +- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse { return nil; @@ -146,7 +146,7 @@ When left unimplemented, `NSURLConnection` will simply use the cached response t Just like its unrelated-but-similarly-named cohort, [`NSCache`](http://nshipster.com/nscache/), `NSURLCache` is not without some peculiarities. -As of iOS 5, disk caching is supported, but only for HTTP, not HTTPS, requests (though iOS 6 added support for this). Peter Steinberger [wrote an excellent article on this subject](http://petersteinberger.com/blog/2012/nsurlcache-uses-a-disk-cache-as-of-ios5/), after digging into the internals while implementing [his own NSURLCache subclass](https://github.com/steipete/SDURLCache). +As of iOS 5, disk caching is supported, but only for HTTP, not HTTPS, requests (though iOS 6 added support for this). Peter Steinberger [wrote an excellent article on this subject](http://petersteinberger.com/blog/2012/nsurlcache-uses-a-disk-cache-as-of-ios5/), after digging into the internals while implementing [his own NSURLCache subclass](https://github.com/steipete/SDURLCache). [Another article by Daniel Pasco at Black Pixel](http://blackpixel.com/blog/2012/05/caching-and-nsurlconnection.html) describes some unexpected default behavior when communicating with servers that don't set cache headers. diff --git a/2013-02-18-reactivecocoa.md b/2013-02-18-reactivecocoa.md index 3ffcd850..ab9830f3 100644 --- a/2013-02-18-reactivecocoa.md +++ b/2013-02-18-reactivecocoa.md @@ -1,7 +1,6 @@ --- layout: post title: ReactiveCocoa - ref: "https://github.com/ReactiveCocoa/ReactiveCocoa" framework: "Open Source" rating: 9.5 diff --git a/2013-02-25-nsassertionhandler.md b/2013-02-25-nsassertionhandler.md index c17454de..4a389e44 100644 --- a/2013-02-25-nsassertionhandler.md +++ b/2013-02-25-nsassertionhandler.md @@ -1,17 +1,17 @@ --- layout: post title: NSAssertionHandler - ref: "https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSAssertionHandler_Class/Reference/Reference.html" framework: Foundation rating: 5.6 +description: "Programming incorporates numerous disciplines of human reasoning, from high-level discourse and semantics—the story we tell each other to explain how a system works—to the mathematical and philosophical machinery that underpins everything." --- "When at first you don't succeed, use an object-oriented injection point to override default exception handling." This is the sort of advice you would have learned at mother's knee if you were raised by `NSAssertionHandler`. -Programming incorporates numerous disciplines of human reasoning, from high-level discourse and semantics—the "story" we tell each other to explain how a system works—to the mathematical and philosophical machinery that underpins everything. +Programming incorporates numerous disciplines of human reasoning, from high-level discourse and semantics—the "story" we tell each other to explain how a system works—to the mathematical and philosophical machinery that underpins everything. -Assertions are a concept borrowed from classical logic. In logic, assertions are statements about propositions within a proof. In programming, assertions denote assumptions the programmer has made about the application at the place where they are declared. +Assertions are a concept borrowed from classical logic. In logic, assertions are statements about propositions within a proof. In programming, assertions denote assumptions the programmer has made about the application at the place where they are declared. When used in the capacity of preconditions and postconditions, which describe expectations about the state of the code at the beginning and end of execution of a method or function, assertions form a [contract](http://en.wikipedia.org/wiki/Design_by_contract). Assertions can also be used to enforce conditions at run-time, in order to prevent execution when certain preconditions fail. @@ -26,15 +26,15 @@ Objective-C combines C-style assertion macros with an object-oriented approach t Foundation [defines](https://gist.github.com/mattt/5031388#file-nsassertionhandler-m-L50-L56) two pairs of assertion macros: - `NSAssert` / `NSCAssert` -- `NSParameterAssert` / `NSCParameterAssert` +- `NSParameterAssert` / `NSCParameterAssert` -Foundation makes two distinctions in their assertion handler APIs that are both semantic and functional. +Foundation makes two distinctions in their assertion handler APIs that are both semantic and functional. The first distinction is between a general assertion (`NSAssert`) and a parameter assertion (`NSParameterAssert`). As a rule of thumb, methods / functions should use `NSParameterAssert` / `NSCParameterAssert` statements at the top of methods to enforce any preconditions about the input values; in all other cases, use `NSAssert` / `NSCAssert`. -The second is the difference between C and Objective-C assertions: `NSAssert` should only be used in an Objective-C context (i.e. method implementations), whereas `NSCAssert` should only be used in a C context (i.e. functions). +The second is the difference between C and Objective-C assertions: `NSAssert` should only be used in an Objective-C context (i.e. method implementations), whereas `NSCAssert` should only be used in a C context (i.e. functions). -- When a condition in `NSAssert` or `NSParameterAssert` fails, `-handleFailureInMethod:object:file:lineNumber:description:` is called in the assertion handler. +- When a condition in `NSAssert` or `NSParameterAssert` fails, `-handleFailureInMethod:object:file:lineNumber:description:` is called in the assertion handler. - When a condition in `NSCAssert` or `NSCParameterAssert` fails, `-handleFailureInFunction:file:lineNumber:description:` is called in the assertion handler. Additionally, there are variations of `NSAssert` / `NSCAssert`, from `NSAssert1` ... `NSAssert5`, which take their respective number of arguments to use in a `printf`-style format string. @@ -63,18 +63,18 @@ And while Foundation assertion macros are extremely useful in their own right— ~~~{objective-c} @implementation LoggingAssertionHandler -- (void)handleFailureInMethod:(SEL)selector - object:(id)object - file:(NSString *)fileName - lineNumber:(NSInteger)line +- (void)handleFailureInMethod:(SEL)selector + object:(id)object + file:(NSString *)fileName + lineNumber:(NSInteger)line description:(NSString *)format, ... { NSLog(@"NSAssert Failure: Method %@ for object %@ in %@#%i", NSStringFromSelector(selector), object, fileName, line); } -- (void)handleFailureInFunction:(NSString *)functionName - file:(NSString *)fileName - lineNumber:(NSInteger)line +- (void)handleFailureInFunction:(NSString *)functionName + file:(NSString *)fileName + lineNumber:(NSInteger)line description:(NSString *)format, ... { NSLog(@"NSCAssert Failure: Function (%@) in %@#%i", functionName, fileName, line); @@ -91,11 +91,11 @@ didFinishLaunchingWithOptions:`. ### AppDelegate.m ~~~{objective-c} -- (BOOL)application:(UIApplication *)application +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSAssertionHandler *assertionHandler = [[LoggingAssertionHandler alloc] init]; - [[[NSThread currentThread] threadDictionary] setValue:assertionHandler + [[[NSThread currentThread] threadDictionary] setValue:assertionHandler forKey:NSAssertionHandlerKey]; // ... diff --git a/2013-03-04-backrow.md b/2013-03-04-backrow.md index f1ff0683..232c726b 100644 --- a/2013-03-04-backrow.md +++ b/2013-03-04-backrow.md @@ -1,7 +1,6 @@ --- layout: post title: Back Row - ref: "http://appletv.ericiii.net/5.2/annotated.php" framework: "" rating: 8.0 @@ -14,13 +13,13 @@ Everything is in place for Apple to kick-start the next generation of television But rather than simply wait for the future, we can take matters into our own hands, with [class-dump](https://github.com/nygard/class-dump) and some reverse-engineering chutzpah. -Voila! [A class dump of the Apple TV private framework headers](http://appletv.ericiii.net/5.2/annotated.php) +Voila! [A class dump of the Apple TV private framework headers](http://appletv.ericiii.net/5.2/annotated.php) That's right: this edition of NSHipster covers a topic so obscure, _it doesn't even officially exist_. --- -Back Row is a private framework used in the Apple TV user experience. Its name is a reference to [Front Row][1], an application included in Mac OS X 10.4 – 10.6 that paired with the Apple Remote to transform the Mac into a couch-friendly media center. +Back Row is a private framework used in the Apple TV user experience. Its name is a reference to [Front Row][1], an application included in Mac OS X 10.4 – 10.6 that paired with the Apple Remote to transform the Mac into a couch-friendly media center. The original Apple TV could be described as a "short Mac Mini", which ran a modified version of Front Row on a stripped-down build of Mac OS X. It was little more than an iTunes remote, streaming content from a shared iTunes library on a separate computer. @@ -28,7 +27,7 @@ The second generation of the device took a smaller form factor, shifting its foc ## Back Row & UIKit -Back Row (name prefix: `BR`) bears a striking resemblance to UIKit, with many of the familiar metaphors and conventions of iOS development. +Back Row (name prefix: `BR`) bears a striking resemblance to UIKit, with many of the familiar metaphors and conventions of iOS development. Here's a brief list of some Back Row classes & protocols and their UIKit equivalents: @@ -75,7 +74,7 @@ Here's a brief list of some Back Row classes & protocols and their UIKit equival ![Apple TV Home Screen](http://nshipster.s3.amazonaws.com/backrow-home-screen.jpg) -In the current Apple TV interface, the home screen contains a grid of rectangular icons, similar to the home screen on iOS. Each icon corresponds to an _appliance_. +In the current Apple TV interface, the home screen contains a grid of rectangular icons, similar to the home screen on iOS. Each icon corresponds to an _appliance_. Why an appliance and not an application? An appliance is more limited in what it can do as compared to an application. On iPhone or iPad, applications range from social media clients and photo tools to games and musical instruments. Whereas on Apple TV, an appliance consists of a series of remote-friendly menus, lists, and grids, which ultimately lead to media playback of some form. When it comes to appliances, (audio / video) content is king. @@ -87,7 +86,7 @@ Pushing and popping controllers is managed by a shared `BRControllerStack`. When ![Apple TV YouTube](http://nshipster.s3.amazonaws.com/backrow-youtube.jpg) -A typical controller consists of a menu list on the right, with some kind of complimentary view on the left. +A typical controller consists of a menu list on the right, with some kind of complimentary view on the left. On top-level controllers, this sometimes takes the form of a `BRMarqueeStack`, which animates a Cover-Flow-style sequence of preview images for each of the controllers. diff --git a/2013-03-25-search-kit.md b/2013-03-25-search-kit.md index 837acfc9..38482eca 100644 --- a/2013-03-25-search-kit.md +++ b/2013-03-25-search-kit.md @@ -1,11 +1,9 @@ --- layout: post title: Search Kit - ref: "https://developer.apple.com/library/mac/#documentation/UserExperience/Reference/SearchKit/Reference/reference.html" framework: CoreServices rating: 9.1 -published: true description: "Search Kit is a C framework for searching and indexing content in human languages. It supports matching on phrase or partial word, including logical & wildcard operators, and can rank results by relevance. Search Kit also provides document summarization, which is useful for generating representative excerpts. And best of all: it's thread-safe." --- diff --git a/2013-04-08-bool.md b/2013-04-08-bool.md index 63a8161a..295703b7 100644 --- a/2013-04-08-bool.md +++ b/2013-04-08-bool.md @@ -1,10 +1,8 @@ --- layout: post title: "BOOL / bool / Boolean / NSCFBoolean" - ref: "https://developer.apple.com/library/mac/#documentation/CoreFoundation/Reference/CFBooleanRef/Reference/reference.html" framework: Objective-C -published: true description: "Once again, encoding our logical universe into the cold, calculating bytecode of computers forces us to deal with these questions one way or another. And as you'll see from our discussion of boolean types in Objective-C and its kin, truth is indeed stranger than fiction." --- diff --git a/2013-04-15-nssecurecoding.md b/2013-04-15-nssecurecoding.md index ffaa7f65..78412db0 100644 --- a/2013-04-15-nssecurecoding.md +++ b/2013-04-15-nssecurecoding.md @@ -1,10 +1,10 @@ --- layout: post title: NSSecureCoding - ref: "http://developer.apple.com/library/mac/#documentation/Foundation/Reference/NSSecureCoding_Protocol_Ref/content/NSSecureCoding.html" framework: Foundation rating: 6.0 +description: "A short post for this week: everything you need to know about NSSecureCoding." --- A short post for this week: everything you need to know about `NSSecureCoding`. diff --git a/2013-04-22-nshipster-quiz-1.md b/2013-04-22-nshipster-quiz-1.md index 5ba3dd06..141f78b6 100644 --- a/2013-04-22-nshipster-quiz-1.md +++ b/2013-04-22-nshipster-quiz-1.md @@ -1,7 +1,6 @@ --- layout: post title: "NSHipster Quiz #1" - ref: "http://www.uikonf.com/2013/03/25/nshipster-quiz-night.html" framework: Trivia rating: 10.0 diff --git a/2013-04-29-mklocalsearch.md b/2013-04-29-mklocalsearch.md index a87622aa..2977881d 100644 --- a/2013-04-29-mklocalsearch.md +++ b/2013-04-29-mklocalsearch.md @@ -1,11 +1,10 @@ --- layout: post title: MKLocalSearch - ref: "http://developer.apple.com/library/ios/#documentation/MapKit/Reference/MKLocalSearch/Reference/Reference.html" framework: MapKit rating: 7.1 -description: In all of the hubbub of torch burning and pitchfork raising, you may have completely missed a slew of additions to MapKit in iOS 6.1. +description: "In all of the hubbub of torch burning and pitchfork raising, you may have completely missed a slew of additions to MapKit in iOS 6.1." --- Look, we get it: people are upset about Apple Maps. diff --git a/2013-05-06-gpuimage.md b/2013-05-06-gpuimage.md index 8f08bdc1..b03cd212 100644 --- a/2013-05-06-gpuimage.md +++ b/2013-05-06-gpuimage.md @@ -1,7 +1,6 @@ --- layout: post title: GPUImage - ref: "https://github.com/BradLarson/GPUImage" framework: "Open Source" rating: 9.3 diff --git a/2013-05-13-nscoding.md b/2013-05-13-nscoding.md index 5a9e248e..fb29f764 100644 --- a/2013-05-13-nscoding.md +++ b/2013-05-13-nscoding.md @@ -4,6 +4,7 @@ title: NSCoding / NSKeyedArchiver ref: "https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Protocols/NSCoding_Protocol/Reference/Reference.html" framework: Foundation rating: 7.5 +description: "Among the most important architectural decisions made when building an app is how to persist data between launches. The question of how, exactly, to re-create the state of the app from the time it was last opened; of how to describe the object graph in such a way that it can be flawlessly reconstructed next time." --- Among the most important architectural decisions made when building an app is how to persist data between launches. The question of how, exactly, to re-create the state of the app from the time it was last opened; of how to describe the object graph in such a way that it can be flawlessly reconstructed next time. @@ -195,4 +196,4 @@ And even if most applications _would_ benefit from Core Data at some point, ther [1]: http://developer.apple.com/library/mac/#documentation/cocoa/Conceptual/CoreData/cdProgrammingGuide.html [2]: http://developer.apple.com/library/ios/#Documentation/Cocoa/Reference/Foundation/Classes/NSKeyedArchiver_Class/Reference/Reference.html -[3]: http://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSKeyedUnarchiver_Class/Reference/Reference.html \ No newline at end of file +[3]: http://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSKeyedUnarchiver_Class/Reference/Reference.html diff --git a/2013-05-27-unit-testing.md b/2013-05-27-unit-testing.md index 262ba932..98dd48c4 100644 --- a/2013-05-27-unit-testing.md +++ b/2013-05-27-unit-testing.md @@ -1,10 +1,10 @@ --- layout: post title: Unit Testing - ref: "https://developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/UnitTesting/00-About_Unit_Testing/about.html" framework: Testing rating: 8.9 +description: "Unit Testing is an emotional topic for developers. It inspires a sense of superiority to its most zealous adherents, and evokes a feeling of inadequacy to non-practitioners. Cargo Cults like TDD stake their reputation on unit testing to the point of co-opting and conflating utility with morality." --- Unit Testing is an emotional topic for developers. It inspires a sense of superiority to its most zealous adherents, and evokes a feeling of inadequacy to non-practitioners. [Cargo Cults like TDD](http://ntoll.org/article/tdd-cargo-cult) stake their reputation on unit testing to the point of co-opting and conflating utility with morality. diff --git a/2013-09-09-network-link-conditioner.md b/2013-09-09-network-link-conditioner.md index 7d3681e6..12ff4fee 100644 --- a/2013-09-09-network-link-conditioner.md +++ b/2013-09-09-network-link-conditioner.md @@ -19,7 +19,7 @@ This week on NSHipster, we'll be talking about the [Network Link Conditioner](ht ## Installation -Network Link Conditioner can be found in the "Hardware IO Tools for Xcode" package. This can be downloaded from the [Apple Developer Downloads](https://developer.apple.com/downloads/index.action?q=Network%20Link%20Conditioner) page. +Network Link Conditioner can be found in the "Hardware IO Tools for Xcode" package. This can be downloaded from the [Apple Developer Downloads](https://developer.apple.com/downloads/index.action?q=Network%20Link%20Conditioner) page. ![Download](http://nshipster.s3.amazonaws.com/network-link-conditioner-download.png) @@ -45,7 +45,7 @@ When enabled, the Network Link Conditioner can change the network environment of - Very Bad Network - 100% Loss -Each preset can set a limit for uplink or downlink [bandwidth](http://en.wikipedia.org/wiki/Bandwidth_%28computing%29), [latency](http%3A//en.wikipedia.org/wiki/Latency_%28engineering%29%23Communication_latency), and rate of [packet loss](http://en.wikipedia.org/wiki/Packet_loss) (when any value is set to 0, that value is unchanged from your computer's network environment). +Each preset can set a limit for uplink or downlink [bandwidth](http://en.wikipedia.org/wiki/Bandwidth_%28computing%29), [latency](http://en.wikipedia.org/wiki/Latency_%28engineering%29%23Communication_latency), and rate of [packet loss](http://en.wikipedia.org/wiki/Packet_loss) (when any value is set to 0, that value is unchanged from your computer's network environment). ![Preset](http://nshipster.s3.amazonaws.com/network-link-conditioner-preset.png) diff --git a/2013-09-16-afnetworking-2.md b/2013-09-16-afnetworking-2.md index a475fdb4..915987ec 100644 --- a/2013-09-16-afnetworking-2.md +++ b/2013-09-16-afnetworking-2.md @@ -1,7 +1,6 @@ --- layout: post title: AFNetworking 2.0 - ref: "https://github.com/AFNetworking/AFNetworking" framework: "Open Source" rating: 9.9 @@ -12,7 +11,7 @@ description: "AFNetworking is one of the most widely used open source projects f By all accounts, AFNetworking is about as mainstream as it gets. -_But have you heard about the sequel?_ +_But have you heard about the sequel?_ [AFNetworking 2.0](https://github.com/AFNetworking/AFNetworking/). This week on NSHipster: an exclusive look at the future of AFNetworking. @@ -63,11 +62,11 @@ With its second major release, AFNetworking aims to reconcile many of the quirks - `AFURLConnectionOperation` - A subclass of `NSOperation` that manages an `NSURLConnection` and implements its delegate methods. - `AFHTTPRequestOperation` - A subclass of `AFURLConnectionOperation` specifically for making HTTP requests, which creates a distinction between acceptable and unacceptable status codes and content types. The main difference in 2.0 is that _you'll actually use this class directly, rather than subclass it_, for reasons explained in the "Serialization" section. -- `AFHTTPRequestOperationManager` - A class that encapsulates the common patterns of communicating with a web service over HTTP, backed by `NSURLConnection` by way of `AFHTTPRequestOperation`. +- `AFHTTPRequestOperationManager` - A class that encapsulates the common patterns of communicating with a web service over HTTP, backed by `NSURLConnection` by way of `AFHTTPRequestOperation`. #### `NSURLSession` Components _(iOS 7)_ -- `AFURLSessionManager` - A class that creates and manages an `NSURLSession` object based on a specified `NSURLSessionConfiguration` object, as well as data, download, and upload tasks for that session, implementing the delegate methods for both the session and its associated tasks. Because of the odd gaps in `NSURLSession`'s API design, __any code working with `NSURLSession` would be improved by `AFURLSessionManager`__. +- `AFURLSessionManager` - A class that creates and manages an `NSURLSession` object based on a specified `NSURLSessionConfiguration` object, as well as data, download, and upload tasks for that session, implementing the delegate methods for both the session and its associated tasks. Because of the odd gaps in `NSURLSession`'s API design, __any code working with `NSURLSession` would be improved by `AFURLSessionManager`__. - `AFHTTPSessionManager` - A subclass of `AFURLSessionManager` that encapsulates the common patterns of communicating with an web service over HTTP, backed by `NSURLSession` by way of `AFURLSessionManager`. --- @@ -157,6 +156,6 @@ Oh yeah, one more thing... ## AFNetworking: the Definitive Guide -I'm thrilled to announce that AFNetworking is getting an official book! +I'm thrilled to announce that AFNetworking is getting an official book! **"AFNetworking: the Definitive Guide"** will be published by [O'Reilly](http://oreilly.com), hopefully within the next couple of months. You can [sign up here to be notified by email when its available](http://eepurl.com/Flnvn), or [follow @AFNetworking](https://twitter.com/AFNetworking). diff --git a/2013-09-30-xcode-key-bindings-and-gestures.md b/2013-09-30-xcode-key-bindings-and-gestures.md index bdda72c2..04cd4965 100644 --- a/2013-09-30-xcode-key-bindings-and-gestures.md +++ b/2013-09-30-xcode-key-bindings-and-gestures.md @@ -1,11 +1,9 @@ --- layout: post title: Xcode Key Bindings & Gestures - ref: "https://developer.apple.com/library/mac/documentation/IDEs/Conceptual/xcode_help-command_shortcuts/Introduction/Introduction.html" framework: Xcode rating: 8.0 -published: true description: "Xcode key bindings and gestures not only shave off seconds of precious work, but make you look more confident, competent, and cromulent in the process." --- @@ -13,7 +11,7 @@ The extent to which programming-as-craft is compared to manual disciplines like Here at NSHipster, the advice is simple and only slightly allegorical: "Xcode is your mustache, so keep it trimmed, waxed to a sharp point, and free of bugs." -Anyway, a few weeks ago, we looked at how [Xcode Snippets](http://nshipster.com/xcode-snippets/) can make you more productive by reducing the amount of boilerplate code you have to type out. This week, we're going to pick up on that thread and cover the essential key bindings and gestures. +Anyway, a few weeks ago, we looked at how [Xcode Snippets](http://nshipster.com/xcode-snippets/) can make you more productive by reducing the amount of boilerplate code you have to type out. This week, we're going to pick up on that thread and cover the essential key bindings and gestures. Xcode key bindings and gestures not only shave off seconds of precious work, but make you look more confident, competent, and cromulent in the process. Learn the following tricks of the trade and join the elite set of Xcode power users. diff --git a/2013-10-07-key-value-observing.md b/2013-10-07-key-value-observing.md index 80874535..fc0e6bb7 100644 --- a/2013-10-07-key-value-observing.md +++ b/2013-10-07-key-value-observing.md @@ -1,11 +1,9 @@ --- layout: post title: "Key-Value Observing" - ref: "https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/KeyValueObserving/KeyValueObserving.html" framework: Foundation rating: 5.4 -published: true description: "Ask anyone who's been around the NSBlock a few times: Key-Value Observing has the _worst_ API in all of Cocoa. It's awkward, verbose, and confusing. And worst of all, its terrible API belies one of the most compelling features of the framework." --- diff --git a/2013-10-21-launch-arguments-and-environment-variables.md b/2013-10-21-launch-arguments-and-environment-variables.md index 86652125..4437a645 100644 --- a/2013-10-21-launch-arguments-and-environment-variables.md +++ b/2013-10-21-launch-arguments-and-environment-variables.md @@ -1,11 +1,9 @@ --- layout: post title: "Launch Arguments &
Environment Variables" - ref: "https://developer.apple.com/library/ios/technotes/tn2239/_index.html" framework: Xcode rating: 7.1 -published: true description: "There are a number of options that can be passed into a target's scheme to enable useful debugging behavior, but like a fast food secret menu, they're obscure and widely unknown." --- diff --git a/2013-10-28-nshipster-quiz-4.md b/2013-10-28-nshipster-quiz-4.md index 220333aa..ef51f182 100644 --- a/2013-10-28-nshipster-quiz-4.md +++ b/2013-10-28-nshipster-quiz-4.md @@ -1,7 +1,6 @@ --- layout: post title: "NSHipster Quiz #4" - ref: "http://www.meetup.com/Appsterdam/events/143596702/" framework: Trivia rating: 10.0 @@ -10,7 +9,7 @@ description: "The fourth and final quiz of the year. Do you have what it takes t The fourth and final NSHipster pub quiz of the year was held in the beautiful city of Amsterdam on October 22nd, with help from the good folks at [Appsterdam](http://appsterdam.rs), [The Big Nerd Ranch](http://www.bignerdranch.com/), and [Heroku](http://www.heroku.com). -The competition was fierce, but ultimately the team of [Mike Lee](https://twitter.com/bmf), [Judy Chen](https://twitter.com/judykitteh), [Eloy Dúran](https://twitter.com/alloy), [Alexander Repty](https://twitter.com/arepty), [Maxie Ketschau-Repty](@Yumyoko), and [Sernin van de Krol](https://twitter.com/paneidos) were victorious. This was, by design, to be the highest-scoring of any pub quiz, with generous portions of extra points, and Team "[Graceful Hoppers](http://en.wikipedia.org/wiki/Grace_Hopper)" came through with an impressive 53 points (which, interestingly enough, only edged out the 2nd place team by ½ of a point). +The competition was fierce, but ultimately the team of [Mike Lee](https://twitter.com/bmf), [Judy Chen](https://twitter.com/judykitteh), [Eloy Dúran](https://twitter.com/alloy), [Alexander Repty](https://twitter.com/arepty), [Maxie Ketschau-Repty](https://twitter.com/Yumyoko), and [Sernin van de Krol](https://twitter.com/paneidos) were victorious. This was, by design, to be the highest-scoring of any pub quiz, with generous portions of extra points, and Team "[Graceful Hoppers](http://en.wikipedia.org/wiki/Grace_Hopper)" came through with an impressive 53 points (which, interestingly enough, only edged out the 2nd place team by ½ of a point). As always, you can play along at home or at work with your colleagues. Here are the rules: @@ -35,7 +34,7 @@ Current events, miscellaneous tidbits, and random trivia. Following a time-honor 6. Which website's failure has given cause for President Obama to do a post-mortem for the failed Rails app? 7. Doomed former smartphone juggernaut BlackBerry recently released an iOS app. What is it called? 8. Apple prompted some raised eyebrows with the final developer release of 
Mac OS X Mavericks. What was the controversy? -9. During development, the 
Gold iPhone 5s was jokingly named
after which American "celebrity"? +9. During development, the 
Gold iPhone 5s was jokingly named
after which American "celebrity"? 10. At an average per capita rate of 8.4kg per year, the Netherlands is the world's #5 consumer of what? Round 2: Foundation Potpourri @@ -43,7 +42,7 @@ Round 2: Foundation Potpourri With the fluff out of the way, it's now time to dive into some hardcore Cocoa fundamentals. How well do _you_ know the standard library? -1. `NSPredicate` objects can be decomposed into left and right hand side components of which class? +1. `NSPredicate` objects can be decomposed into left and right hand side components of which class? 2. Which of the following is _not_ something `NSDataDetector` can detect? Addresses, Phone Numbers, Product Listings, or Flight Information. 3. Which Foundation collection class allows values to be weakly referenced? 4. What method would you implement in an `NSFormatter` subclass in order to override what's displayed while editing? @@ -79,18 +78,18 @@ Round 4: NSAnagram And finally, an admittedly _sadistic_ round that combines wordplay with Cocoa arcana. Each question is an anagram, whose letters can be rearranged to form the name of a class or type in a well-known system framework (hint: Foundation, Core Foundation, UIKit, and AddressBook are represented here). Good luck! -1. Nose Call +1. Nose Call 2. Uncle Consort Inn -3. Oi! Inaccurate Wit Vividity -4. A Band's Cement Jog +3. Oi! Inaccurate Wit Vividity +4. A Band's Cement Jog 5. Tartan's Screech 6. Kebab's Sad Odor -7. Macs Fret +7. Macs Fret 8. Manservant of Rulers -9. Measurably Rant +9. Measurably Rant 10. Ill-Oiled Canonicalized Tuxedo -* * * +* * * # Answers diff --git a/2014-01-06-colophon.md b/2014-01-06-colophon.md index 69fd260f..40e45e72 100644 --- a/2014-01-06-colophon.md +++ b/2014-01-06-colophon.md @@ -2,7 +2,6 @@ layout: post title: "Colophon" category: "Colophon" -published: true framework: "" description: "As a way to kick off this new year, I thought it'd be fun to share some insights of just how NSHipster is made. This article covers both the website and the recently-released NSHipster book, so if you've wondered about the nitty gritty of digital or physical publishing, this article is for you." --- diff --git a/2014-01-20-extended-file-attributes.md b/2014-01-20-extended-file-attributes.md index 057dd7d0..d31c5d9e 100644 --- a/2014-01-20-extended-file-attributes.md +++ b/2014-01-20-extended-file-attributes.md @@ -1,10 +1,8 @@ --- layout: post title: "Extended File Attributes" - ref: "" framework: Objective-C -published: true description: "Amidst revelations of widespread spying by the NSA, the concept of metadata has taken an unexpected role in the national conversation about government surveillance. What is it? And how much does it reveal about us and our daily habits? These are questions that the American people are asking, and they deserve an answer." --- diff --git a/2014-02-03-mktileoverlay-mkmapsnapshotter-mkdirections.md b/2014-02-03-mktileoverlay-mkmapsnapshotter-mkdirections.md index 22f69e19..9783d3c3 100644 --- a/2014-02-03-mktileoverlay-mkmapsnapshotter-mkdirections.md +++ b/2014-02-03-mktileoverlay-mkmapsnapshotter-mkdirections.md @@ -4,7 +4,7 @@ title: "MKTileOverlay,
MKMapSnapshotter &
MKDirections" ref: "https://developer.apple.com/library/ios/documentation/MapKit/Reference/MapKit_Framework_Reference/_index.html#//apple_ref/doc/uid/TP40008210" framework: MapKit rating: 9.0 -description: Unless you work with MKMapView. on a regular basis, the last you may have heard about the current state of cartography on iOS may not have been under the cheeriest of circumstances. Therefore, it may come as a surprise maps on iOS have gotten quite a bit better in the intervening releases. Quite good, in fact. +description: "Unless you work with MKMapView. on a regular basis, the last you may have heard about the current state of cartography on iOS may not have been under the cheeriest of circumstances. Therefore, it may come as a surprise maps on iOS have gotten quite a bit better in the intervening releases. Quite good, in fact." --- Unless you work with `MKMapView` on a regular basis, the last you may have heard about the current state of cartography on iOS may not have been [under the cheeriest of circumstances](http://www.apple.com/letter-from-tim-cook-on-maps/). Even now, years after the ire of armchair usability experts has moved on to iOS 7's distinct "look and feel", the phrase "Apple Maps" still does not inspire confidence in the average developer.