Simple React Native networking

If you are doing some cross platform mobile development, and find yourself in need of doing some simple React Native networking, never fear, fetch is here.

Here is a simple example of what one of your React Native files might look like. Keep in mind that I have gutted out a bunch of stuff from this file just to keep it readable, but you should get the idea from the networking functions getMoviesFromApiAsync() and moviesResponse() below.

import React, { Component } from 'react';
import { Platform, StyleSheet, View } from 'react-native';
import Styles from './Styles'
 
export default class Home extends Component<{}> {
 
  constructor(props) {
    super(props);
  }
 
  static navigationOptions = {
    header: (
      <View style={Styles.header}>
        <View style={{flex:1.0,justifyContent:'center',alignItems:'center'}}>
          <Text style={Styles.locBtnText}> Title </Text>
        </View>
      </View>
    )
  };
 
  render() {
    return (
      <View style={Styles.container}>
        {/* Your stuff goes here */}
      </View>
    );
  }
 
  {/* Networking call done here */}
  getMoviesFromApiAsync() {
    return fetch('https://facebook.github.io/react-native/movies.json')
      .then(response => response.text())
      .then(text => this.moviesResponse(text))
      .catch((error) => {
        console.error(error);
      });
  }
 
  {/* Response comes in here */}
  moviesResponse(text) {
    this.setState({waitCursorShowing: false});
    console.log("Movies response: " + text);
  }
 
}
 
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor:'white',
    alignItems: 'center',
    justifyContent:'center'
  },
});

BTW, Happy Anniversary to 2001: A Space Odyssey, which debuted to the public 50 years ago today. Sure it is a little slow, but oh what a jump cut.

WWDC goat rodeo

I have an idea for Apple on how to avoid the whole WWDC goat rodeo in terms of the tickets lottery. There are so many developers that do not get a chance to go to the event due to seats being taken up by people who only attend the keynote.

So here’s a thought, have separate tickets for the keynote and for the rest of the event. See, I’m an idea person.

BTW, a posthumous Happy Birthday to Denton “Cy” Young, one of the greatest pitchers in the history of baseball, born this date in 1867.

Back to the future?

What kind of sorcery is going with my framework modification dates?

BTW, a posthumous Happy Birthday to Mr. Fabulous, Alan Rubin. I feel the need now to go and watch Blues Brothers for like the 500th time.

Visual Studio Community 2017 crashes when running application

If you have Visual Studio Community 2017 and it crashes when you try running an application, I have heard that you can solve the problem by making sure that the .NET Framework 4.7.1 package is installed on your Windows machine.

BTW, Happy Birthday to the Great One, Wayne Gretzky.

Advent of Code 2017

Well this year’s Advent of Code 2017 must have been easier than the past two years. Either that, or I am getting better at this software development thing, as I am actually finished with it on the final day of the challenge. Huzzah!

Please feel free to check out my Github site for all the Swift 4 goodness needed to solve the 25 challenges:

https://github.com/Wave39/AdventOfCode2017

BTW, Merry Christmas (or insert your own holiday here) to all, and here’s hoping your 2018 is the best it can be.

Background thread URL download in Swift 4

I was recently working on a project in swift, and was not able to quickly find a way to use a background thread to do a URL download in Swift 4. There were plenty of snippets and tutorials out there, but they were all for older versions of Swift. (BTW Swift, you have to stop it with these breaking changes.)

So here is what I cobbled together to download from the OpenAQ web site, which has an open API to provide air quality data.

The Swift class that does the downloading and processing of the data from the site is this class, which I called OpenAQ.swift:

//
//  OpenAQ.swift
//  openaq
//
//  Created by Brian Prescott on 11/16/17.
//  Copyright © 2017 Brian Prescott. All rights reserved.
//
 
import UIKit
 
class OpenAQResult: NSObject {
    var city: String = ""
    var count: Int = 0
    var country: String = ""
    var locations: Int = 0
}
 
protocol OpenAQDelegate: class {
    func didFinish(sender: Any)
    func didError(sender: Any)
}
 
class OpenAQ: NSObject {
 
    weak var delegate:OpenAQDelegate?
    var returnValue: [OpenAQResult] = []
 
    func readDataBackground() -> Void {
        let urlString = "https://api.openaq.org/v1/cities?limit=10000"
        guard let url = URL(string: urlString) else { return }
        URLSession.shared.dataTask(with: url) { (data, res, err) in
 
            guard let data = data else {
                return
            }
 
            do {
 
                let json = try JSONSerialization.jsonObject(with: data, options: []) as! [String: Any]
                let resultsArray = json["results"] as! NSArray
                var retval: [OpenAQResult] = []
                for x in resultsArray {
                    let dict = x as! NSDictionary
                    let res = OpenAQResult()
                    res.city = dict.value(forKey: "city") as! String
                    res.count = dict.value(forKey: "count") as! Int
                    res.country = dict.value(forKey: "country") as! String
                    res.locations = dict.value(forKey: "locations") as! Int
                    if (res.count >= 10000) {
                        retval.append(res)
                    }
                }
                self.returnValue = retval.sorted(by: { $0.count > $1.count })
                self.delegate?.didFinish(sender: self)
            } catch {
                print("An error occurred")
            }
 
        }.resume()
    }
 
}

So then to use this class, here is a template of what your main view controller (or wherever you want to use it) would look like:

class MasterViewController: UITableViewController {
 
    var detailViewController: DetailViewController? = nil
    var objects = [OpenAQResult]()
    var openAQ: OpenAQ? = nil
 
    override func viewDidLoad() {
        super.viewDidLoad()
 
        openAQ = OpenAQ()
        openAQ?.delegate = self
        openAQ?.readDataBackground()
 
        // do the rest of your initialization
    }
 
    // the rest of your class would go here
 
}
 
extension MasterViewController: OpenAQDelegate {
    func didError(sender: Any) {
        print ("An error occurred!!!")
    }
 
    func didFinish(sender: Any) {
        objects = (sender as! OpenAQ).returnValue
        if (objects.count == 0) {
            let alert = UIAlertController(title: "Error", message: "The data could not be loaded. Please establish an internet connection and press the Refresh button above.", preferredStyle: UIAlertControllerStyle.alert)
            alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
            self.present(alert, animated: true, completion: nil)
        }
 
        DispatchQueue.main.async {
            // do something here
            // for example, reload a table view
        }
    }
}

In the code above, when the didFinish method is called, the objects instance variable is retrieved from the openAQ variable, and you can then do something with the data you just retrieved.

BTW, Happy Thanksgiving to all my U.S. readers. It has been a very trying year personally and all around, but we still have so much to be thankful for.

Plain ol’ XML

So let’s say you are working on an application in the .NET sphere of influence, and you have an object that you want to turn into XML. However, you shoot it through an XmlSerializer and you think you are done.

Ugh, what’s all that cruft in the XML stream?

Well there are some options you can play with to get rid of the extra stuff and just get plain ol’ XML. Here is a code snippet, where you will pass in your own object instead of the generic Order as shown below:

public String GetPlainOldXML(Order order)
{
    var emptyNamepsaces = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty });
    var settings = new XmlWriterSettings();
    settings.OmitXmlDeclaration = true;
 
    XmlSerializer xsSubmit = new XmlSerializer(typeof(Order));
    var xmlString = "";
    using (var sww = new StringWriter())
    {
        using (XmlWriter writer = XmlWriter.Create(sww, settings))
        {
            xsSubmit.Serialize(writer, order, emptyNamepsaces);
            xmlString = sww.ToString();
        }
    }
 
    return xmlString;
}

BTW, Happy Birthday to Leslie West of Mountain fame.

Chuwi Surbook review

As I said before in my GPD Pocket review, I don’t usually do reviews, but I need a posting for September. So, here is my Chuwi Surbook review.

I have always liked the form factor of the Microsoft Surface, but certainly not the price. When I saw this on Indiegogo, while the specs were not up to Surface levels, the price was certainly enticing, and it looked like they were far enough along that I didn’t have to worry about a lengthy wait for delivery. (My Fusion Guitar finally showed up, so now I’m looking at you, Jamstack.)

The durability and build quality of this device seem good, as it has withstood lugging back and forth to work for a month or so now without incident.

The screen is 12 inches in diagonal, and the resolution is very good, on par with the retina MacBook Pro computers.

This device does have a 1.1 GHz processor, so in terms of computing power, it is not the speediest, especially since it only has 6 GB of RAM. However, so far it has performed well for me on my light and medium duty tasks. I even installed Visual Studio 2017 Community on it, and I am able to do development work on a .NET MVC site that I have been futzing around with. There is a little delay when trying to run the application, but overall not bad.

The one big beef I have with this device is that the trackpad on the keyboard cover is very finicky, which led me to disable that mouse in the Device Manager, and then I use either a Bluetooth mouse or the included pen.

Kudos to Chuwi for adding a Micro SD card slot on this device.

Rating: 4 stars out of 5

Pros:

  • Solid build quality
  • Great value for the cost

Cons:

  • Keyboard case trackpad is very tempermental

BTW, I know I missed the actual date by a couple of days, but Happy 30th Birthday to Star Trek: The Next Generation.

Totality

Well it has been over a week now since the Great American Eclipse, and I must say that despite the relative difficulty in witnessing it, it was well worth it.

We decided to make a western U.S. trip out of the eclipse, so on the morning of Monday, August 21, we found ourselves stopping in the little town of Guernsey, Wyoming. With just over 2 minutes of totality, this seemed like a good compromise between duration of totality and traffic.

So we found some street parking at the West River Park, settled in with our eclipse glasses, and were blown away when the the town slipped into the moon’s umbra. It was quite the rush.

Leaving the area was not a total disaster either, as I suspect that choosing to avoid the totality center line was a good decision. Our two hour drive back to Cheyenne only took about three hours, which is a lot better than some of the traffic jam horror stories we heard about.

We are already looking forward to April 8, 2024.

BTW, can it really be 20 years ago that Princess Diana was lost in a car crash?

Keezel review

The Keezel is another interesting technology item that I backed on Indiegogo, and so after using it for a while both at home and on the road, I thought it might just be time for a Keezel review.

The Keezel device is a VPN device that allows you to secure your wi-fi communications. After you power it up, you connect to it and then use a web browser to go into the device’s administration panel. From there, you can set up what wireless access point and VPN you want to connect to. In addition, it can function as a spare battery pack as well, powering any mobile devices that charge through a standard USB port.

Right out of the box, I had some issues trying to get the Keezel registered with my Premium activation code that was included in the box. No matter what I did, it still did not think that it was registered. After a couple of emails with Keezel support, it was working just fine. I suspect that there is some kind of issue with the Keezel software or with their back end managing the subscriptions, and that they did something manually on their side that enabled it to connect up.

Once set up, the device worked great at home. On the road, though, it did not work quite as well, but even then I suspect that it had more to do with the quality of the wi-fi on the road I was trying to connect to, than a problem with the Keezel device or software. Toward the end of my trip, the device was knocked out of commission because the wi-fi log in page that I was trying to use would not come through to the user, they would just get an error message in the browser.

Rating: 4 stars out of 5

Pros:

  • Compact and light
  • Good battery life
  • Fast response from support

Cons:

  • Can be a bit touchy
  • Location of supported VPNs does not include all locations

BTW, Happy Birthday to Clint Hurdle, manager of the Pittsburgh Pirates.