Archive for the ‘Cocoa Coding’ Category

Xcode 10.2 is Out

Tuesday, March 26th, 2019

xcode.jpg

This morning, after I updated to macOS 10.14.4, I noticed that Xcode 10.2 was out with Swift 5, and that has the new Strings, and the ABI compatibility, and a host of new things. So let's get that going, and see how it changes things. I really haven't read what is new in Swift 5 - other than the new Strings, so that will be something to read up on this morning.

What I've found in converting an ObjC project is that a few of the localizations needed to be cleaned up - Xcode did that just fine, and then it built and ran just fine. But for the Swift project, it complained about the use of index(of:) and suggested that it be changed to firstIndex(of:) - which is fine, but I don't know that anyone used to coding for very long makes that mistake - but OK... I get it.

The next one said that in this code:

  ans.append(ascii[self.index(of: c)!.encodedOffset])

needed to be changed to:

  ans.append(ascii[self.firstIndex(of: c)!.utf16Offset(in: self)])

and figuring that out took some time.

Specifically, they deprecated the encodedOffset - which they say was being misused. And then didn't really give me a replacement. I had to fiddle and search the docs for what to put in it's place. And given that this is coming off a call to self - how is it that utf16Offset() doesn't default to that?

In any case, I got that fixed, and then I refactored the code for pattern from:

  let ascii: [Character] = ["a","b","c","d","e","f","g","h","i","j","k",
                            "l","m","n","o","p","q","r","s","t","u","v",
                            "w","x","y","z"]
  var ans = ""
  for c in self {
    ans.append(ascii[self.firstIndex(of: c)!.utf16Offset(in: self)])
  }
  return ans

to:

  let ascii: [Character] = ["a","b","c","d","e","f","g","h","i","j","k",
                            "l","m","n","o","p","q","r","s","t","u","v",
                            "w","x","y","z"]
  var ans = ""
  let src = Array(self.utf8)
  for c in src {
    ans.append(ascii[src.firstIndex(of: c)!])
  }
  return ans

I just didn't like the way the encoding was being handled, and that got to be a real annoyance... so by just converting it to UTF8, and then using that array for indexing, I was able to do the same thing - and it looks a lot cleaner.

I'm less and less a fan of the speed with which they released Swift. I understand they needed to get it out in the wild, and they had to answer requests for features, but they added too many too quickly, and without the long-term consideration that they are usually known for. I mean look at ObjC... the classes changed a little, but the language was shipping product for 5 yrs, and Swift has been around for 5 yrs, and it's still not close to stable.

Part of it is also that they stuck with OOA&D, and that's got to be a killer.

Upgrading Postgres 10.3 to 11.1 Using Homebrew

Friday, February 15th, 2019

PostgreSQL.jpg

It's time to make sure that my laptop has the latest version of PostgreSQL, as I was reading that they were making big strides in the windowing functions in postgreSQL 11. And with Homebrew 2.0 out, it made sense to just write it all down again, just so that I have it for reference.

The process isn't bad... dump all the databases into one file, stop the server, update Homebrew, update postgres. This gets us to the point that we are ready to rebuild the new database:

  $ pg_dumpall > dump.sql
  $ brew services stop postgresql
  $ brew update
  $ brew upgrade postgres

Now we need to move out the old database data, create a new structure, and restart the service:

  $ cd /usr/local/var
  $ mv postgres postgres.old
  $ initdb -D /usr/local/var/postgres
  $ brew services start postgresql

You then need to go back to the directory of the first command - the one where you dumped the databases, and reload them all:

  $ psql -d postgres -f dump.sql

and at this point, everything should be back and running:

  $ psql --version
  psql (PostgreSQL) 11.1
  $ psql -l
                                      List of databases
      Name     | Owner | Encoding  |    Collate     |     Ctype      |  Access privileges
  -------------+-------+-----------+----------------+----------------+---------------------
   health      | drbob | SQL_ASCII | en_US.US-ASCII | en_US.US-ASCII |
   inventory   | drbob | SQL_ASCII | en_US.US-ASCII | en_US.US-ASCII |
   northhollow | drbob | SQL_ASCII | en_US.US-ASCII | en_US.US-ASCII |
   postgres    | drbob | SQL_ASCII | en_US.US-ASCII | en_US.US-ASCII |
   template0   | drbob | SQL_ASCII | en_US.US-ASCII | en_US.US-ASCII | =c/drbob           +
               |       |           |                |                | drbob=CTc/drbob
   template1   | drbob | SQL_ASCII | en_US.US-ASCII | en_US.US-ASCII | drbob=CTc/drbob    +
               |       |           |                |                | =c/drbob           +
               |       |           |                |                | _postgres=CTc/drbob+
               |       |           |                |                | postgres=CTc/drbob
   test        | drbob | SQL_ASCII | en_US.US-ASCII | en_US.US-ASCII |
  (7 rows)

