NEW: Subscribe to Hacking with Swift+ and accelerate your learning! >>

Issue - Hacking with macOS book

Forums > macOS

I recently purchased the Hacking with macOS book and have been following along intently. I have found a few discrepancies between the book and XCode 11.1 and have sent those to Paul for future update of the book for XCode 11.1.

However, I am working on Project1: Storm Viewer and I have gotten to the part where the reader is directed to create the protocol for the SourceViewControler on page 144.

The second to last paragraph it reads As you start typing “number”, Xcode should hopefully bring up its autocompletion window and fill most of the rest in for you. This did not happen for me.

After I completed adding the method func numberOfRows() I then pressed CMD+R to run the program and I do not see the output Table View Cell in the column.

The debugger window at the bottom of the XCode window shows:

2020-04-10 17:47:58.921288-0500 Project1[64848:17732152] *** Illegal NSTableView data source (<NSScrollView: 0x100818200>). Must implement numberOfRowsInTableView: and tableView:objectValueForTableColumn:row:

2020-04-10 17:47:58.948477-0500 Project1[64848:17732152] Metal API Validation Enabled

Where did I mess up?

1      

It sounds like you accidentally set your NSTableViewDataSource to the NSScrollView instead of the SourceViewController.

   

I went back and redid the whole project up to page 144 and once again, the behavior is the same. I ensured I followed every step exactly as described in the book.

I also ran into this problem trying to follow Apple's Developer Tutorial for the Landmarks app. What the tutorial displays is not what the reader encounters, and for a newbie trying to learn XCode 11.1 and SwiftUI.

I hope Paul (@twostraws) can chime in. The Alt+Cmd+# keys are not the same in the book and XCode 11.1, which makes me wonder if something changed since the publishing of this book and XCode 11.1.

Anyway, I'm at a standstill once again. No one has written an updated book for XCode 11.1 that I have found. If anyone has a suggestion on a good book or resource to learn XCode 11.1 and macOS app development, I would appreciate it.

   

Hacking with Swift is sponsored by NSSpain

SPONSORED Announcing NSSpain 2020: Remote Edition! An online, continuous conference for iOS developers. We’ll start on Thursday and finish on Friday, with talks, activities, and lots of fun for 36 hours, non-stop. Sound good? Join us!

Find out more

Sponsor Hacking with Swift and reach the world's largest Swift community!

I generally find the quickest way to fix these things early on in a book like this is to download the source, make sure it runs, then compare to what I have coded. Why not take a look at project 1 at https://github.com/twostraws/macOS to see if you can spot the difference? It's also a sanity check that the project is going to run in your environment with your version of XCode.

Like you, I'm struggling to find any resources for learning MacOS programming...

Also worth noting, there is a course on Udemy for this book. I believe its in the process of being updated at the moment, but it might be worth a look as a companion to the book.

   

That exact same error is what I get if I take my own working Project1, break the existing dataSource connection to SourceViewController and rehook it up to the scroll view instead.

2020-04-11 02:20:47.313496-0700 Project1[12370:676797] *** Illegal NSTableView data source (<NSScrollView: 0x101037800>).  Must implement numberOfRowsInTableView: and tableView:objectValueForTableColumn:row:
2020-04-11 02:20:47.351156-0700 Project1[12370:676797] Metal API Validation Enabled

You could always upload your project to your github account and ask us to check it out.

Check the connections inpector for your table view. What does it show for dataSource? connections inspector connections_inspector_2

   

@twostraws  Site Admin

@tcarroll2 The next update removes the Alt+Cmd mentions entirely – Apple keep changing them, and it's hard to spot.

1      

Thanks @roosterboy! I don't know how it happened, but yes, even the second time around and following the directions I had it connected to the scroller. I tried using github (I have an account), but now it's giving me all kinds of trouble and I can't create the repository even after following tutorials. Hell, I can't even get the github desktop app to create a repository... Sheesh. Seems I can't catch a break...

Thanks @sabarnett - I loaded the code from the book and it had errors right off the bat, but not my error. Anyway, I dug around and fixed the errors and it runs with several warnings.

Thanks @twostraws. Looking forward to the book being updated for XCode 11.1.

So, I fixed the delegate and datasource issue, but when I run the code as it sits on page 144 I do not get the output as displayed on page 145. I just get two empty panes.

   

I finally got the GitHub repository thing to work with XCode 11.1. It still gives me an error about "The remote repository rejected commits - Make sure you have permission to push to the remote repository and try again.". However, the commits are being applied on GitHub. I guess it's something Apple will need to fix in an update.

My repository is under tcarroll2. I will be keeping it up to date for each project I am doing in the book. Thanks for the tip!

   

So now I am back to not seeing on my display according to what the book is showing.

For example, on pages 154 and then 155 it directs the reader to click on the Image View in the Detail View Controller and then press Alt+CMD+5 (which is actually Alt+CMD+6 in XCode 11.1) to change the Content Compression Resistance Priority values. However, I am not seeing those settings when I do that. Please see the attached image. Is there a setting somewhere that I changed? I saw those properties when I resized the TableView, but I do not see them here.

screenshot

   

You don't have any constraints set on the ImageView, so the content hugging/compression stuff won't appear in the inspector. There's a part earlier in the chapter (don't know the exact page) where you are instructed to select the DetailViewController and set constraints using the menu Editor > Resolve Auto Layout Issues > Reset to Suggested Constraints.

   

Thank you @roosterboy! I think I figured it out. I've wrapped up Project1 lesson and it works nicely.

I'm now on Project2. I have gotten to page 168 and 169.

On page 168 the reader is instructed to create the tableView method.

func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
        guard let vw = tableView.makeView(withIdentifier: tableColumn!.identifier, owner: self) as? NSTableCellView else {
              return nil
        }

        if tableColumn?.title == "Guess" {
              // this is the "Guess" column; show a previous guess
              vw.textField?.stringValue = guesses[row]
        } else {
             // this is the "Result" column; call our new method
             vw.textField?.stringValue = result(for: guesses[row])
        }
        return vw
}

At the beginning of page 169 where the reader is instructed to "add this method now."

func tableView(_ tableView: NSTableView, shouldSelectRow row: Int) -> Bool {
      return false
}

This struck me as odd, because the tableView method was created on page 168, so why would I add another tableView method? I decided to look at the code provided in the companion project files I downloaded from giutHub and the shouldSelectRow method is not anywhere in the ViewController.swift file.

I really appreciate your help! I hope to be able to repay you someday. :)

Tom

   

@twostraws  Site Admin

On page 168 the reader is instructed to create the tableView method.

Not quite – this isn't Java or C#, it's Swift, and you created a method called tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int), not tableView(). Apple frequently differentiates methods based on the parameters they accept, so it's possible to have many methods that a developer from another language might think are the same – in this case tableView().

   

Grrrr... This is making my head hurt! Okay, thanks!

P.S. I removed the error above. After further comparison of my Main.storyboard and the companion project2 Main.storyboard file I see where I had created an extra outlet.

   

@twostraws  Site Admin

Yeah, I remember finding the method naming odd when I first learned Objective-C! As for the storyboard error: it's an easy one to make, and at least you figured it out 👍

   

So I completed Project2 and I'm now on Project3 (gitHub) and I just completed dragging the share button to the First Responder (page 190). When I built and ran the app I did not get the error shown in the book on page 191. However, when I clicked the Airdrop button and then clicked Cancel this error appeared in the log:

Project3[80238:20414174] [Framework] viewServiceDidTerminateWithError Error Domain=com.apple.ViewBridge Code=18 "(null)" UserInfo={com.apple.ViewBridge.error.description=NSViewBridgeCanceledError}

Tom

   

In addition to the above errors I reported seeing in Project3, I am now working in Project4 and I got to the point of Adding the ATS to the info.plist file on page 213. However, I noticed I was getting this error:

Project4-tc[89354:20622873] [Process] kill() returned unexpected error 1

So, I decided to load up the project from the resource files and it too is giving me the same error:

Project4[89077:20616536] [Process] kill() returned unexpected error 1

(note, "Project#-tc" denotes my code and "Project#" denotes the example code from the resource files)

   

I just did some reading in the Apple Developer forums about this very issue. Someone posted that this error is gone in XCode 11.4, so I'm now downloading to upgrade from 11.1.

Will report back after the upgrade is done.

   

The upgrade didn't fix the error. It is logging the error for every movement of the mouse, button press, or keypress. Weird. The only thing new is the Webkit in Project4.

   

I absolutely could be entirely, completely wrong about this, but re: this error:

Project3[80238:20414174] [Framework] viewServiceDidTerminateWithError Error Domain=com.apple.ViewBridge Code=18 "(null)" UserInfo={com.apple.ViewBridge.error.description=NSViewBridgeCanceledError}

