NSWindow min and max size (Swift 4)

You can force the views to keep a inferred min and max width/height by using AutoLayout, but what if you’re working with several views simultaneously? Wouldn’t it be simpler to have a window min and max width/height? 

Just add the following in your NSWindowController:

override func windowDidLoad() {

        super.windowDidLoad()

        window?.minSize = NSSize(width: 410, height: 600 )

        window?.manSize = NSSize(width: 600, height: 1200

}

 

Questions / comments? I’m at @MarcMasVi 

Marc

NSImageView Aspect Fill

Setting an image to use AspectFill in iOS is trivial, you can set it by code or directly in storyboard. 

But how do you do it in macOS? In Cocoa/App Kit there is no property for that, you may scale it , but there is no option for AspectFill (or AspectFit for that matter). So, how do we do it?

Once you find the way is quite easy actually. We’ll create a subclass of NSImageView and we’ll override the image property, then, we’ll place the image in a CALayer; and finally we’ll use this CALayer to resize it with the desired AspectFill. 

import Cocoa

 

class ImageAspectFillView: NSImageView {

 

    override var image: NSImage? {

        set {

            self.layer = CALayer()

            self.layer?.contentsGravity = kCAGravityResizeAspectFill

            self.layer?.contents = newValue

            self.wantsLayer = true

            

            super.image = newValue

        }

        

        get {

            return super.image

        }

    }

 

 

}

 

And that’s it! I hope it helped, took me quite a while to find this solution but works like a charm. Questions, comments? I’m at @MarcMasVi

 

Marc

Open links in the Background

Here’s a quick tip on how to open a URL in the background or foreground depending on a user-set preference. 

if(openInBackgroundPreferenceSet == true){ 
                 NSWorkspace.shared.open([linkToOpen], withAppBundleIdentifier: nil, options: NSWorkspace.LaunchOptions.withoutActivation, additionalEventParamDescriptor: nil, launchIdentifiers: nil)
}else{
                 NSWorkspace.shared.open(linkToOpen)
}

 

Questions / comments? I’m at @MarcMasVi 

 

 Marc

Denarius 1.6 & the slippery bug

This last couple of months I’ve been hard at work on two new projects, the first of which will be released fairly soon! But, today I wanted to write about something else: CoreData Concurrency.

Since the release of Denarius about a year ago I’ve been regularly improving the personal finance app with new features and, of course, bug fixes. However there was this one bug that kept popping up in crash logs but that I was unable to track down. I knew it had something to do with Core Data but that’s the extend of it. 

CoreData in Denarius is implemented with two Managed Object Context, one of them being the background one for complex tasks and a second one for standard operation (as explained in this post).  So, everything was supposedly working as intended. 

However, after way too many hours I saw what was going on: I was doing a change in the main thread with information computed on the background thread… So, how did I solve it? Using objectID of course, the only safe way to transfer objects between threads. 

So instead of:

mainThreadObject.attributeX = computedThreadObjectInBackgroundQueue.attributeX

Now I had (and remember this piece of code is being executed in the background):

let transactionObjectId = mainThreadObject1.objectID
let typeObjectId = computedThreadObject2InBackgroundQueue.objectID
DispatchQueue.main.async { //Here I’m calling the main thread and push the complex background computation to the right object
      (self.managedObjectContext.object(with: transactionObjectId) as! object1).attributeX = (self.managedObjectContext.object(with: typeObjectId) as! object2).attributeX

}

A bit longer, but did the trick! This improvement will ship very soon with the new Denarius 1.6 release. 

Questions / comments? I’m at @MarcMasVi 

Marc

Shoe Dog: A Memoir by the Creator of Nike

Just finished “Shoe Dog: A Memoir by the Creator of Nike” and it’s great:  well written and refreshingly honest.

Even if you’re not into business books, I believe this one is worth your time. 

Bill Gates could not have said it better in his book review:

“Shoe Dog, Phil Knight’s memoir about creating Nike, is a refreshingly honest reminder of what the path to business success really looks like. It’s a messy, perilous, and chaotic journey riddled with mistakes, endless struggles, and sacrifice. In fact, the only thing that seems inevitable in page after page of Knight’s story is that his company will end in failure.” Source

 

Marc

Get Date Day, Month or Year in Swift 3.0

Just a quick update to show how to get Date Day, Month or Year in Swift 3

//Here I’m creating the calendar instance that we will operate with:

let calendar = NSCalendar.init(calendarIdentifier: NSCalendar.Identifier.gregorian)

     

 

//Now asking the calendar what month are we in today’s date:

let currentMonthInt = (calendar?.component(NSCalendar.Unit.month, from: Date()))!

       

 

//Now asking the calendar what year are we in today’s date:

let currentYearInt = (calendar?.component(NSCalendar.Unit.year, from: Date()))!

 

Hope this proves useful.

If you would have any suggestions on how to improve reach me @MarcMasVi in Twitter. 

 Marc

Blogging about developing an app: Denarius

Roughly two years ago I started blogging about the challenges of developing a new Mac app. I decided to do so after reading Brent Simmons great series on Vesper development. I thought it was a great way to 1. structure my thoughts and 2. help the community. 

It’s been one of the most fun times I’ve had in years. The kick I get out of creating something from nothing* is not easily found anywhere else.

Also worth mentioning is the Mac community: all fellow Mac developers I engaged with were very helpful and responsive, I’m extremely thankful for that. Thank you. 

Enough rambling, about the app I’ve been -indirectly- blogging about: It’s called Denarius and it’s a Personal finance Mac app. For years I controlled my personal finances with excel; existing Mac apps had a lot to offer but they required a lot of micromanagement as well.

My goal for Denarius was simple: the app should tell you all you need to know with minimal effort.

I hope you like it, you can know all about it here. And you can get in touch with me via Twitter at @MarcMasVi

Will update you on how the app does and what I will be working on next. 

 

Marc 

* leveraging the awesome work of Apple developers who worked on all the frameworks I use. 

Simple Animations on macOS (Swift 3)

If you’ve ever coded for iOS you’ll most likely be familiar with the UIView animateWithDuration function. Wouldn’t it be great if there would be an OSX equivalent?

Well, there sure is, just type the following:

        NSAnimationContext.runAnimationGroup({_in

            //Indicate the duration of the animation

            NSAnimationContext.current().duration = 5.0 

            //What is being animated? In this example I’m making a view transparent

            someView.animator().alphaValue = 0.0 

        }, completionHandler:{ 

            //In here we add the code that should be triggered after the animation completes.

            print(“Animation completed”)

        })

 

That’s it, you’re good to go! Questions / comments? I’m at @MarcMasVi 

 

Marc