Swift app crashes with dyld Library not loaded message

So you are humming along on your new Swift app, and all of a sudden, when you bring in a framework revision or try to deploy to a device, you suddenly start getting dyld: Library not loaded messages when the app tries to launch.

Most likely, the reason for this is that the setting for embedding the Swift standard libraries is turned off, and the app for some reason needs them. The fix is easy enough, just go into your build settings for your app and look for “Always Embed Standard Swift Libraries”. Turn this setting on for your app’s target, clean, and then try to run again.

BTW, Happy 20th Anniversary to the iMac, which was announced to the world by former Apple CEO Steve Jobs on this date in 1998. I have had a few iMacs through the years, and they are great machines.

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?