At this point you can remove the old data:

  $ rm -rf /usr/local/var/postgres.old
  $ rm dump.sql

and everything is updated. You can then use any of the normal tools, including the Apache/PHP/Postgres that Apple makes available, and Postico - a great GUI client.

Big Download Morning

Wednesday, October 31st, 2018

Software Update

This morning there was a flurry of downloading, and while I expected iOS 12.1 because of yesterday's Apple Event, I didn't expect to see macOS 10.14.1, and then Xcode 10.1 - but in truth, the emoji updates in iOS 12.1 had to be mirrored in macOS or we'd have some very funny looking tweets.

What I found interesting was that the App Store can have updates in it, and System Preferences has updates in it - and they aren't the same, but the System Preferences appears to be able to control the downloading and installing from both sources. That's good.

In the Apple menu, there are two items - App Store..., and System Preferences... and each of these had a decoration for the updates. It's a nice touch - classy, as always from Apple.

More Fun with Xcode 10 and CryptoQuip

Wednesday, October 10th, 2018

xcode.jpg

This morning I dove back into Xcode 10 and CryptoQuip - this time fixing up the UI elements because I had the test string in the NSTextView and that was sloppy and there were no tips on the text boxes, and the hint was a pair of NSComboBoxs, and that wasn't as nice as the NSPopUpButton I'd used in the Swift version. So it was time to clean it up.

The first thing was to pull out the test string from the NSTextView and put in the tool tips on where to put what. That was simple... converting an NSComboBox to an NSPopUpButton was not as easy. I was hoping it was a simple object change, but it really had to be a remove-and-replace which wasn't horrible because the placement tools for Xcode 10 are really nice.

CryptoQuip Xcode Project

What was a little more painful was the fact that I needed to create all 26 values for the NSPopUpButton A-Z in the UI. There didn't seem to be a simple way to do it. And now that Xcode 10 has removed the Object Library from the UI, I had to find the new Library Search feature... very "Spotlight"-like, and not horrible, but it was a bit of a surprise to see it gone.

The final part was really cleaning up the code on the -decode: method. That was a mess because I was previously looking at each UI element in isolation, and that was a mistake. Also, I wasn't putting the values back... it was just a mess. So I decided to clean it up like:

- (IBAction) decode:(id)sender
{
  // get the values from the UI elements
  NSString*   cyphertext = [[self getCyphertextLine] stringValue];
  NSString*   cypher = [[self getCypherChar] titleOfSelectedItem];
  NSString*   plain = [[self getPlainChar] titleOfSelectedItem];
 
  // if there is no cyphertext, flip to the test case for testing
  if ((cyphertext == nil) || ([cyphertext length] == 0)) {
    cyphertext = @"Fict O ncc bivteclnbklzn O lcpji ukl pt vzglcddp";
    cypher = @"b";
    plain = @"t";
    // ...and feed all these back into the UI so it looks nice
    [[self getCyphertextLine] setStringValue:cyphertext];
    [[self getCypherChar] selectItemWithTitle:[cypher uppercaseString]];
    [[self getPlainChar] selectItemWithTitle:[plain uppercaseString]];
  }
 
  // now let's call the solver
  [self solve:cyphertext
        where:tolower([cypher characterAtIndex:0])
       equals:tolower([plain characterAtIndex:0])];
}

Now, we are looking at just the cypher text, and keying off that for the test case. Makes a lot more sense. Much better.

All builds and runs fine. Check it all in, and really happy with the way it all worked out. Looks a lot better.

Reading Up on CloudKit

Wednesday, September 26th, 2018

CloudKit

After I went through Swift and Xcode, I was looking for something to read, and CloudKit seemed like a really good thing to read - as I know a friend is using it for his app, and it's one of the really nice features that Apple is making available for server-side uses in the iOS and macOS apps. I'm not at all sure when I'll use it, but I really wanted to get to know it so that I can know what it's capable of, and the basic limitations it's got.

To start, it's important to see this as what might be called a very simple database, and it's probably a good idea to take Apple's cue and call them RecordSets. It really is best to think of them as Collections, as it's not really a traditional database at all, but you can mimic a lot of database activity with it. Still - Collections is the best way to think about it.

Next, they have certainly put in a lot of work to make sure app developers have the tools they need to specify these records on the Apple developer web site. It's really impressive, but then again, Apple uses CloudKit a lot - so it makes sense that you make the tools that help you make apps.

What's interesting is that they have a very logical, clear, data access pattern that covers getting just the updated records... or sending a predicate and getting all the records that match that, or paging them as needed to make the app more responsive to the user. What I find very nice about CloudKit is that for thumbnails of the images - they don't do a thing - it's up to you, the app developer, to make those, and put those in the record. That way, you control the style, image quality, etc. of the thumbnail. Very nice.

I Like that they have the batch and single operation interface, and they have really gone all-in on the NSOperation as the tool for doing all this work. If you get used to that, and good at using it you're going to be set with CloudKit. They have subclassed that to have a lot of different operations, and true to NeXT and Apple form, the names are a little strange to me now - having done a lot of functional coding over the last few years - where names are typically a lot shorter, but that's just the way NeXT has always been.

As I was watching the WWDC sessions, and reading the docs, I realized that this could not really be made a lot simpler for the general case of interacting with iCloud, but it sure was a lot more complicated than any one app would really need. I kept thinking about how to simplify this and make it into a library with simpler access patterns. Then I'd realize that it would be restrictive, and so it would only be good for a subset of all use-cases, and again Apple did the right thing, and it's complex because it's a complex system.

Still... I can bet that if I had to use it in an app, I'd have to make a Framework or something to encapsulate the use cases that I was going to be using - just because I'd need to abstract this away to make it simpler to see how the part interacted with one another. But I suppose that another point to consider is that an app isn't about a lot of complexity, and so interacting with CloudKit is probably the most complex thing an app is doing, and so it's not really surprising that this is as complex as it is.

Low down: it's impressive, and full-featured, and I think it's great that Apple made it.

MacOS 10.14 – Mojave Arrives!

Tuesday, September 25th, 2018

Apple Computers

Yesterday, around noon, I guess, macOS Mojave was released, and signified the end of a very exciting week for Apple. First it was iOS 12, and Xcode 10, then the new iPhones, then macOS Mojave. What a week!

I'm not going to use Dark Mode - it's just too hard for me to read the small text, but that's OK. I like that Apple is trying new things, and it's getting people excited about the UI again, which is always good. I do like a few of the UI changes that they added - there is now a clear distinction between the apps in the Dock, and those that are permanent members of the Dock. Nice. I also like that Safari 12 is getting more strict with the security and ad blocking. It's an entirely different world out there now - as opposed to 10 yrs ago, and I like that Safari, and Apple, feel that security and privacy is a fundamental human right.

There are tons of things under the covers, I'm sure. I've read about several, and as Xcode 10 was likely the build system, I'm guessing that there are nice performance boosts in several spots as well. All very cool stuff.

More Xcode 10 Performance Tests

Monday, September 24th, 2018

xcode.jpg

This morning I decided to take another look at the Xcode 10 performance tests on my CryptoQuip puzzle solver, but this time, looking at the Objective-C version and see if the Xcode 10 changes would make it any faster. Turns out, I'm very glad that I did.

I was getting a very odd error on the line:

int main(int argc, const char *argv[])
{
    return NSApplicationMain(argc, argv);
}

the value of argv was causing a SIGABRT - and I just had a feeling it was some setting in the old project file and I needed to clean those up - so after a little bit of updating, it compiled and ran just fine.

I then put in the timing of the call with a few lines:

- (BOOL) attemptWordBlockAttack
{
    // sort the puzzle pieces by the number of possible words they match
    [[self getPuzzlePieces] sortUsingSelector:@selector(comparePossibles:)];
    // ...now run through the standard block attack
    NSTimeInterval begin = [NSDate timeIntervalSinceReferenceDate];
    BOOL ans = [self doWordBlockAttackOnIndex:0 withLegend:[self getStartingLegend]];
    NSLog(@"%lu Solution(s) took %f msec",
        (unsigned long)[[self getSolutions] count],
        ([NSDate timeIntervalSinceReferenceDate] - begin) * 1000);
    return ans;
}

so that I'd get a similar result as the Swift version - basically, taking everything out of the time in the solution except the attack. That's as close as an apples-to-apples as I could get with the other versions.

What I found out blew me away:

CryptoQuip[87317:16056980] Loaded 25384 words from /Users/drbob/.../words
CryptoQuip[87317:16056980] Ready
CryptoQuip[87317:16056980] Solving puzzle: 'Fict O ncc bivteclnbklzn O lcpji ukl pt
                               vzglcddp' where b=t
CryptoQuip[87317:16056980] 1 Solution(s) took 0.464082 msec
CryptoQuip[87317:16056980] Solution found: 'When I see thunderstorms I reach for an
                               umbrella'

Now the times for Clojure were in the 6 msec... and Swift was about 7 msec... but I had to do a double-take on this... I had no idea Objective-C was going to be this fast! I had to compute, by hand, the number of milliseconds since the reference date - January 1, 2001 - just to make sure I was doing the math right. I was right... it was right... I checked the code several times, made sure I wasn't skipping the actual solution... and I wasn't.

Wow... Apple has really outdone themselves on this... sub-msec on the solution. Wow! I have to say this is excellent news in my book. I can live with Swift, and I know it's the future, and it's fast... but it's not this fast, and that's just amazingly cool!

What has Happened to Swift?

Thursday, June 28th, 2018

Swift

As a long-time fan of ObjC, and what NeXT and Apple have done with it, I was very interested when they released Swift 1.0 back in 2014, I was excited to see them move a little in the direction of Ruby. Everything in one file, more along the lines of a semi-scripting language, and while it wasn't complete to be sure, I was impressed that Apple was moving in this direction.

This week, I've been working on some architecture docs for work, and one of them is about the mobile platform space, and what we should be doing there to really increase the stability and speed of feature releases. Something that's been historically tough for NeXTSTEP and Apple with regards to ObjC is memory management and threading.

The days of retain/release were somewhat tough for new developers to ObjC to get right. It was really just about understanding the patterns for the use of retain and release and when to use autorelease. Once you had those down, you were pretty much golden. The run loop would pick up the instances with a retain count of zero, and didn't have to go looking for them. Memory didn't grow unless you retain-ed it and that was then pretty easy to spot with something like OmniAlloc.

Then Apple added Automatic Reference Counting and it got a little better, but we lost a few things in the mix. For example, compare-and-swap operations could not be known to have succeeded or failed by the compiler, so it could not know what to do with the retain count. I understood this, but ARC, as it was known, did a lot about removing the need for retain/release and so it got folks up to speed faster.

Losing a little functionality is something I can understand - if the overall gains are there, and there is at least some possibility of implementing similar functionality another way. This was disappointing, and Apple was clearly forcing ARC on the developers, as they had warnings about the use of retain and release.

Then I didn't pay a lot of attention to Swift 2 and 3, but I had reason to look at Swift 4 because of these architecture docs for the mobile platform. Wow. Apple has gone crazy and complex with Swift 4.

Several things have been added in 4.0 that wasn't in 1.0 - and some of them are probably quite nice. But at this point, the costs don't seem to outweigh the complexity of the language. But it certainly explains the Playgrounds as a concept - to get people writing code in a more friendly, less stressful environment.

Swift has lost the ability to use classic threading concepts like pthreads, and mutexes, and put in their place Grand Central Dispatch (GCD), which is a great idea for the kinds of "work unit" things that end up really complicating the code base when you have to do lots of different things - like most apps these days. But it shouldn't be used for little things... it's just too much overhead.

At least that's how tools should be used. You don't use a hand grenade to kill a mosquito, and you don't need Grand Central Dispatch to atomically increment an integer... or do you?

