Looking for some programming puzzles to test your skill? Try return true to win, a site that challenges you to complete the JavaScript functions it gives you to return the value true
. It will also remind you how full of “wat” JavaScript is.
In the previous article in this series, we added a long-missing feature to iOS text fields: the ability to limit them to a maximum number of characters, specifying this limit using either Interface Builder or in code. In this article, we’ll add an additional capability to our improved text field: the ability to allow only specified characters to be entered into them.
MaxLengthTextField
: A quick review
A screen shot of the example app demonstrating our improved text field class, MaxLengthTextField
, in action. Download the project files for the app.
In the previous article, we subclassed the standard iOS text field, UITextField
, to create a new class called MaxLengthTextField
. MaxLengthTextField
uses the following to give it the ability to limit itself to a set maximum number of characters:
- It adopts the
UITextFieldDelegate
protocol, giving it access to itstextField(_:shouldChangeCharactersIn:replacementString:)
method, which is called whenever is called whenever user actions change the text field’s content. This method lets us intercept this event, and determine whether or not the changes should be allowed. If the method returnstrue
, the changes are allowed; otherwise, it forbids the change, and the text field acts as if the user didn’t do any editing. - It adds a private variable,
characterLimit
, which stores that maximum number of characters allowed into the text field. - It adds a property,
maxLength
, which is used to get and set the value stored incharacterLimit
.maxLength
is marked with the@IBInspectable
attribute, which allows its value to be read and set from within Interface Builder. - The code within
textField(_:shouldChangeCharactersIn:replacementString:)
determines the length of the string that would result if the user’s edits to the text field were to be made. If the resulting number of characters is less than or equal to the set maximum, the method returnstrue
and the changes are allowed. If the resulting number of character is greater than the set maximum, the method returnsfalse
, and the changes do not take place.
We’ll build our new text field class, which we’ll call AllowedCharsTextField
, as a subclass of MaxLengthTextField
. Before we do that, we need to tweak the MaxLengthTextField
class so that it’s easier to subclass.
Let’s refactor MaxLengthTextField
, just a little
If you didn’t work with any of the code from the previous article, don’t worry — this article will provide you with the code for MaxLengthTextField
. In fact, it’ll provide you with a slightly tweaked version, shown below.
Create a new project, and within that project, create a Swift file named MaxLengthTextField.swift, which you should then fill with the following code:
import UIKit class MaxLengthTextField: UITextField, UITextFieldDelegate { private var characterLimit: Int? required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) delegate = self } @IBInspectable var maxLength: Int { get { guard let length = characterLimit else { return Int.max } return length } set { characterLimit = newValue } } func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { guard string.characters.count > 0 else { return true } let currentText = textField.text ?? "" let prospectiveText = (currentText as NSString).replacingCharacters(in: range, with: string) // 1. Here's the first change... return allowedIntoTextField(text: prospectiveText) } // 2. ...and here's the second! func allowedIntoTextField(text: String) -> Bool { return text.characters.count <= maxLength } }
This version of MaxLengthTextField
differs from the version in the previous article in two ways, each one marked with a numbered comment.
The original version of the textField(_:shouldChangeCharactersIn:replacementString:)
method contained all the logic of determining whether or not the text field should accept the changes made by the user:
- First, we filter out cases where the changes do not add any characters to the text field. In such a case, we know that the changes will not cause the text field to exceed the set maximum number of characters, so we accept the changes by returning
true
. - Then, we determine what the prospective text — the text that would result if the changes to the text field were accepted — would be.
- Finally, use the length of the prospective text to decide whether or not to accept the changes.
Steps 1 and 2 are applicable to any text field where we want to limit input to some criteria. Step 3 is specific to a text field where we want to limit input to a set maximum number of characters. We’ve factored step 3 into its own method, which returns true if the prospective text meets some criteria. There’s a method to this madness, and it’ll become clear once we build the AllowedCharsTextField
class.
Now let’s subclass MaxLengthTextField
to make AllowedCharsTextField
Add a new a Swift file to the project and name it AllowedCharsTextField.swift. Enter the following code into it:
import UIKit import Foundation class AllowedCharsTextField: MaxLengthTextField { // 1 @IBInspectable var allowedChars: String = "" required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) delegate = self // 2 autocorrectionType = .no } // 3 override func allowedIntoTextField(text: String) -> Bool { return super.allowedIntoTextField(text: text) && text.containsOnlyCharactersIn(matchCharacters: allowedChars) } } // 4 private extension String { // Returns true if the string contains only characters found in matchCharacters. func containsOnlyCharactersIn(matchCharacters: String) -> Bool { let disallowedCharacterSet = CharacterSet(charactersIn: matchCharacters).inverted return self.rangeOfCharacter(from: disallowedCharacterSet) == nil } }
Here’s what’s happening in the code above — these notes go with the numbered comments:
- The instance variable
allowedChars
contains a string specifying the characters that will be allowed into the text field. If a character does not appear within this string, the user will not be able to enter it into the text field. This instance variable is marked with the@IBInspectable
attribute, which means that its value can be read and set from within Interface Builder. - We disable autocorrect for the text field, because it may try to suggest words that contain characters that we won’t allow into it.
- Overriding
MaxLengthTextField
‘sallowedIntoTextField
method lets us add additional criteria to our new text field type. This method limits the text field to a set maximum number of characters and to characters specified inallowedChars
. - We extend the
String
class to include a new method,containsOnlyCharactersIn(_:)
, which returnstrue
if the string contains only characters within the given reference string. We use theprivate
keyword to limit this access to this newString
method to this file for the time being.
Using AllowedCharsTextField
Using AllowedCharsTextField
within storyboards is pretty simple. First, use a standard text field and place it on the view. Once you’ve done that, you can change it into an AllowedCharsTextField
by changing its class in the Identity Inspector (the inspector with the icon):
If you switch to the Attributes Inspector (the inspector with the icon), you’ll be able to edit the text field’s Allowed Chars and Max Length properties:
If you prefer, you can also set AllowedCharsTextField
‘s properties in code:
// myNextTextField is an instance of AllowedCharsTextField myNewTextField.allowedChars = "AEIOUaeiou" // Vowels only! myNewTextField.maxLength = 5
A sample project showing MaxLengthTextField
and AllowedCharsTextField
in action
If you’d like to try out the code from this article, I’ve created a project named Swift 3 Text Field Magic 2 (pictured above), which shows both MaxLengthTextField
and AllowedCharsTextField
in action. It’s a simple app that presents 3 text fields:
- A
MaxLengthTextField
with a 6-character limit. - An
AllowedCharsTextField
text field with a 5-character maximum length that accepts only upper- and lower-case vowels. Its Max Length and Allowed Chars properties were set in Interface Builder. - An
AllowedCharsTextField
text field with a 10-character maximum length that accepts only the characters from “freaky”. ItsmaxLength
andallowedChars
properties were set in code.
Try it out, see how it works, and use the code in your own projects!
You can download the project files for this article (68KB zipped) here.
Coming up next in this series…
In the next installment in this series, we’ll build a slightly different text field: one that allows all characters except for some specified banned ones.
Join us on Tuesday, September 27th for Tampa iOS Meetup, where we’ll cover making sticker packs and apps for iOS 10’s overhauled iMessage app!
With the newly-released iOS 10, the iMessage app will introduce a boatload of new features, including the ability for users to really customize their messages with:
- Stickers: static and animated pictures that you can include in messages, and
- Apps: extensions to iMessage that let you use it to customize messages, send payments, play games and more!
One really interesting thing about iMessage sticker packs is that you don’t do any coding to create them! If you’ve got art skills but no coding skills, stickers are your chance to put something in the App Store.
For those of you with coding skills, you’ll find iMessage apps interesting — they’re apps that live within iMessage and extend its capabilities! You can build apps that use iMessage as a platform so that friends can play games, send customized messages, make payments, and more! We’ll show you how to get started writing iMessage apps.
When and where
Come join us at the Tampa iOS Meetup on Tuesday, September 27th at 6:30 p.m. and learn about making stickers and apps for iMessage, which promises to be a great new way to break into the iOS market.
You don’t even need coding skills to get something from this meetup. To make sticker packs, all you need is a Mac, Apple’s free Xcode software and a developer account (we’ll show you how to get these), and a little creativity. If you’re new to Swift but have some programming experience in just about any language, whether it’s Java, JavaScript, C#, Python, Ruby, or any other object-oriented programming language, you shouldn’t have any trouble following the iMessage apps presentation. We’ll make all of our presentation materials, and project files available at the end of the meetup so you won’t leave empty-handed!
Please note that this session of the Tampa iOS Meetup will take place at a new location: the Wolters Kluwer offices at 1410 North Westshore Boulevard (Tampa).
We’d like to thank Jamie Johnson for letting us use his office, Energy Sense Finance for the past year. We couldn’t have done it without you!
What you’ll need
You don’t actually need to bring anything to the meetup, but you can get even more out of it if you bring a Mac with Xcode installed (you can download it for free from Apple).
If you have any questions, please feel free to contact me at joey@joeydevilla.com.
That was quick: A mere day after the iPhone 7 announcement in which the much-rumored removal of the 1/8″ analog headphone jack turned out to be true, the wags at College Humor produced a pitch-perfect iPhone parody ad featuring a pretty good impression of a Jony Ive voice-over:
I laughed out loud at the part where they showed Jony Ive’s iCalendar, which has a couple of amusing scheduled items:
Click to see at full “al-yoo-minny-yum” size.
Hey, I still love my iPhone (and don’t forget, I run an iOS developer meetup), but if you must vent at me for blaspheming by posting this article, there is a comments selection below…
Solid advice from Julia Evans’ Twitter feed. Click to see the source.
If you’re a programmer (or hope to be one) and you’re not following Julia Evans (@b0rk) on Twitter, go and fix that mistake right now.
Her Twitter feed has the vibe of a zine — pronounced zeen — which is short for fanzine, which in turn is short for fan magazine. Before the web, fans of certain things — alt-rock or punk bands, cyberpunk, various cultural movements or social causes, jokes, whatever — would publish stapled-together photocopied publications as little do-it-yourself magazines:
Zines. Click on the photo to see the source.
Here’s a definition of zine in zine format:
Click the photo to see the source.
Zines came about when it was easier to get your hands on a photocopier and Letraset than a computer and printer that could print more than just text. By necessity, they featured a lot of hand-drawn, hand-lettered art and comics…
…and because they’re labors of love, they often feature material that you wouldn’t find in larger, more mainstream publications. Zines cover all sorts of topics, from underground culture and music to science and social responsibility…
Click to see at full size.
…and there’s at least one heavily-trafficked site that started off as a zine:
Julia’s actually up and made zines about programming, what with her zine on debugging your programs using strace and her upcoming one, Linux debugging tools you’ll ❤️ (pictured below):
Here’s another gem from her Twitter feed:
Click to see the source.
I think she’s bringing back something that we lost when why the lucky stiff decided to pull a J.D. Salinger and disappear from the web:
But hey, this post is about Julia, so let’s end it with one more goodie from her Twitter feed!
Click to see the source.
Once again, if you haven’t added @b0rk to your Twitter feed, you’re missing out on some great stuff!
Update, September 8, 2016: My original implementation of this solution had a memory leak problem. This new implementation doesn’t!
In this series of articles, we’ll look at making iOS text fields even better using Swift 3. We’ll start by adding an important capability that iOS text fields have been missing for far too long: the ability to limit themselves to a maximum number of characters.
.NET has a maxLength property for text fields; why can’t Cocoa?
In Microsoft’s .NET framework, TextBox
es — the .NET equivalent of Cocoa’sUITextFields
— have a MaxLength
property that you can set, either visually or in code, that specifies the maximum number of characters that can be entered into them:
In the setup shown above, the TextBox
‘s MaxLength
property is set to 3, which ensures that the maximum number of characters that can be entered into it is 3, whether the characters are inserted by the user typing or pasting them in, or by code.
Cocoa’s UIKit doesn’t provide an analog to MaxLength
for its UITextFields
, but there’s no reason we can’t create it ourselves. By the end of this article, we’ll haveUITextFields
that feature a maxLength
property that can be set either in code or Interface Builder, as shown below:
Creating a new class that subclasses UITextField
and features a maxLength
property that can be edited in Interface Builder
Start a new project by doing the standard File → New → Project… dance to create a new Single View Application.
Open Main.storyboard, place a single text field on the view, select the text field and switch to the Attributes Inspector view (the inspector panel with the icon):
The Attributes Inspector lets you edit all sorts of text field properties, but not the maximum length…yet.
Use File → New → File… to create a new Swift File…
…and give it the name MaxLengthTextField.swift. We’ll use it for the code of a new class, MaxLengthTextField, which will contain the necessary properties and behaviors for a text field where you can specify a maximum length.
Change the contents ofMaxLengthTextField.swift to the code below:
import UIKit // 1 class MaxLengthTextField: UITextField, UITextFieldDelegate { // 2 private var characterLimit: Int? // 3 required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) delegate = self } // 4 @IBInspectable var maxLength: Int { get { guard let length = characterLimit else { return Int.max } return length } set { characterLimit = newValue } } }
Here’s what’s happening in the code above — these notes go with the numbered comments:
- In order to create a text field with the ability to set a maximum length, we’re defining a new class —
MaxLengthTextField
— as a subclass ofUITextField
, which gives it all the properties and behaviors of aUITextField
. We also specify thatMaxLengthTextField
adopts theUITextFieldDelegate
protocol, which allows us to manage changes to the content of our new text fields. We’ll need this in order to set a limit on how much text will be allowed inside the text field. characterLimit
will hold the maximum number of characters that can be entered into the text field. It’s defined as anInt?
since its value may or may not be defined, and defined as private since its value will be get and set using themaxLength
property.- In the initializer, we specify that
MaxLengthTextField
will define its ownUITextFieldDelegate
protocol methods. We’ll make use of one of these protocol methods later on to ensure that the text field doesn’t accept any more than the specified maximum number of characters. - The
@IBInspectable
attribute makes themaxLength
property editable from within Interface Builder’s Attribute Inspector.
Trying out our new MaxLengthTextField
class
With the starter code for MaxLengthTextField
done, let’s try it out. Switch to Main.storyboard and put a text field on the view. With the text field still selected, select the Identity Inspector (the one with the icon). Within the Identity Inspector’s Custom Class section, use the Class drop-down to change the text field’s class from
UITextField
to MaxLengthTextField
:
With this change, the text field is no longer an instance of UITextField
; it’s now an instance of MaxLengthTextField
. This becomes obvious when you switch to the Attributes Inspector (the inspector with the icon). Near the top of the Attributes Inspector, you’ll see that the text field has a new section of properties, Max Length Text Field, and within it, a new property called Max Length:
Note that Interface Builder did a couple of things in response to our marking the maxLength
property with the @IBInspectable
attribute:
- It created a new section of the Attributes Inspector titled Max Length Text Field, deriving its name from the
MaxLengthTextField
class, where you can edit its@IBInspectable
properties. - It created a new property field titled Max Length, which lets you edit
MaxLengthTextField
‘smaxLength
property.
You’ll want to keep the way Xcode names Attribute Inspector fields in mind when naming classes and properties that you want to be editable within Interface Builder.
You can set the Max Length property to any valid integer value. It won’t have any apparent effect if you run the app; right now, all it does is get and set the value of MaxLengthTextField
‘s private characterLimit
variable. Let’s make Max Length actually do something.
Making the maxLength
property limit the number of characters allowed in a text field
Update the code in MaxLengthTextField.swift so that it contains the following:
import UIKit class MaxLengthTextField: UITextField, UITextFieldDelegate { private var characterLimit: Int? required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) delegate = self } @IBInspectable var maxLength: Int { get { guard let length = characterLimit else { return Int.max } return length } set { characterLimit = newValue } } // 1 func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { // 2 guard string.characters.count > 0 else { return true } // 3 let currentText = textField.text ?? "" // 4 let prospectiveText = (currentText as NSString).replacingCharacters(in: range, with: string) // 5 return prospectiveText.characters.count <= maxLength } }
Here’s what’s happening in the code above — these notes go with the numbered comments:
- The actual functionality of
MaxLengthTextField
is contained withintextField(_:shouldChangeCharactersIn:replacementString:)
, one of the methods made available by adopting theUITextFieldDelegate
protocol. This method is called whenever user actions change the text field’s content, and itsBool
return value specifies if the text change should actually change place. We’ll use this method to limit the number of characters that can be entered into the text field — if user changes would cause the number of characters in the text field to exceedcharacterLimit
, it returnsfalse
; otherwise, it returnstrue
. - 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 usingguard
to filter out cases where the user’s changes are of zero length, which means that characters aren’t being added, but deleted. In this case, we don’t have to see if the user’s changes will cause the text field to exceed its set maximum number of characters. We do want the method to return true in order to allow the user’s deletions to take place. - If we’ve reached this point of the method, it means that the user has made additions to the text field. We should see if these changes would cause the text field to contain more than
characterLimit
characters. The first step in this process is getting the text currently in the text field. We use the nil coalescing operator —??
— to assign the contents of the text field if they are notnil
, or the empty string if they arenil
. - Now that we have the current text, we’ll determine the prospective text — the text that would result if the changes were accepted.
- Finally, we use the the length of the prospective text to decide whether to allow the changes or not.
If you include MaxLengthTextField.swift in any of your iOS projects, it’s pretty simple to turn ordinary text fields into ones with maxLength
properties 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!
A sample project showing Visual Studio-style text field maximum lengths in action
If you’d like to try out the code from this article, I’ve created a project named Swift 3 Text Field Magic 1 (pictured above), which shows our new MaxLengthTextField
subclass in action. It’s a quick-and-dirty single-view app that presents 4 text fields:
- A text field without a set maximum length.
- A text field with a 1-character maximum length, with the Max Length property set in Interface Builder.
- A text field with a 5-character maximum length, with the
maxLength
property set in code (in the view controller’sviewDidLoad
method). - 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!
You can download the project files for this article (61KB zipped) here.
Coming up next in this series…
In the next installment in this series, we’ll build on what we’ve made so far to create a text field that accepts only a defined set of characters.
Samsung Galaxy Note 7 recalled worldwide over battery combustion issue
In response to reports of the Galaxy Note 7 “phablet” catching fire while charging, Samsung has announced that they will recall and “voluntarily replace” users’ current devices with new ones “over the coming weeks”. Samsung reports that they are aware of 35 faulty Galaxy Note 7 devices and says that they’ve found 24 problem devices for every million sold. At the time of writing, 2.5 million Note 7s have been sold.
Here’s an ABC News report on the issue:
Samsung says that it will take two weeks to set up the recall. After that, replacement devices will be made available, with replacement dates varying by country. If you are concerned about your Galaxy Note 7, Samsung advises that you contact your nearest Samsung service center. If you purchased your Note 7 from a carrier, you should keep an eye out for announcements (T-Mobile has already issued one).
- Read Samsung’s press release: [Statement] Samsung Will Replace Current Note7 with New One
- Read Samsung is recalling the Galaxy Note 7 worldwide over battery problem (CNN)
- Read T-Mobile’s press release: T-Mobile Suspends Samsung Galaxy Note7 Sales – We’ll Take Care of Customers
The next great platform is the one that we already have
Josh Elman, a partner at Silicon Valley venture firm Greylock Partners, makes a convincing argument that the next great platform just happens to be the current great platform: mobile.
History is his guide. Just as some people say “mobile is over” now, people were saying “the web is over” a little over a decade ago — and then Web 2.0, the LAMP stack, AJAX, and social networking came along. A little over ten years before that, some people were worried that desktop computing had plateaued — and then CD-ROM multimedia and the web came along.
There are still plenty of needs that aren’t being met by mobile today, but they could be met by mobile tomorrow.
Speech is 3x faster than typing for English and Mandarin text entry on mobile devices
A recent experiment at Stanford University revealed some interesting results: entering text via speech recognition into mobile devices yielded faster input rates and lower error rates. If these results are repeated in other experiments, we may find a radical change in the way we interact with our phones in the near future.
They produced a two-minute video summarizing their findings: