Categories
Florida Tampa Bay

Functional Ybor meetup: Functional World Tour (May 31, 2016)

functional ybor

Ybor City is home not just to some great bars, clubs, and restaurants, but also a number of wild urban chickens and roosters. They’re much better than pigeons.

If you’re a programmer looking for something to do tonight in Tampa, I recommend checking out Functional Ybor, part of the Ybor Tech series of meetups run by Tony Winn. Ybor Tech is a gathering that happens twice a month in Tampa’s Ybor City neighborhood, once in a more formal, presentation-style setting, and once at New World Brewery over beer and pizza. Tonight’s gathering is the more formal, presentation-style one, but if the pattern holds true, we’re very likely to go somewhere in Ybor for beer afterwards.

Tony will be giving tonight’s presentation, titled Functional World Tour. He’ll give us an overview of the most interesting and popular functional languages in use today: Clojure, Scala, Haskell, Erlang, Elixir, Elm (that’s his jam), Scheme, OCaml, and JavaScript (“with some guide rails”). At the end of the talk, he’ll open things up for discussion so that the group can figure out which functional language we’d like to cover in depth over the next several meetings.

robert saunders sr public library

Tonight’s meetup will take place at the Robert Saunders Sr. Public Library, located at 1505 North Nebraska Avenue (just south of 7th Avenue) from 6:30 p.m. to 8:00 p.m.. It’ll take place in the big meeting room on the second floor. See you there!

Categories
Uncategorized

The inaugural ReactJS Tampa Bay meetup

reactjs tampa bay 1

Photo by Ryan Connolly. Click the photo to see the source.

The inaugural ReactJS Tampa Bay Meetup took place yesterday at 352 Inc to a pretty full and very enthusiastic room. Kudos to organizers/hosts Josh Burgess, Ryan Connolly, John Hampton, and Eric Nograles for putting it together! I’m looking forward to attending — and likely speaking at — future ReactJS Tampa Bay events.

ReactJS Tampa Bay Meetups are going to alternate between two kinds of gatherings:

  • Presentations, where the format will be one or more speakers giving presentations on all manner of topics involving React, both technical and non-technical (such as business cases, design issues, and so on), and
  • “ReHacked” labs, which will be hands-on workshops for people interested in learning how to develop applications with React.

Last night’s gathering was one of the presentation ones, and the topic was React: A Competitive Edge and a Business Decision. A major issue covered in the talk was why both decision makers and developers both should care about React.

For decision-makers, the reasons that React matters are:

  • React has been proven in production by industry giants (most importantly, Facebook, who built it for their own purposes)
  • Its design doesn’t lock you into it, and it’s easier to pivot from React to other technologies if necessary
  • It was designed with faster feature delivery in mind
  • Thanks to Facebook’s clout and widespread developer approval, it has considerable community momentum and support
  • As the current darling of the development set, authorizing its use means more excited and productive front-end teams

For developers, the reasons are:

  • The mental model you have to adopt is considerably simpler than most JavaScript frameworks, which are feeling increasingly like some labyrinthine, byzantine monstrosity — React is largely projecting data onto UI
  • It uses vanilla JavaScript instead of HTML-based templates (I think this is good, but I know some back-end devs who swear by templates)
  • It’s design to be “fast by default”
  • React’s architecture allows for easier future transitions to whatever comes next
  • Its reliance on world-class developer tools means a great developer experience
  • This is as close as we’ve gotten to being truly cross-platform: it’s “learn once, write anywhere”, which is more truthful and practical than the old promise of “write once, run anywhere”

Here’s the slide deck they showed (it might not render completely correctly at this size; you may want to check it out on a full screen):

The next ReactJS Tampa Bay gathering will take place on Wednesday, June 8th and will be a ReHacked lab covering the basics of ReactJS development called SPA Basics with React. John Hampton and Eric Nograles will be leading the session, which is described as follows:

