Swift 4.2 has introduced a native random number API in the standard library, making it cross platform.
Read more in the great article from Ole Begemann, worth a read.
Marc
by Marc Maset
Swift 4.2 has introduced a native random number API in the standard library, making it cross platform.
Read more in the great article from Ole Begemann, worth a read.
Marc
I wanted a simple function to resize an image to a desired height, while keeping proportions. Here’s what I came up with (based on Marco implementation):
extension NSImage {
func resizedImageTo(sourceImage: NSImage, newSize: NSSize) -> NSImage?{
if sourceImage.isValid == false {
return nil
}
let representation = NSBitmapImageRep(bitmapDataPlanes: nil, pixelsWide: Int(newSize.width), pixelsHigh: Int(newSize.height), bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, isPlanar: false, colorSpaceName: .calibratedRGB, bytesPerRow: 0, bitsPerPixel: 0)
representation?.size = newSize
NSGraphicsContext.saveGraphicsState()
NSGraphicsContext.current = NSGraphicsContext.init(bitmapImageRep: representation!)
sourceImage.draw(in: NSRect(x: 0, y: 0, width: newSize.width, height: newSize.height), from: NSZeroRect, operation: .copy, fraction: 1.0)
NSGraphicsContext.restoreGraphicsState()
let newImage = NSImage(size: newSize)
newImage.addRepresentation(representation!)
return newImage
}
}
Questions / comments / suggestions? I’m at @MarcMasVi
Marc
Updated after I discovered the great implementation Marco Arment suggested.
Subclass your NSWindow Controller, then in Window Did Load add the following two lines:
//Signature Color
window?.titlebarAppearsTransparent = true
window?.backgroundColor = NSColor.blue
That’s it, here’s the result you’ll get:
Comments / questions? I’m at @MarcMasVi
Marc
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
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
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
Extremely good article explaining why Google Maps is ahead on many areas ahead of Apple maps.
Worth your time: link
Marc
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
Great article from Marco Arment on the news about the “death” of the MP3 format.
Worth a read: https://marco.org/2017/05/15/mp3-isnt-dead
Marc
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