2048 in swift playground

I composed a 2048 game with less than 400 lines of code in swift playground a couple of months ago. I just wanted to see how serious Swift Playground for iOS 10 could be. I wrote most of the code in a coffee bar with my iPad Pro. Dash for iPad was my best friend especially when I did not have Xcode along with me. It reminded me when I was in my teenage and typed lines of BASIC into my Apple II clone just to play Snake.

Now Swift Playground has been officially released with iOS 10 and I just updated my 2048 to the latest version of Swift 3.0. If you like, you can check it out and have some fun with numbers.

NSTextField’s attributedString and truncating

I have a NSTextField in a table cell view. Since it can be to long to show, I set the line break as Truncate Middle in interface builder. But no matter how I tried, the truncating just did not work.

After some investigation, I found the problem is that I set the ‘’’attributed string’’’ explicitly and it overrides the line break setting by interface builder. I have to set it when I made up the attributed string.

let paragraph = NSMutableParagraphStyle()
paragraph.lineBreakMode = .ByTruncatingMiddle

let attributes = [NSParagraphStyleAttributeName:paragraph]

attributedString.addAttributes(attributes, range:  range )

It is pretty obvious when you know the problem. Of course the setting of line break in interface building is overridden by the attributedString. It’s just the same as the the setting of text color, background color and so on. The line break setting is under Control section. I think that’s why I was confused in the first place.

Layout NSCollectionView with your own NSCollectionViewLayout

First, subclass NSCollectionViewLayout:

class LYExpandableLayout: NSCollectionViewLayout {
}

Tell your collection view to use the layout:

self.collectionView.collectionViewLayout = LYExpandableLayout()

No, it’s not done yet. There are several methods you need to implement in your layout class.

Override collectionViewContentSize and return the calculated content size of the collection view according to the collection items in it.

override var collectionViewContentSize: NSSize {
	
}

Tell if you want to invalidate layout when the bounds change. In most time, just return true here.

override func shouldInvalidateLayoutForBoundsChange(newBounds: NSRect) -> Bool {
    return true
}

Return a selected array of NSCollectionViewLayoutAttributes of item views according to the rect. Ideally, we figure out which item views are in the rect and only return the necessary NSCollectionViewLayoutAttributes of these item views. You can of course return the NSCollectionViewLayoutAttributes of all your item views if the performance won’t be hurt badly by this way.

override func layoutAttributesForElementsInRect(rect: NSRect) -> [NSCollectionViewLayoutAttributes] {
    
}

Here’s the place to calculate the layout attributes. There are several attributes. If you want to control the position, frame should be the one to set. If the items overlaps, you may want to set the zIndex as well.

override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> NSCollectionViewLayoutAttributes? {
    
}

Here’s an example of a customized NSCollectionViewLayout. It layouts a group of fixed sized item views with spacings. When an item is clicked, the following rows of items move downward to make a space. You can fill the space with a view to show detailed information of the item just like the album view in iTunes. download the example project