Yet that's what I was to come to learn from the docs I was reading. Apple is really pushing the concept of the main thread of the app, and that makes sense - it is the hold-over from the run-loop, and the single-threaded nature of classic Mac apps. This is a lot like the run loop of X11 apps, and a lot of the UI apps for a long time. But then why not abstract that thread from the programming model?

But there's more...

Because of the dynamic relocation of memory in iOS, there really can't be any fixed memory locations in the code. It's a cool feature, but now you have to add all the things in the language to indicate mutability and access control. They could have used this syntax to indicate which variables are to be fixed... or at least tracked carefully so that they always appear to have a stable location in the memory map of the process.

The end result is that Swift has become quite limiting in how to do things. You really have to go all in with their constructs. That would be fine if they had taken the extra steps and built in that level of abstraction. If they wanted Grand Central to play such an important role, then hide that role with some simple syntax. Make the 'jobs' that go onto the GCD queue simple and allow their specification to indicate their need for thread safety.

When I re-wrote some code from ObjC to Ruby, the project went from 2,700 lines to about 790. That's a significant savings, and makes code easier to write, maintain, and enhance. That's good stuff. But with the things that I'm seeing now in Swift 4 - I would not be surprised if the reduction to Swift wasn't at all like that for Ruby. I hadn't done the conversion at the time because Swift 1.0 didn't have the kinds of class libraries that I needed to make the conversion. Now, it probably does.

Some day I'll actually have to knuckle down and write the project in Swift and see what it turns out to be. I hope this is just a step along the way for Swift... just a snapshot of where they want to go.

Upgrading Postgres 9.3.4 to 9.4.1 Using Homebrew

Monday, April 20th, 2015

PostgreSQL.jpg

This morning I didn't have a lot going on, and I decided to upgrade my laptop from Posgres 9.3.4 to 9.4.1 as there are a few little things in 9.4 that are nice, and I've got 9.4 on my work laptop, and I figured this would be an easy upgrade - like super easy... I was mistaken.

The rules about automatic upgrades for Postgres is a bug release version change. I thought it was a minor release. So I was expecting to simply shut down the server, upgrade the packages with Homebrew, and then start it back up. The code would detect that it was the next minor version, and automatically update the data. Sadly, that's not the case. It's a big upgrade, and that means that I might as well do a complete dump/load.

Sadly, I didn't do a dump, so I'd have to live with an older version. Not a tragedy, but annoying when I'm in the middle of the upgrade process only to learn that it's not going to work. So it goes...

So here's what I had to do - in the right order to get things working. Not bad, but it's basically the instructions for a dump/load, so I'll assume we know this going in.

First, create a complete dump of the database. Assuming that all these things are installed on Mac OS X, and using Homebrew, the paths are not important - they are all fixed with Homebrew, anyway.

  $ pg_dumpall > dump_file

Next, shut down the running server, update Homebrew, and then upgrade postgres within Homebrew. Just to be safe, let's re-link the launchctl file because in this case, it has changed, and better safe than sorry.

  $ launchctl unload ~/Library/LaunchAgents/homebrew.mxcl.postgresql.plist
 
  $ brew update
 
  $ brew upgrade postgresql
  $ ln -sfv /usr/local/opt/postgresql/*.plist ~/Library/LaunchAgents

At this point I need to move the old database data to the side, and then initialize the database with the new codebase. Once that's done, we can then restart it with the re-linked launchctl file.

  $ cd /usr/local/var
  $ mv postgres postgres.old
 
  $ initdb -D /usr/local/var/postgres
 
  $ launchctl load ~/Library/LaunchAgents/homebrew.mxcl.postgresql.plist

Finally, we need to load up the entire database from the dump file we made in the first step.

  $ psql -d postgres -f /path/to/dump_file

Check and make sure that everything looks OK and then you can easily remove the old database directory:

  $ rm -rf /usr/local/var/postgres.old

That's it.

Updated to Xcode 6.3

Thursday, April 9th, 2015

xcode.jpg

This morning I was reminded that I read on Twitter last night that Xcode 6.3 was out, and along with OS X 10.10.3 and iOS 8.3, it was time to update the build tools to get the latest in Swift, as well as the libraries for the new platforms. It was a simple update right out of the App Store.

No mess... No fuss... Just better tools. Gotta love this company.