Want to get started with writing React SPA apps but don’t know where to begin? This session will cover how to get up and going quickly with React. We will cover the basics of a build system using Webpack and Babel, React component basics, a quick tour of react-router, and how to communicate with a backend Web API.

I’m looking forward to it!

rehacked

Categories
Uncategorized

A whole lotta videos of Google I/O 2016 presentations

gogole io 2016

I’m working on upping my Android development game, and if you are too, you’ll probably want to check out this collection of high-quality videos from Google I/O 2016. There’s hours of viewing here…enjoy!

Google I/O 2016 keynote

What’s new in Android

What’s new in Android Studio 2.2

The experts’ guide to Android development tools

Android layouts: A new world

What the fragment?

RecyclerView ins and outs

Android themes and styles demystified

Discover the expanded Material Design motion guidelines

Streamlining developer experiences with the Google Maps APIs

Location and proximity superpowers (Eddystone + Google Beacon Platform)

Understand your place in this world (Google Place API)

Image compression for Android developers

Android high-performance audio

Best practices in media playback

Building for billions on Android

Android application architecture: Get ready for the next billion users!

Firebase overview

Zero to app: Develop with Firebase

Lean and fast: Putting your app on a diet

Android memory and battery optimizations

What’s new in the support library

What’s new in Google Play for developers

Introducing Google Developer Certification: Become an Associate Android Developer

Categories
Swift Kick

A better way to program iOS text fields that have maximum lengths and accept or reject specific characters

In my last article on iOS programming in Swift, I showed you how to add some code to your project that would allow you to add a “Max Length” property to all its text fields, which you could set in code, or better yet, in Xcode’s Interface Builder, as shown below:

max chars text field

For more details, you should take a look at that article, iOS programming trick: How to use Xcode to set a text field’s maximum length, Visual Studio-style.

A key part of what made it work was the @IBInspectable keyword. When applied to a property of an object that can be displayed in Interface Builder, it makes that property available to the Attributes Inspector, which in turn provides a user interface for viewing and changing that property.

That got me thinking: could I apply @IBInspectable to the text field tricks I covered in my April 2015 article, How to program an iOS text field that takes only numeric input or specific characters with a maximum length?

In that article, I covered how to program text fields that accepted only specified characters or accepted all characters except a specified set, and it required making the containing view controller adopt the UITextFieldDelegate protocol and use itself as its own delegate, and then implementing the textField(_:shouldChangeCharactersInRange:replacementString:) method.

Wouldn’t it be nice if it were simpler? Consider the illustration below of an “Allowed Chars Text Field”. It lets me specify the following in Interface Builder:

  1. That characters that are allowed to be entered into the text field, and
  2. The maximum number of characters that are allowed to be entered into the text field.

allowed chars text field

This works if the set of characters that I want to allow into the text field is small. How about the case where I want to do the opposite: prevent the user from entering a small set of specified characters? That would be a “Banned Chars Text Field”, and it would allow me to specify the following in Interface Builder:

  1. That characters that are not allowed to be entered into the text field, and
  2. The maximum number of characters that are allowed to be entered into the text field.

banned chars text field

Let’s make these happen!

Limiting the number of characters that can be put into a text field

In the article iOS programming trick: How to use Xcode to set a text field’s maximum length, Visual Studio-style, we put the following code into a file named TextFieldMaxLengths.swift:

import UIKit

// 1
private var maxLengths = [UITextField: Int]()

// 2
extension UITextField {
  
  // 3
  @IBInspectable var maxLength: Int {
    get {
      // 4
      guard let length = maxLengths[self] else {
        return Int.max
      }
      return length
    }
    set {
      maxLengths[self] = newValue
      // 5
      addTarget(
        self,
        action: #selector(limitLength),
        forControlEvents: UIControlEvents.EditingChanged
      )
    }
  }
  
  func limitLength(textField: UITextField) {
    // 6
    guard let prospectiveText = textField.text
      where prospectiveText.characters.count > maxLength else {
        return
    }
    
    let selection = selectedTextRange
    // 7
    text = prospectiveText.substringWithRange(
      Range<String.Index>(prospectiveText.startIndex ..< prospectiveText.startIndex.advancedBy(maxLength))
    )
    selectedTextRange = selection
  }
  
}

Once again, here are the annotations for the numbered comments in the code:

  1. There are two big things going on in this single line of code, which declares and initializes maxLengths, a dictionary that stores the maximum lengths of text fields:
    • First, there’s the private declaration. In many programming languages, private means “accessible only inside the class”, but in Swift, private means “accessible only inside the source file where they’re defined”. Any code inside TextFieldMaxLengths.swift has access to maxLengths, and any code outside TextFieldMaxLengths.swift does not. By putting maxLengths in the same file as our UITextField extension, we get a place where we can store the maximum lengths of text fields (remember: extensions can only add methods, not properties), and by making it private, we keep other code from messing with it.
    • Then there’s the matter of what to use as the key for the maxLengths dictionary. Swift lets you use anything that conforms to the Hashable protocol as a dictionary key, and UITextField does just that. It makes sense to use the text fields themselves as the keys to the values for their maximum lengths.
  2. Swift extensions let you add new functionality to existing classes, structs, enumerations, and protocols. We’re using an extension to UITextField to add two things:
    • maxLength, a property that lets the programmer set and get the maximum length of a text field, and
    • limitLength, a method called whenever the contents of a text field are changed, and limits the number of characters in that text field.
  3. By marking the maxLength property with @IBInspectable, we make it available to Interface Builder, which then provides an editor for its value in the Attributes Inspector.
  4. Get to know and love the guard statement and the “early return” style of programming; you’re going to see a lot of it in a lot of Swift coding. Here, we’re using guard to filter out cases where no maximum length has been defined for the text field, in which case, we simply return the theoretical maximum string size.
  5. We use addTarget in maxLength‘s setter to ensure that if a text field is assigned a maximum length, the limitLength method is called whenever the text field’s contents change.
  6. Another guard statement. Any case that gets past it is one where the text about to go into the text field is longer than the maximum length.
  7.  Cocoa sometimes likes to make things complicated. This line is the Cocoa way of saying “put the first maxLength characters of prospectiveText into text“. If you’re going to be playing with substrings, you need to get comfortable with Ranges and intervals.

max length text field

Any Xcode project containing the code in TextFieldMaxLengths.swift will have text fields featuring “maximum length” properties that can be set in either Interface Builder or in code.

text2 screenshot

If you’d like to see these “max length” text fields in action, download the Text2 project (the running app is pictured above) and try them out!

AllowedCharsTextField: A text field that allows only specific characters

Let’s build on our new, improved text fields by creating one that accepts only characters from a defined set. You might need a text field that accepts only digits, or punctuation, or the letters A, C, G, and T. We’ll make setting up such a text field easy by creating a subclass of UITextField, which we’ll call AllowedCharsTextField. Since it’s a subclass of UITextField, it inherits all its capabilities, which includes any extensions, including the “max length” one we created.

Use File → New → File… to create a new Swift File. Give it the name AllowedCharsTextField.swift, and once you’ve created it, enter the following code into it:

import UIKit


// 1
class AllowedCharsTextField: UITextField, UITextFieldDelegate {
  
  // 2
  @IBInspectable var allowedChars: String = ""
  
  required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    // 3
    delegate = self
    // 4
    autocorrectionType = .No
  }

  // 5  
  func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {  
    // 6
    guard string.characters.count > 0 else {
      return true
    }
    
    // 7
    let currentText = textField.text ?? ""
    let prospectiveText = (currentText as NSString).stringByReplacingCharactersInRange(range, withString: string)
    return prospectiveText.containsOnlyCharactersIn(allowedChars)
  }
  
}


// 8
extension String {

  // Returns true if the string contains only characters found in matchCharacters.
  func containsOnlyCharactersIn(matchCharacters: String) -> Bool {
    let disallowedCharacterSet = NSCharacterSet(charactersInString: matchCharacters).invertedSet
    return self.rangeOfCharacterFromSet(disallowedCharacterSet) == nil
  }

}

Here’s what’s happening just after the numbered comments in the code:

  1. Our class inherits from UITextField to get the capabilities of a text field, and it adopts the UITextFieldDelegate protocol to be able to respond to the textField(_:shouldChangeCharactersInRange:replacementString:) method in order to intercept changes to the text field just after they’ve been input by the user, but before they’re committed to the text field.
  2. allowedChars stores the characters that we’ll allow in the text field, and @IBInspectable makes its value editable in Interface Builder. Interface Builder takes the code-cased allowedChars property name and displays it as Allowed Chars in the Attributes Inspector.
  3. This indicates that this class is the UITextFieldDelegate and will implement at least one UITextFieldDelegate method — in this case, textField(_:shouldChangeCharactersInRange:replacementString:).
  4. We disable autocorrection because it has a tendency to bypass the the textField(_:shouldChangeCharactersInRange:replacementString:) method that we use to detect allowed characters. I’ll admit it; this is a quick a dirty fix. That being said, you probably don’t want “autocucumber” in a text field like this anyway. I’m looking into ways to allow autocorrection and still have this text field work as designed.
  5. This method gets called after the user has made changes to the text field, but before they’re committed. It gives us a chance to cancel those changes. The method should return true if we want to accept the changes, and false otherwise.
  6. We’re only concerned about cases where characters are added, so if this string has a length of 0, exit early.
  7. Here’s where the real work is done:
    • ?? is Swift’s nil coalescing operator. It returns the left operand if it’s not nil, otherwise it returns the right operation (e.g.: x ?? y returns x if it isn’t nil, otherwise it returns y).
    • We create prospectiveText, which is the text that would result if we accept the user’s changes.
    • If prospectiveText contains only the allowed characters, we return true; otherwise, we return false.
  8. We’re using an extension of String to give it a containsOnlyCharactersIn function, which returns true if the string contains only the characters in the given string, false otherwise.

That’s all the code we need to create AllowedCharsTextField. To use it, drag a plain ol’ text field onto a view in the storyboard and do the following:

allowed chars 1

1. Select the Identity Inspector.
2. Select the text field.
3. Change its class to AllowedCharsTextField.

By default, the underlying class for a text field in the Storyboard is UITextField. However, the Identity Inspector lets you change the classes of things on the storyboard to other classes related by inheritance. If you got to the Custom Class  menu in the Identity Inspector and expand the Class drop-down menu, you’ll see that you now have two choices: AllowedCharsTextField and UITextField. Changing this value to AllowedCharsTextField marks the text field as an instance of our new AllowedCharsTextField instance instead of a regular UITextField.

You’ll know it’s working in the next couple of steps:

allowed chars 2

4. Select the Attributes Inspector.
5. You can now define allowed characters and maximum length in Interface Builder.

You can also define allowed characters and maximum length in code:

// myTextField is an instance of AllowedCharsTextField.
// It should accept up to 7 characters,
// and they MUST be vowels.
myTextField.allowedChars = "aeiou"
myTextField.maxLength = 7

BannedCharsTextField: A text field that bans only specific characters

AllowedCharsTextField works well for text fields where the set of characters that we want to allow into it is relatively small. There may be times when you want the opposite: a text field that accepts all characters, except for a certain few specific ones. Let’s build one in the same way we built AllowedCharsTextField and call it BannedCharsTextField.

Use File → New → File… to create a new Swift File. Give it the name BannedCharsTextField.swift, and once you’ve created it, enter the following code into it:

import UIKit


// 1
class BannedCharsTextField: UITextField, UITextFieldDelegate {
  

  // 2
  @IBInspectable var bannedChars: String = ""
  