My gut feeling is that it's perhaps not a big deal. I'm thinking it's maybe like how AppleScript returns error code -128 when a user cancels something (e.g. a display dialog command). Internally, the sharing service in macOS traps on that particular error but it doesn't mean anything at the higher level of code we are writing at.

Note that it's clearly not an error that will kill your app, as it keeps on running and you can even select other share services—or even the same one again—without any issue.

But, again, I could be completely wrong about it.

   

The latested update to Catalina 10.15.4 and XCode 11.4.1 has eliminated the Process Kill issue.

   

I just finished Project8 - I think I'm starting to understand the concepts a little better having never written anything in XCode/Swift/Objective-C.

After making the changes for the dark/light mode I ran the code and then went over to System Preferences and changed my desktop theme from Dynamic to Light then to Dark back to Light several times and the Project 8 screen never changed modes. I also ran the code from the Resource files and it behaves the same way.

I am now running XCode 11.4.1 on macOS Catalina 10.15.14.

Is there something different with the newer version of XCode and Catalina than when the book was written?

   

Beginning to work on Project 10. Looks like DarkSky is no longer offering an API because Apple bought them.

I'll see if there is another free weather service API I can use and try to adapt it to Project 10.

   

I used OpenWeatherMap.

   

@roosterboy, I decided to give that a try as well, but I am struggling with how to read the JSON data. Particularly the weather.description field.

How are you reading that data? Do you have your projects posted to github?

I'm trying to use this code:

func updateDisplay() {
        guard let feed = feed else { return }
        var text = "Error"
        switch displayMode {
            case 0:
                // summary text
                print ("case 0")
                if let summary = feed["weather"]["main"]["description"].string {
                    text = summary
                }
            case 1:
                print ("case 1")
                // Show current temperature
                if let temperature = feed["main"]["temp"].int {
                    text = "Temp: \(temperature)°"
                }
            case 2:
                print ("case 2")
                // Show wind speed and direction as well as gusts
                text = "Winds: "
                if let windDir = feed["wind"] ["deg"].int {
                    switch windDir {
                        case 0..<12:
                            text += "N"
                        case 12..<34:
                            text += "NNE"
                        case 34..<56:
                            text += "NE"
                        case 56..<79:
                            text += "ENE"
                        case 79..<101:
                            text += "E"
                        case 101..<124:
                            text += "ESE"
                        case 124..<146:
                            text += "SE"
                        case 146..<169:
                            text += "SSE"
                        case 169..<191:
                            text += "S"
                        case 191..<214:
                            text += "SSW"
                        case 214..<236:
                            text += "SW"
                        case 236..<259:
                            text += "WSW"
                        case 259..<281:
                            text += "W"
                        case 281..<304:
                            text += "WNW"
                        case 304..<326:
                            text += "NW"
                        case 326..<349:
                            text += "NNW"
                        case 349..<361:
                            text += "N"
                        default:
                            text += ""
                    }
                    if let wind = feed["wind"] ["speed"].double {
                        text += " @ \(wind)"
                    }
                }
            case 3:
                print ("case 3")
                // Show cloud cover
                if let cloud = feed["clouds"]["all"].int {
                    text = "Cloud: \(cloud)%"
                }
            default:
                // This should not be reached
                break
        }
        statusItem.button?.title = text
    }

   

I just figured it out! I had to refer to the array position.

I am now using:

if let summary = feed["weather"][0]["description"].string {
    text = summary
}

   

I have the same problem as OP. It seems the issue is as descirbed above with the seques. However, I can't see how to change the datasource and delegate to the Source View Controler? How is this done?

Thanks

   

Ok, I see how to change the Seques to Source View Controller, but I still don't see the rows?

   

The easiest way is using the Document Outline in Interface Builder. Hold down the Command key and drag from your TableView to the SourceViewController. Like so...

TableView connections

   

Ok, got it working as expected. The Seques was the problem as well as coding error the following:

func numberOfRows(in tableView: NSTableView) -> Int {
        return 100

   

Hacking with Swift is sponsored by NSSpain

SPONSORED Announcing NSSpain 2020: Remote Edition! An online, continuous conference for iOS developers. We’ll start on Thursday and finish on Friday, with talks, activities, and lots of fun for 36 hours, non-stop. Sound good? Join us!

Find out more

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

Not logged in

Log in
 

Link copied to your pasteboard.