The inaugural ReactJS Tampa Bay meetup

by Joey deVilla on May 26, 2016

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

{ 0 comments }

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

{ 0 comments }

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:

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:

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:

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:

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:

“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.

{ 0 comments }

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.

{ 0 comments }

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:

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:

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. Update the code in TextFieldMaxLengths.swift to this:

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.

{ 0 comments }

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!

{ 0 comments }

putting it all together

There’ve been four articles in this series on building a simple weather iOS weather app with Swift:

  • In the first article, we introduced OpenWeatherMap, its current forecast API, and how to use that API to get weather data for a specific city, both manually and programatically.
  • In the second article, we went a little deeper into NSURLSession and the related classes that made iOS networking possible. We also took the weather data that OpenWeatherMap returned and converted it from a string containing JSON-formatted weather data into a more easily processed Swift dictionary.
  • In the third article, we gave our weather app a user interface.
  • In the fourth article, we took a little detour from the weather app in order to introduce geolocation. We wrote a simple geolocation app that outputs the device’s coordinates to the debug console.

simpleweather 5 screenshot

What our app will look like by the end of this article.

In this article, we’re going to take what we’ve learned from our little geolocation app and make some changes to our weather app so that:

  • When the app is launched, it automatically determine the user’s current location and displays the weather for that location.
  • The user can press a button marked Get weather for your current location to display the weather at his/her current location.
  • The user can also enter a city name into a text field and press a button below it marked Get weather for the city above to display the weather in that city.

Another way to use OpenWeatherMap’s “current weather” API

latitude and longitude

To get the weather for a given city using OpenWeatherMap’s “current weather” API, we’ve been using this call:

http://api.openweathermap.org/data/2.5/weather?APPID=API_KEY&q=CITY_NAME

where:

  • API_KEY is the developer’s API key for OpenWeatherMap
  • CITY_NAME is the name of the city that we want the current weather for

There’s also a way to get the weather for a given latitude and longitude. It’s done by making this call:

http://api.openweathermap.org/data/2.5/weather?APPID=API_KEY&lat=LATITUDE&lon=LONGITUDE

where:

  • API_KEY is the developer’s API key for OpenWeatherMap
  • LATITUDE is the latitude of the location that we want the current weather for
  • LONGITUDE is the longitude of the location that we want the current weather for

I’m based in Tampa, whose coordinates are 27.9506° N, 82.4572° W. That translates into:

  • A latitude of 27.9506 (positive latitudes are north of the equator, negative latitudes are south)
  • A longitude of -82.4572 (positive longitudes are east of the prime meridian in London, negative longitudes are west)

Another way of getting the current weather for Tampa from OpenWeatherMap is to make the call below.. Try pasting the URL into your browser’s address bar (using your own API key, of course):

http://api.openweathermap.org/data/2.5/weather?APPID=API_KEY&lat=27.9506&lon=-82.4572

We’re going to make some additional to our weather app so that it can do this programatically.

Updating WeatherGetter

Here’s an updated version of the WeatherGetter class, which we use to connect to OpenWeatherMap and get weather data:

We’ve made a couple of changes:

  • We’ve added two new methods:
    • getWeatherByCity is called when we want to get the weather for that city. It accepts a String containing the name of a city, which it uses to form an URL, which it then passes to getWeather.
    • getWeatherByCoordinates is called when we want to get the weather for a set of coordinates. It accepts two Doubles representing the latitude and longitude components of the coordinates, which it uses to form an URL, which it then passes to getWeather.
  • We’ve also changed an existing method, getWeather. It used to be public and accept a city as a parameter; now, it’s private and accepts an URL as a parameter. It’s now called indirectly; getWeatherByCity and getWeatherByCoordinates take city or coordinate data, convert it into an URL, and then call getWeather. Aside from this change, the rest of its code is the same.

Updating the UI

updated ui for simpleweather

We’ve added one button with the title Get weather for your current location and put it between the weather data labels and the controls for entering a city’s name. It’s assigned the following:

  • The outlet getLocationWeatherButton
  • The action getWeatherForLocationButtonTapped, which is connected to a Touch Up Inside event

Updating the view controller

We’ve also updated the view controller code:

Let’s take a closer look at the view controller code…

Buttons

Here’s the section of the code for the buttons:

The getWeatherForLocationButtonTapped method handles the case when the user presses the Get weather for your current location button, while the getWeatherForCityButtonTapped method handles the case when the user presses the Get weather for the city above button. Both methods disable both buttons when pressed by calling the setWeatherButtonStates method, and the buttons are re-enabled once either a weather report or error message has been obtained.

WeatherGetterDelegate methods

Here’s the section for the WeatherGetterDelegate methods:

The view controller adopts the WeatherGetterDelegate protocol, which has two required methods:

  • didGetWeather, which is called when the WeatherGetter instance successfully retrieves weather data from OpenWeatherMap and manages to parse its JSON data into a Swift dictionary, and
  • didNotGetWeather, which is called when WeatherGetter either fails to retrieve weather data from OpenWeatherMap or parse its JSON data into a Swift dictionary

Both methods are called from the closure provided to the data task defined in WeatherGetter‘s getWeather method. This means that they’re not being executed in the main queue. Both methods’ primary function is to make changes to the UI, which must be done in the main queue. That’s why I put the UI code in these methods into a dispatch_async block specifying that the block must be executed in the main queue.

Location-related methods

Here’s the code for the CLLocationManagerDelegate and related methods:

Most of getLocation() is concerned with ruling out cases where we can’t get the user’s location. Only the last three lines of the method deal with getting location updates from locationManager.

  • The first guard statement allows control to pass to the next line if and only if location services are enabled for the device. If location services are disabled, we display a simple “Location services are disabled on your device” alert, and getLocation() is exited.
  • The second guard statement allows control to pass to the next line if and only if the app is authorized to use location services when it is in use (i.e., its authorization status is .AuthorizedWhenInUse). A switch statement in the guard block determines the specific reason why the app isn’t authorized:
    • If the app explicitly does not have permission to use location services (i.e., its authorization status is either .Denied or .Restricted), we display a “This app is not authorized to use your location” alert, which presents the use with the option to open the Settings for this app and authorize it to use location services.
    • If the app has not explicitly been given or denied permission to use location services (i.e., its authorization status is .NotDetermined), the location manager’s requestWhenInUseAuthorization() method is called, which displays the alert asking the user if s/he wants to give the app permission to use location services.
    • The default case is the remaining authorization status, .AuthorizedAlways. There’s no way to get to this point, and I included this case only because the switch statement requires that all cases to be covered.

If control made it past the first two guard statements, it means that location services has been activated for the device and the user has given our app permission to use location services while the app is active. The following happens:

  • It sets the view controller as the location manager’s delegate, which means that it can receive and respond to location and heading updates from the location manager.
  • It requests the lowest possible location accuracy from the location manager: kCLLocationAccuracyThreeKilometers, which can pinpoint your device’s coordinates within 3 kilometers (about 1.86 miles). I’m doing this for two reasons:
    • Weather is a large-area phenomenon and weather stations are far apart, so 3-kilometer accuracy is more than plenty for our needs.
    • 3-kilometer accuracy, as a function of being the lowest-accuracy setting, is also the least power-draining.
  • In earlier versions of this app, we made a call to locationManager.startUpdatingLocation, which requested that the location manager start sending location update notifications, typically at the rate of once per second. This works, but it’s overkill for the purposes of a weather app. Instead, we’re using a new method introduced with iOS 9: requestLocation, which sends a single location notification once Core Location has determined the current location to the specified accuracy.

Once requestLocation is called, one of two methods will be called as a result:

  • locationManager(_:didUpdateLocations:) is called if the location manager managed to get the current location.
  • locationManager(_:didFailWithError:) is called if the location manager failed to get the current location.

UTTextFieldDelegate and related methods

A quick explanation of each of these methods:

  • textField(_:shouldChangeCharactersInRange:replacementString:) — This method is called whenever the contents of a text field in a view that adopts the TextFieldDelegate protocol change. We’re using this to enable the Get weather for the city above button when the “city name” text field contains any text, and disable the button when the “city name” text field is empty.
  • textFieldShouldClear(_:) — This method is called when the user taps the “clear text field” button. We use this to disable the Get weather for the city above button since pressing this button clears the “city name” text field.
  • textFieldShouldReturn(_:) — We capture this event so that pressing the Return key is like pressing the Get weather for the city above button.
  • touchesBegan(_:withEvent:) — We capture this event so that tapping on the background view dismisses the keyboard.

And finally, the utility methods…

These methods, explained:

  • showSimpleAlert(title:message:) — This method allows us to display a simple alert with a single OK button with a single line of code.
  • String.urlencoded — We use this to encode city names provided by the user into a format that can be used in the query we send to OpenWeatherMap.
  • String.trimmed — This handy utility function removes whitespace from the beginning and ending of strings.

A working weather app

sunny sky

At this point, we have a basic, working weather app. Given the name of a city or your current location from your iDevice’s location services, it displays the current weather conditions for that location. There’s still plenty of opportunities for features and improvements, some of which are:

  • Forecasts for future weather: tomorrow’s weather, the forecast for the next few days, or a long-range forecast.
  • Graphics. Yahoo!’s weather app  shows pictures of the cities that it’s giving forecasts for, and most weather apps provide pictures or pictograms that match their forecasts.
  • Sound. I’m not aware of any weather apps that make particularly good use of sound. Maybe you can make one!
  • Personality. Take a look at Carrot Weather, which has a snarky sense of humor.

Download the project files

xcode download

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

{ 0 comments }