  required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    // 3
    delegate = self
    // 4
    autocorrectionType = .No
  }
  
  // 5
  func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    // 6
    guard string.characters.count > 0 else {
      return true
    }
    
    // 7
    let currentText = textField.text ?? ""
    let prospectiveText = (currentText as NSString).stringByReplacingCharactersInRange(range, withString: string)
    return prospectiveText.doesNotContainCharactersIn(bannedChars)
  }
  
}


// 8
extension String {
  
  // Returns true if the string has no characters in common with matchCharacters.
  func doesNotContainCharactersIn(matchCharacters: String) -> Bool {
    let characterSet = NSCharacterSet(charactersInString: matchCharacters)
    return self.rangeOfCharacterFromSet(characterSet) == nil
  }
  
}

Here’s what’s happening just after the numbered comments in the code:

  1. Our class inherits from UITextField to get the capabilities of a text field, and it adopts the UITextFieldDelegate protocol to be able to respond to the textField(_:shouldChangeCharactersInRange:replacementString:) method in order to intercept changes to the text field just after they’ve been input by the user, but before they’re committed to the text field.
  2. bannedChars stores the characters that we’ll allow in the text field, and @IBInspectable makes its value editable in Interface Builder. Interface Builder takes the code-cased bannedChars property name and displays it as Banned Chars in the Attributes Inspector.
  3. This indicates that this class is the UITextFieldDelegate and will implement at least one UITextFieldDelegate method — in this case, textField(_:shouldChangeCharactersInRange:replacementString:).
  4. We disable autocorrection because it has a tendency to bypass the the textField(_:shouldChangeCharactersInRange:replacementString:) method that we use to detect banned characters. I’ll admit it; this is a quick a dirty fix. That being said, you probably don’t want “autocucumber” in a text field like this anyway. I’m looking into ways to allow autocorrection and still have this text field work as designed.
  5. This method gets called after the user has made changes to the text field, but before they’re committed. It gives us a chance to cancel those changes. The method should return true if we want to accept the changes, and false otherwise.
  6. We’re only concerned about cases where characters are added, so if this string has a length of 0, exit early.
  7. Here’s where the real work is done:
    • ?? is Swift’s nil coalescing operator. It returns the left operand if it’s not nil, otherwise it returns the right operation (e.g.: x ?? y returns x if it isn’t nil, otherwise it returns y).
    • We create prospectiveText, which is the text that would result if we accept the user’s changes.
    • If prospectiveText contains only the allowed characters, we return true; otherwise, we return false.
  8. We’re using an extension of String to give it a doesNotContainCharactersIn function, which returns true if the string doesn’t contain any of the characters in the given string, false otherwise.

That’s all the code we need to create BannedCharsTextField. To use it, drag a plain ol’ text field onto a view in the storyboard and do the following:

banned chars 1

1. Select the Identity Inspector.
2. Select the text field.
3. Change its class to BannedCharsTextField.

By default, the underlying class for a text field in the Storyboard is UITextField. However, the Identity Inspector lets you change the classes of things on the storyboard to other classes related by inheritance. If you got to the Custom Class  menu in the Identity Inspector and expand the Class drop-down menu, you’ll see that you now have three choices: AllowedCharsTextFieldBannedCharsTextField, and UITextField. Changing this value to BannedCharsTextField marks the text field as an instance of our new BannedCharsTextField instance instead of a regular UITextField.

You’ll know it’s working in the next couple of steps:

banned chars 2

4. Select the Attributes Inspector.
5. You can now define allowed characters and maximum length in Interface Builder.

You can also define allowed characters and maximum length in code:

// myTextField is an instance of BannedCharsTextField.
// It should accept up to 7 characters,
// and they CANNOT be vowels.
myTextField.bannedChars = "aeiou"
myTextField.maxLength = 7

“Allowed + Banned Chars Text Fields”: A sample project showing text fields with maximum lengths, AllowedCharsTextField, and BannedCharsTextField in action

allowed - banned chars app screenshot

You’re probably raring to try out the code from this article. Here’s a project you can play with that presents a quick-and-dirty single view app with 4 text fields:

  1. A text field a maximum length of 6 characters.
  2. A vowels-only text field with a 5-character maximum length, with the Max Length and Allowed Chars properties set in Interface Builder.
  3. A no-vowels-allowed text field with a 7-character maximum length, with the Max Length and Banned Chars properties set in Interface Builder.
  4. A text field with a 10-character maximum length that accepts only the characters from the word freaky. Its maxLength and allowedChars properties were set in code in the view controller’s viewDidLoad method.

Give it a try, learn what makes it tick, and use it as a jumping-off point for your own projects!

xcode download

You can download the project files for this article (37KB zipped) here.

Categories
Uncategorized

“Why can’t girls code?” hilariously sends up the sexist excuses for shooing girls and women away from tech

If you watch only one video today, make it Why Can’t Girls Code?, which provides all sorts of crazy reasons why girls (and eventually, woman) shouldn’t take up programming or anything tech-related, from this one…

boobs

…to this one…

auburn strands of mink

…to this one:

mood swings

As Margot Richaud, an alumna of Girls Who Code (the people behind the video) puts it:

“These videos may seem absurd, but sadly they’re not so off the mark. As a high school senior, I’ve had classmates and teachers tell me that coding is not for me, or that I’d be better off focusing on design and making something look ‘pretty’. These comments, plus the stereotypes that we see everyday of a coder as a nerdy guy in a hoodie, keep a lot of my friends from considering computer science as a career path. We need to change that and stop telling girls that coding is not for us. There is never be an excuse for a girl to not code.”

For more, visit GirlsWhoCode.com.

Categories
Uncategorized

iOS programming trick: How to use Xcode to set a text field’s maximum length, Visual Studio-style [Updated for Swift 3]

Setting a text box’s maximum length, the Visual Studio way

easy in visual studio

Here’s how you set the maximum number of characters than can be entered into a text box when developing C# and VB applications in Microsoft Visual Studio:

There’s the GUI builder way…

  1. Select the text box.
  2. Set its MaxLength property in the Properties pane.

…and there’s the code way:

myTextBox.maxLength = 3 // or whatever length you like

Setting a text field’s maximum length, the out-of-the-box Xcode way

guy yelling at computer

Here’s how you set the maximum number of characters than can be entered into a text field when developing Objective-C and Swift applications in Xcode:

There isn’t a GUI builder way — just a code way, and it’s a little more work than it needs to be. The typical steps are:

  1. Make the containing view controller a text field delegate (i.e. make it adopt the UITextFieldDelegate protocol) so that it receives messages from all the text fields it contains.
  2. Implement the textfield(_:shouldChangeCharactersInRange:replacementString) method in order to intercept changes to any of the view’s text fields before they’re finalized. This involves:
    • Identifying the text field whose contents were changed, usually with an if or switch statement. If the text field is one whose text we want to limit to a certain length, then:
      • If the change in contents will result in the text not exceeding that length, simply return true.
      • If the change in contents will result in the text exceeding that length,  return false. You may want to take some additional action: for example, if the user tries to paste in more text you want to allow in the text field, you may want to allow a “partial paste” — pasting in the first n characters that will fit in the remaining space — and not reject the pasted text outright.

If you’re curious, I covered this in an earlier article, How to program an iOS text field that takes only numeric input or specific characters with a maximum length.

That’s a lot of work. Isn’t there a way we can get a “max length” property for text fields, like the .NET people?

wouldnt it be nice in xcode

The screen shot above (if you ignore my text annotations) isn’t Photoshoppery on my part. That’s a screen shot of my Xcode showing a selected text field and a corresponding Max Length property editor in the Attributes panel. With just a little coding in a single file, you too can your iOS text fields these goodies that .NET developers have had for ages and set the maximum length of text in a text field in both these ways:

  1. The GUI builder way, and
  2. With a single line of code.

Setting a text field’s maximum length, the improved Xcode way

Start a new project by doing the standard File → New → Project… dance to create a new Single View Application. Open Main.storyboard and place a single text field on the view:

plain text field and attributes inspector

Select the text field and switch to the Attributes Inspector (the inspector panel with the attributes inspector icon icon). The Attributes Inspector lets you edit all sorts of text field properties, but not the maximum length…yet.

new swift file

Use File → New → File… to create a new Swift File. Give it the name TextFieldMaxLengths.swift, and once you’ve created it, enter the following code into it:

import UIKit

extension UITextField {
  
  @IBInspectable var maxLength: Int {
    get {
      return 5
    }
    set {
      
    }
  }

}

Switch back to Main.storyboard, select the text field and look at the Attributes Inspector. You may notice that something’s changed:

enhanced text field and attributes inspector

All we did was create an extension for the UITextField class to give it an extra Int property named maxLength. Marking this property with the @IBInspectable keyword makes the property available to the Attributes Inspector (hence the name — the property can be inspected in Interface Builder).

Now that we’ve added a property to UITextField and made it inspectable within Interface Builder, it’s time to make the property do something.

If you’re using Swift 2.x, update the code in TextFieldMaxLengths.swift to the code below (keep scrolling if you’re using Swift 3):

// Swift 2.x version
// This will NOT work with Swift 3!
// ================================

import UIKit

// 1
private var maxLengths = [UITextField: Int]()

// 2
extension UITextField {
  
  // 3
  @IBInspectable var maxLength: Int {
    get {
      // 4
      guard let length = maxLengths[self] else {
        return Int.max
      }
      return length
    }
    set {
      maxLengths[self] = newValue
      // 5
      addTarget(
        self,
        action: #selector(limitLength),
        forControlEvents: UIControlEvents.EditingChanged
      )
    }
  }
  
  func limitLength(textField: UITextField) {
    // 6
    guard let prospectiveText = textField.text
      where prospectiveText.characters.count > maxLength else {
        return
    }
    
    let selection = selectedTextRange
    // 7
    text = prospectiveText.substringWithRange(
      Range<String.Index>(prospectiveText.startIndex ..< prospectiveText.startIndex.advancedBy(maxLength))
    )
    selectedTextRange = selection
  }
  
}

If you’re using Swift 3, update the code in TextFieldMaxLengths.swift to the code below:

// Swift 3 version
// This will NOT work with Swift 2.x!
// ==================================

import UIKit

// 1
private var maxLengths = [UITextField: Int]()

// 2
extension UITextField {
  
  // 3
  @IBInspectable var maxLength: Int {
    get {
      // 4
      guard let length = maxLengths[self] else {
        return Int.max
      }
      return length
    }
    set {
      maxLengths[self] = newValue
      // 5
      addTarget(
        self,
        action: #selector(limitLength),
        for: UIControlEvents.editingChanged
      )
    }
  }
  
  func limitLength(textField: UITextField) {
    // 6
    guard let prospectiveText = textField.text,
              prospectiveText.characters.count > maxLength
    else {
      return
    }
    
    let selection = selectedTextRange
    // 7
    let maxCharIndex = prospectiveText.index(prospectiveText.startIndex, offsetBy: maxLength)
    text = prospectiveText.substring(to: maxCharIndex)
    selectedTextRange = selection
  }
  
}

Here are my annotations that match the numbered comments in the code:

  1. There are two big things going on in this single line of code, which declares and initializes maxLengths, a dictionary that stores the maximum lengths of text fields:
    • First, there’s the private declaration. In many programming languages, private means “accessible only inside the class”, but in Swift, private means “accessible only inside the source file where they’re defined”. Any code inside TextFieldMaxLengths.swift has access to maxLengths, and any code outside TextFieldMaxLengths.swift does not. By putting maxLengths in the same file as our UITextField extension, we get a place where we can store the maximum lengths of text fields (remember: extensions can only add methods, not properties), and by making it private, we keep other code from messing with it.
    • Then there’s the matter of what to use as the key for the maxLengths dictionary. Swift lets you use anything that conforms to the Hashable protocol as a dictionary key, and UITextField does just that. It makes sense to use the text fields themselves as the keys to the values for their maximum lengths.
  2. Swift extensions let you add new functionality to existing classes, structs, enumerations, and protocols. We’re using an extension to UITextField to add two things:
    • maxLength, a property that lets the programmer set and get the maximum length of a text field, and
    • limitLength, a method called whenever the contents of a text field are changed, and limits the number of characters in that text field.
  3. By marking the maxLength property with @IBInspectable, we make it available to Interface Builder, which then provides an editor for its value in the Attributes Inspector.
  4. Get to know and love the guard statement and the “early return” style of programming; you’re going to see a lot of it in a lot of Swift coding. Here, we’re using guard to filter out cases where no maximum length has been defined for the text field, in which case, we simply return the theoretical maximum string size.
  5. We use addTarget in maxLength‘s setter to ensure that if a text field is assigned a maximum length, the limitLength method is called whenever the text field’s contents change.
  6. Another guard statement. Any case that gets past it is one where the text about to go into the text field is longer than the maximum length.
  7.  Cocoa sometimes likes to make things complicated. This line is the Cocoa way of saying “put the first maxLength characters of prospectiveText into text“. If you’re going to be playing with substrings, you need to get comfortable with Ranges and intervals.

If you include TextFieldMaxLengths.swift in any of your iOS projects, all text fields will have a maxLength property that you can set either GUI builder style in Interface Builder or in code, using myTextField.maxLength = n syntax, just like the .NET people do.

Happy text field coding!

“Text2”: A sample project showing Visual Studio-style text field maximum lengths in action

text2 screenshot

If you’d like to try out the code from this article, I’ve create a project — unimaginatively named Text2 and pictured above— that shows our UITextField extension in action. It’s a quick-and-dirty single view app that presents 4 text fields:

  1. A text field without a set maximum length.
  2. A text field with a 1-character maximum length, with the Max Length property set in Interface Builder.
  3. A text field with a 5-character maximum length, with the maxLength property set in code (in the view controller’s viewDidLoad method).
  4. A text field with a 10-character maximum length, with the Max Length property set in Interface Builder.

Give it a try, learn what makes it tick, and use it as a jumping-off point for your own projects!

xcode download

You can download the project files for this article (27KB zipped) here.

This code was derived from a Swift 1.2 solution posted by Frouo in Stack Overflow. I annotated it, and updated it so that it would be compatible with both Swift 2 and 3.

Categories
Uncategorized

This quick hack lets you use a standard pop filter with a Blue Yeti microphone

pop filter - blue yeti - hex dumbbell - 1

If you do podcasting or any kind of narrative recording with your computer at your desk, I can’t recommend the Blue Yeti microphone highly enough. Its shape and design ensure that it fits on even the most crowded of desktops, but many pop filters weren’t designed to clip onto it.

Here’s a quick and clever fix, and you may already have all the necessary parts sitting about your house.

pop filter - blue yeti - hex dumbbell - 2

Most pop filters were designed to attach to microphone stands. Their C-clamps were designed to wrap around something thin and cylindrical, a shape that doesn’t appear anywhere on the Blue Yeti. However, if you’ve got a small dumbbell lying around home — especially a hex-style dumbbell that won’t roll around — you’ve got the makings of a pop filter stand.

(If you don’t have a dumbbell like this handy, you should be able to find one at a garage sale or a used sporting goods store. You shouldn’t have to pay more than $5 for one.)

pop filter - dumbbell 1

Simply attach the pop filter to the dumbbell by clamping it onto one of the ends of its handle, as pictured above…

pop filter - dumbbell 2

…and then position your new pop filter/dumbbell combo in front of your mic!

felt pads

I’ve got a desk made of pine, which is pretty soft wood, so I attached a couple of felt pads to my dumbbell to prevent scratching.

And there you have it: a quick, easy, and even portable (I’ve flown with this setup) fix that lets you use a standard pop filter with a Blue Yeti mic!